java的构造器详解



构造器是一个特殊的方法,用于创建对象的实例。java类必须包含一个或更多的构造器。
构造器最大用途是在创建对象时执行初始化
构造器会返回所创建对象的实例,所以不需要显式声明返回值,也不需要用return显式给出返回值(但是构造器可以使用return; 这行语句结束构造器的代码继续运行,return;不提供任何返回值,只是结束程序)。



java自动提供构造器

因为任何类必须包含至少一个构造器,如果构建类时没有显式的提供构造器,java会自动为这个类提供一个无参数的默认构造器,这个构造器什么都不会做
但是,如果构建类时已经显式提供了构造器,那系统不会自动提供这个默认构造器,如果需要无参构造器,必须程序员自己显式提供。



构造器与对象的关系

构造器负责创建对象的实例,但构造器并不是完全负责对象的创建工作
实际上,静态初始化块,类变量指定默认值,初始化块,实例变量指定默认值这部分的代码都是在构造器的代码之前执行。在构造器执行之前,系统已经为对象分配内存空间,并对成员变量进行初始化(可能是默认初始化,也可能是显式初始化)了。此时对象就已经存在了,只是外界没办法访问。等构造器部分的代码执行后,构造器会返回对象的引用,此时外界才可以访问该对象。



构造器重载

很多类会提供多种初始化的方式,与之对应,就需要多个重载的构造器。

重载的构造器形参列表不同,初始化对象时,会根据传入实参去匹配对应的重载构造器,就可以执行所需要的初始化方式。

而且,在构造器的内部,可以通过this(形参列表)的形式,放到某个构造器的第一行,可以跳转到另一个构造器,也就是可以让构造器B辅助构造器A执行对象初始化。



子类构造器和父类构造器

在运行子类构造器之前,一定会先运行父类构造器,也就是说,第一个运行的构造器一定是最顶层父类Object的构造器。
子类运行父类构造器并不是为了创建父类,而是为了通过父类构造器,初始化父类已有的实例变量,因为这些变量也会被子类继承。



构造器的运行顺序

构造器一般会通过new关键字进入内部,但new一个对象时,构造器并不是最开始运行的。

构造器是与对象相关的,但第一次new某个类的对象,一定是先加载类本身。所以会先根据先后顺序先运行顶层父类的类变量指定默认值和类初始化块,次顶层父类的类变量设定默认值和类初始化块,一直到最底层子类的类变量设定默认值和类初始化块。

等类相关的初始化代码运行完毕后,再从最顶层父类开始执行对象初始化代码类相关的初始化只会进行一次,之后创建对象只会执行对象相关初始化代码。

对象初始化代码会根据先后顺序先执行实例变量指定默认值和非静态初始化块,这两者一定都先于构造器执行。等父类构造器全部运行完毕(可能有重载构造器的调用),再运行子类的初始化代码,直到子类最后一个构造器运行完毕。

new一个子类对象时,根据参数类型选择匹配的构造器,会先进入其内部第一行代码,但之后会不断地在自身重载构造器或者父类构造器中跳转,等那些代码都运行完毕后,最后才会执行最先进入的构造器的代码逻辑。
也就是说,new一个对象时,最先进入的构造器的代码,实际上是最后运行的



抽象类与构造器

抽象类只是不能通过构造器创建实例,但抽象类本身拥有构造器。抽象类的构造器用于被子类调用,子类在初始化时,需要借助抽象父类构造器辅助完成初始化。



接口与构造器

接口不能有构造器。接口是定义一套规则,它和抽象类一样,不能创建自身实例。而且它的成员变量都是静态常量,都在定义同时显示初始化。所以接口根本不需要构造器对自身的实例变量完成初始化,所以接口就没有拥有构造器的必要。



单例类

一般情况下,构造器的访问权限都是public,这样可以让外界创建该类的对象。
但是,有时候,我们只允许创建该类的一个对象。比如系统的窗口管理器,有一个该类的对象就足够了。多了只会浪费更多的性能。
这时候,就需要使用单例类。
第一步:需要把该类的所有构造器的访问权限设置为private。
第二步:需要公开的类方法帮助创建这一个对象。
注意创建这个对象的方法必须是类方法,因为此时对象还还不存在,自然也没有相关的实例方法。
第三步:该类必须用一个类变量来缓存已经创建的对象,用来区分这个对象是否已经存在(如果存在就不允许创建第二个对象了)。
注意记录对象的变量必须是类变量,因为它将用于和类方法交互
举例:

public class Single {
    
    
.	// 用这个类变量记录创建的单个对象
    private static Single instance;
    // 构造器设置为私有
    private  Single() {
    
    }
	// 用公开的类方法创建对象,但是如果已经创建,就直接返回对象的引用
    public static Single getInstance() {
    
    
        if (instance == null) {
    
    
            instance = new Single();
        }
        return instance;
    }
}
class SingleTest {
    
    
    public static void main(String[] args) {
    
    
    	// 测试发现,调用了2次创建对象的方法,但只得到一个对象
        Single s1 = Single.getInstance();
        Single s2 = Single.getInstance();
        // 结果为true
        System.out.println(s1 == s2);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_983030560/article/details/131137351
今日推荐