zoukankan      html  css  js  c++  java
  • Java对象创建过程补遗

    一、static修饰的东东是属于这个类的,是所有的该类的实例共享的,因此它们的初始化先于实例对象的初始化。

    二、Java中没有静态构造方法,但是有静态代码块。当类中同时存在静态代码块和静态成员变量声明语句时,它们谁先执行?

    答:按照类中定义的从上到下顺序,谁在前面谁先执行。

    三、当类中同时存在非静态代码块和非静态成员变量声明语句时,它们谁先执行?

    答:按照类中定义的从上到下顺序,谁在前面谁先执行。

    四、含有赋值的非静态成员变量声明语句,如 int v=4,其实这个语句的执行要分成两步进行。首先创建对象时初始化变量v,此时v=0;然后在构造器中再给v赋值,也就是v=4。

    五、非静态初始化块中的赋值语句、实例变量值初始化赋值语句,都比构造器中的赋值语句先执行。

    原理如下:不管是非静态初始化块中的赋值语句,还是实例变量值初始化赋值语句,它们在编译器处理后,都会被提取到构造器中,而且在构造器中原有的语句之前。

    public class JavaTest
    {
        //成员变量
        int count=20;
    
        //非静态初始化代码块
        {
            count = 12;
            System.out.print("占个位置而已");
        }
    
        //构造器
        public JavaTest()
        {
            System.out.println(count);
        }
    
        public JavaTest(String name)
        {
            System.out.println(count);
        }
    }

    编译后等价于:

    public class JavaTest
    {
        //成员变量
        int count;
    
        //非静态初始化代码块
        {
            System.out.print("占个位置而已");
        }
    
        //构造器
        public JavaTest()
        {
            count=20;//原来的成员变量赋值
            count=12;//原来的初始化代码块赋值
            System.out.println(count);
        }
    
        public JavaTest(String name)
        {
            count=20;//原来的成员变量赋值
            count=12;//原来的初始化代码块赋值
            System.out.println(count);
        }
    }

    六、“Java对象是由构造器创建的”这句话是错误的。构造器只是负责对Java对象的实例变量执行初始化而已,就像前面的三、四、五点所提及的。在执行构造器代码之前,该实例对象所占的内存已经被分配下来了,这些内存都默认是空值——对于基本类型的变量,默认的空值就是0、0.0或者false;对于引用类型的变量,默认的控制就是Null。看看下面的代码,分析一下结果是什么:

    
    class base
    {
        private int i = 2;
    
        public Base()
        {
            这里是1处
            this.display();
        }
    
        public void display()
        {
            System.out.println(i);
        }
    }
    
    class Derived extends base
    {
        private int i = 22;
    
        public Derived()
        {
            i = 222;
        }
    
        public void display()
        {
            System.out.println(i);
        }
    }
    
    public class Test
    {
        public static void main(String[] args)
        {
            new Derived();
        }
    }

    问题一:Derived对象的实例中有几个”i“实例变量? 说只有一个的同学,请自己去面壁

    问题二:代码中的红色的1处,所指的“this”是谁?是base的实例还是Derived的实例?  答案是 Derived

    问题三:代码中的红色1处,“this.display(); ”调用的是哪个类里面的display方法?       答案是 Derived

    问题四:执行Test后输出是2?22?还是222?   答案是 0

    七、编译器在处理成员变量和方式时是有区别的。当子类和父类存在同名的成员变量时,实际是各自拥有一个名字相同的成员变量;当子类中有个方法和父类签名相同的时候,实际是子类对父类中该方法的重写,这个时候通过子类的实例调用这个名称的方法将始终是子类的方法,哪怕你把子类强制转换成父类。这么说有点迷糊,直接往下看:

    class base
    {
        private int i = 2;
    
        public Base()
        {
            this.display();
        }
    
        public void display()
        {
            System.out.println("我是父类"+i);
        }
    }
    
    class Derived extends base
    {
        private int i = 22;
    
        public Derived()
        {
            i = 222;
        }
    
        public void display()
        {
            System.out.println("我是子类"+i);
        }
    }

    情况一:

    Base b=new Base()

    b.count :肯定是2,因为当前对象是父类的实例

    b.display():肯定是调用父类的方法,因为当前是父类的实例

    情况二:

    Derived d=new Derived();

    b.count: 肯定是22,因为当前对象是子类的实例,子类自己有个成员变量叫“i”干嘛拿父类的

    b.display():子类的方法

    情况三:

    Base bd=new Derived();

    b.count:肯定是2,因为当前子类是被向上转换了,不得不拿父类的“i”

    b.display():还是子类的方法,向上转换不能太过分了,子类已经重写的方法不能再反悔了。要想调用父类的同名方法,还得用这种方式:super.display()

    情况四:

    Derived d=new Derived();

    Base d2b=d;

    b.count:肯定是2,因为当前子类是被强制类型转换了,不得不拿父类的“i”

    b.display():还是子类的方法,强制类型转换也不能太过分了,子类已经重写的方法不能再反悔了。要想调用父类的同名方法,还得用这种方式:super.display()

    八、从内存分配的角度来看,当程序创建一个子类对象时,JVM不仅会为该类中定义的实例变量分配内存,同时也会为其父类中定义的所有实例变量分配内存,即使子类定义了与父类中同名的实例变量。如果子类中定义了与父类同名的成员变量,那么子类中的变量会隐藏父类中定义的变量,但不是完全覆盖,只是不能直接用而已;当把子类转换成父类的时候或者使用”super“关键字,就可以使用父类中的同名成员变量了。

  • 相关阅读:
    oracle日志总结
    UIScrollView,contentOffset,contentInsert的各自特点和区别?
    js动态增加表格
    判断某个对象是不是DOM对象
    IOS 中frame与bounds的区别
    删除重复项,只取其中一条数据
    NSBundle
    React
    HTML5 postMessage 和 onmessage API 详解
    SonarQube
  • 原文地址:https://www.cnblogs.com/yuananyun/p/3947115.html
Copyright © 2011-2022 走看看