think in java 第四章 初始化和清除 第一部分

think in java 第四章的学习

构建器初始化,方法过载:如何区分,主类型过载,不能返回值过载,默认构建器

 

第四章:初始化和清除

“初始化”和“清除”是这些安全问题的其中两个。许多C程序的错误都是由于程序员忘记初始化一个变量造成的。对于现成的库,若用户不知道如何初始化库的一个组件,就往往会出现这一类的错误。

清除是另一个特殊的问题,因为用完一个元素后,由于不再关心,所以很容易把它忘记。这样一来,那个元素占用的资源会一直保留下去,极易产生资源(主要是内存)用尽的后果。

C++为我们引入了“构建器”的概念。这是一种特殊的方法,在一个对象创建之后自动调用。Java也沿用了这个概念,但新增了自己的“垃圾收集器”,能在资源不再需要的时候自动释放它们。本章将讨论初始化和清除的问题,以及Java如何提供它们的支持。

1.用构建器自动初始化

对于方法的创建,可将其想象成为自己写的每个类都调用一次initialize()。这个名字提醒我们在使用对象之前,应首先进行这样的调用。但不幸的是,这也意味着用户必须记住调用方法。

在Java中,由于提供了名为“构建器”的一种特殊方法,所以类的设计者可担保每个对象都会得到正确的初始化。若某个类有一个构建器,那么在创建对象时,Java会自动调用那个构建器——甚至在用户毫不知觉的情况下。所以说这是可以担保的!

一个简单的构造器如下:

现在,一旦创建一个test对象,就会分配相应的存储空间,并调用构建器。这样可保证在我们经手之前,对象得到正确的初始化。
请注意所有方法首字母小写的编码规则并不适用于构建器。这是由于构建器的名字必须与类名完全相同!
构建器有助于消除大量涉及类的问题,并使代码更易阅读。例如在前述的代码段中,我们并未看到对initialize()方法的明确调用——那些方法在概念上独立于定义内容。在Java中,定义和初始化属于统一的概念——两者缺一不可。
构建器属于一种较特殊的方法类型,因为它没有返回值。这与void返回值存在着明显的区别。对于void返回值,尽管方法本身不会自动返回什么,但仍然可以让它返回另一些东西。构建器则不同,它不仅什么也不会自动返回,而且根本不能有任何选择。若存在一个返回值,而且假设我们可以自行选择返回内容,那么编译器多少要知道如何对那个返回值作什么样的处理。

我的理解:

构建器有助于消除大量涉及类的问题,并使代码更易阅读,便于完成初始化等操作,并不用特别使用initialize()方法进行初始化。一个类只能有一个对应的相同名称的构造器。构造器是特殊的方法,没有返回值。

如果使用构建器,有如下注意点:

(1) 在采取其他任何操作之前,为对象分配的存储空间初始化成二进制零.(这样的话,在父类构造器里面调用父类的方法,如果这个方法在子类里面被重写,那么调用的就是子类的这个方法。但是,此时刻子类还没有初始化,只是被初始化了全部是0,这样就会导致不可控。如果一定要调用方法,就调用private或者final的方法,因为这样的方法不可以被子类重写。)

(2) 调用基础类(父类)构建器,一直到最底层的父类Object类。原因是,在构建子类的时候,必须保证父类已经构建完成,不然子类在构造函数中使用父类的public或者protected属性或者方法的时候,无法保证稳定正确。

(3) 按声明顺序调用成员初始化模块。(在类本身里面,也是需要先初始化属性,然后调用构造器。因为,构造器也会可能使用类本身的属性)

(4) 调用衍生构建器的主体。(最后一步,才是调用自身的构造函数)

2.方法过载

大多数程序设计语言(特别是C)要求我们为每个函数都设定一个独一无二的标识符。所以绝对不能用一个名为print()的函数来显示整数,再用另一个print()显示浮点数——每个函数都要求具备唯一的名字。
在Java里,另一项因素强迫方法名出现过载情况:构建器。由于构建器的名字由类名决定,所以只能有一个构建器名称。但假若我们想用多种方式创建一个对象呢?例如,假设我们想创建一个类,令其用标准方式进行初始化,另外从文件里读取信息来初始化。此时,我们需要两个构建器,一个没有自变量(默认构建器),另一个将字串作为自变量——用于初始化对象的那个文件的名字。由于都是构建器,所以它们必须有相同的名字,亦即类名。所以为了让相同的方法名伴随不同的自变量类型使用,“方法过载”是非常关键的一项措施。同时,尽管方法过载是构建器必需的,但它亦可应用于其他任何方法,且用法非常方便。

简单来说,就是方法重载

我的理解:

这个应该就是我之前所理解的方法重载,可以允许同名方法。

(1)java是如何区分两个/多个同名方法的呢?

答案是通过不同的自变量列表,也就是不同的参数列表。

比如说,public void test(String a)是不可以和public void test(String b)共存的,因为参数列表同为String。但是如果是public void test(int a,String b)就可以了。参数列表的不同顺序也是可以区分的。public void test(int a,String b)就可以和public void test(String b,int a)共存。

(2)主类型过载

这个是基本的主类型之间相互转化的问题。什么int转string,string转int之类的。

我的理解:

大概知道有这回事,但是使用起来的时候很少遇到这个问题,感觉不值得特别注意…

(3)不能返回值过载

这个是区分int test(){}和string test(){}的问题。我们通过类名和参数列表来区分方法,为什么不能通过返回值来区分呢?int test(){}和string test(){}的返回值不一样,为什么不能区分呢?

我的理解:

因为这两个方法的返回值是不一样的,所以实际上java可以根据返回的效果来进行区分。比如说int x = test(),string y = test(),因为返回值不同,java可以区分具体调用的是哪个方法。但是会有如下的情况,比如直接调用test(),或者syso(test()),那么java怎么知道他要去调用哪个方法呢?

因为会有这样的风险,所以java干脆就不支持返回值过载了。一旦出现这种情况,在编译时就会报错。

(4)默认构建器

正如早先指出的那样,默认构建器是没有自变量的。它们的作用是创建一个“空对象”。若创建一个没有构建器的类,则编译程序会帮我们自动创建一个默认构建器。

这个已经有构造器,就不会生成了。

new test(String.valueOf(i))的作用是新建一个对象,并调用默认构建器——即使尚未明确定义一个象这样的构建器。若没有它,就没有方法可以调用,无法构建我们的对象。然而,如果已经定义了一个构建器(无论是否有自变量),编译程序都不会帮我们自动合成一个。

我的理解:

任何类都要有构造器,如果你自己没有定义,java会自动帮你定义一个默认的构建器。

6.总结

这次的内容我用得都相对比较少…希望能多多理解这些特性的好处。

发表评论

电子邮件地址不会被公开。 必填项已用*标注