• class类的初始化


    class类的初始化##

     C++中引入了构造器这个概念(constructor)的概念,这是在创建一个对象时被自动调用的特殊方法。
     Java也引入了构造器
     构造器的主要的作用就是确保每个对象都会得到初始化。创建对象时,如果其类具有构造器,Java就会在用户操作对象之前自动调用相应的构造器,从而确保初始化的进行。

    
    
    public class Initial extends Parent {
    	public static int i=j+1;
    	public Initial()
    	{
    		System.out.println("1");
    		System.out.println(i);
    	}
    	public  void get()
    	{
    		super.get();
    		System.out.println("4");
    	}
    }
    class Parent 
    {
    	public static int j=4;
    	public Parent()
    	{
    		System.out.println("2");
    	}
    	public  void get()
    	{
    		System.out.println("3");
    	}
    }
    ...
    public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Initial initial=new Initial();
    		initial.get();
    }
    ...
    

    在上面类Initial和Parent类各有一个不带参数的构造器,这可以保证在使用对象之前,已经被初始化了
     由于构造器和类名必须完全相同,所以不用在遵从方法首字母小写的编码风格

        Initial initial=new Initial();
    

     如果Initial()是Initial类的唯一的构造器,那么编译器不会允许其他任何方式创建Initial对象。new Initial()会给相应的对象分配空间,并返回对新建对象的引用
     不带任何参数的构造器被称为默认构造器。

    默认构造器###

     默认构造器又称为无参构造器,它的作用是创建一个默认对象。如果类中没有构造器,则编译器会自动创建一个默认构造器。

    public Bird(){} 
    ...
    public static void main(String[] args) {
        Bird bird=new Bird();
    }
    ...
    

    如果已经定义了一个构造器(无论是否有参数),编译器不会再自动创建默认构造器.意思就是,如果定义了构造器,那么只能用已经定义的构造器来构造对象,不能再使用默认构造器了。

    继承和初始化####

     在思考这个问题时,就要考虑到类的加载先后顺序。Java的加载方式不同于C++。Java中的所有事物都是对象。每个类的编译代码都存在自己的独立文件里。该文件只在需要使用程序代码时才会被加载。一般来说,类的代码在初次使用才会加载。这通常指的是加载发生于创建类的第一个对象,但是当访问static域或static方法时,也会发生加载。(构造器是没有显式使用static的静态方法),因此在使用构造器创建对象时就会加载类。
     运行最上面的代码时,代码的入是main()函数,由于main()函数是静态函数,所以加载main函数所在的类的编译代码。接下来是Initial initial=new Initial();创建Initial对象,需要加载Initial类的编译代码(Initial.class).在对它进行加载的过程中编译器会发现它有一个基类,于是继续进行加载。如果该基类还有其他基类,则第二个基类就会被加载,如此类推,根基类的static初始化会被执行,然后是下一个导出类,以此类推。这种方式很重要,因为导出类的static的初始化可能会依赖基类成员能否被正确的初始化

    类中成员的初始化###

     类加载的顺序以及继承类之间的static初始化顺序现在清楚了,但是在一个类之中的初始化顺序是怎么样的?

    class  Dogs
    {
    	int a;
    	boolean b;
    	char c;
    	float f;
    	double d;
    	Dogs dogs;
    	public void PrintInf()
    	{
    		System.out.println("a  "+a);
    		System.out.println("b  "+b);
    		System.out.println("c  "+c);
    		System.out.println("d  "+d);
    		System.out.println("dogs   "+dogs);
    	}
    	public Dogs(int i)
    	{
    		System.out.println("Dog("+i+")");
    	}
    	public Dogs()
    	{
    		
    	}
    }
    class  Dogss{
    	Dogs dogs=new Dogs(0);
    	static Dogs dogs1=new Dogs(1) ;
    	public Dogss()
    	{
    		System.out.println("Dogss()");
    		dogs3=new Dogs(33);
    	}
    	static Dogs dogs2=new Dogs(2);
    	static Dogs dogs3=new Dogs(3);
    }
    public class Dog {
    
    	public static void main(String[] args) {
    		// TODO Auto-generated method stub
    		Dogss dogss=new Dogss();
    		new Dogs().PrintInf();
    	}
    
    }
    
    
    
    运行结果
    Dog(1)
    Dog(2)
    Dog(3)
    Dog(0)
    Dogss()
    Dog(33)
    a  0
    b  false
    c  
    d  0.0
    dogs   null
     
    

    上面这些代码可以看出
    1、首先关于基本类型的初始化可以发现,在构造对象之后,基本类型数据成员都会首先初始化一个默认值,没有自定义初始化的对象会默认为null。如上面的dogs被默认为null。
    2、其次在类的内部,加载时首先是先初始化静态变量,然后初始化正常对象(这里重点说明一下,不是static的基本类型变量,在没有使用构造器创建对象时是没有存储位置的,所以也不会先于构造器初始化),然后调用构造器。就如同上面的结果一样。先初始化了Dog(1),Dog(2),Dog(3),然后接下来是正常变量Dog(0),最后才是构造器
     加载类之后,先初始化静态变量(对象和基本类型数据),接下来初始化正常创建的对象,(要使用构造器的话,因为只使用静态参数的话是不需要使用构造器的)接下来调用构造器,初始化基本类型数据为默认值,调用自定义基本数据初始化方法,最后调用构造器里面的内容

    总结一下对象的创建过程,假设有个名为Dog的类

    1.即使没有显式使用static关键字,构造器也是静态方法。因此当第一次创建Dog的对象时,或者Dog类的静态方法被首次访问时,Java解释器就会加载Dog类,即寻找Dog.class文件

    2.然后载入Dog.class文件,这是有关静态初始化的所有动作都会执行(比如静态变量被初始化,静态对象的初始化,静态方法的初始化)。因此静态初始化只会在Class对象被首次加载的时候进行一次

    3.当用new Dog()创建对象的时候,首先在堆上为Dog对象分配足够的存储空间。

    4.这块存储空间现在为空,自动将Dog对象中的基本类型数据都设置为默认值,引用被设置为null

    5.执行所有出现在字段定义出的初始化动作

    6.执行构造器

  • 相关阅读:
    百度地图API 绘制矩形多边形等覆盖物
    不可多得的JS优化技巧
    vscode的settings.json配置(个人习惯)
    npm 查看模块全部版本
    .net core 生成 发布的文件里删除多余的语言包指定仅需要的语言
    225. Implement Stack using Queues (栈实现队列)
    232. Implement Queue using Stacks(队列实现栈)
    496. Next Greater Element I (单调栈)
    239. Sliding Window Maximum (滑动窗口最大值, 大根堆or 单调队列)
    30. Substring with Concatenation of All Words (滑动窗口)
  • 原文地址:https://www.cnblogs.com/Black-Cobra/p/6896932.html
Copyright © 2020-2023  润新知