编程思想 之「初始化与清理」

来源:互联网 发布:linux ntp命令 编辑:程序博客网 时间:2024/05/29 07:08

温馨提示:本系列博文(含示例代码)已经同步到 GitHub,地址为「java-skills」,欢迎感兴趣的童鞋StarFork,纠错。

与其他语言相比,Java 的一大特点就是其自动的初始化与清理功能。对于基本数据类型的全局变量,Java 自动将其初始化为对应的默认值,具体可以参考「对象漫谈」中的内容;对于对象,我们可以通过构造方法对其进行初始化;对于清理操作,Java 提供了垃圾回收机制,其可以帮我们自动清理不再使用的对象,释放资源。

构造方法

构造方法是一种特殊的方法,它是一个与类同名且没有返回值类型的方法。对象的创建就是通过构造方法来完成,其功能主要是完成对象的初始化。当类实例化一个对象时会自动调用构造方法。构造方法和其他方法一样也可以重载。在 Java 中,任何变量在被使用前都必须先设置初值,构造方法就是专门为类的成员变量赋初值的方法。构造方法的特殊性主要反映在如下几个方面:

  • 构造方法的作用主要有两个,分别为构造出来一个类的实例和对构造出来的类的实例(对象)进行初始化;
  • 构造方法的名字必须与定义他的类名完全相同,没有返回类型,甚至连 void 也没有;
  • 主要完成对象的初始化工作,构造方法的调用是在创建一个对象时使用 new 操作完成的;
  • 类中必定有构造方法,若不写,系统自动添加无参构造方法;
  • 接口不允许被实例化,因此接口中没有构造方法;
  • 不能被staticfinalsynchronizedabstractnative修饰;
  • 构造方法在初始化对象时自动执行,一般不能显式地直接调用;
  • 当同一个类存在多个构造方法时,java 编译系统会自动按照初始化时最后面括号的参数个数以及参数类型来自动的一一对应,完成构造函数的调用;
  • 构造方法分为两种,分别为无参的构造方法和有参的构造方法;
  • 构造方法可以被重载,没有参数的构造方法称为默认构造方法,与一般的方法一样,构造方法可以进行任何活动,但是经常将他设计为进行各种初始化活动,比如初始化对象的属性。  

我们也可以通过构造代码块给对象进行初始化,对象一建立构造代码块就执行,而且优先于构造函数执行。构造代码块和构造函数的区别在于构造代码块是给所有不同对象的共性进行统一初始化,构造函数则是给对应的对象进行初始化。

构造方法是一个与类同名的方法,对象的创建就是通过构造方法来完成的,构造方法有两个特点:一是没有返回值;二是与类同名。如果在类中没有定义任何(无参或者有参)构造方法时,编译器会在该类中自动创建一个无参的构造方法,也就是我们常说的默认构造方法。

此外,还有一点需要特别注意:如果类中定义了构造方法且都不是无参的,那么编译器也不会自动创建无参的构造方法,而是根据参数个数和类型,按顺序进行匹配,直到找到对应的构造方法;当我们调用了无参的构造方法实例化对象时,编译器就会报错啦,因为现在全是有参的构造方法,没有无参的构造方法。

在 GitHub 的项目「java-skills」中,提供了测试代码,感谢兴趣的同学可以自行下载体验。

方法重载与 this 关键字

在「对象漫谈」中,我们曾说过,方法名和参数列表构成了「方法签名」,它能够唯一的标识出一个具体的方法。方法重载,是指方法名相同,而参数个数不同、参数类型不同或者参数个数和参数类型都不同。实际上,参数顺序不同也可以区分两个方法,但是建议不要这么做,因此这会让代码难以维护。例如,

package com.hit.chapter5;/** * author:Charies Gavin * date:2017/12/22,21:04 * https:github.com/guobinhit * description:测试方法重载 */public class Overload {    public static void main(String[] args) {        introduce(18, "Charies");        introduce("Charies", 18);    }    public static void introduce(int age, String name) {        System.out.println("My name is " + name + ", I'm " + age + " old!");    }    public static void introduce(String name, int age) {        System.out.println("My name is " + name + ", I'm " + age + " old!");    }}

如上述代码所示,我们通过声明不同的参数顺序,区分了重载方法。But,我们不能通过方法的返回值来区分重载方法

此外,如果传入的数据类型(实际参数类型)小于方法中声明的形式参数类型,实际参数类型就会被提升,如声明int类型、传入short类型,则short类型会自动被提升为int类型。如果传入的实际参数类型较大,就会通过类型转换来执行窄化转换,如声明int类型、传入double类型,则double类型会自动窄化为int类型。

对于同一个类型的多个对象,编译器是如何让它们能够正确调用各自的方法呢?例如,

package com.hit.chapter5;/** * author:Charies Gavin * date:2017/12/25,9:07 * https:github.com/guobinhit * description:测试 this 关键字 */public class MottoHIT {    public static void main(String[] args) {        Hiter hiter_1 = new Hiter();        Hiter hiter_2 = new Hiter();        hiter_1.sayMotto("Zora");        hiter_2.sayMotto("Charies");    }}class Hiter {    public void sayMotto(String name) {        System.out.println(name + ": 规格严格,功夫到家");    }}

saymotto

为了能够让对象调用正确的方法,编译器会“偷偷”的将“所操作对象的引用”当做第一个参数传递给调用的方法,例如上述的调用实际上会变为:

Hiter.sayMotto(hiter_1, "Zora");Hiter.sayMotto(hiter_2, "Charies");

上面的格式为编译器内部的表示形式,我们并不能这样书写代码,也编译不过。为此,Java 提供了一个关键字thisthis只能在方法的内部调用,表示“调用方法的那个对象”的引用


———— ☆☆☆ —— 返回 -> 那些年,关于 Java 的那些事儿 <- 目录 —— ☆☆☆ ————

原创粉丝点击