关于本次课堂代码的练习

(1)对象变量的判等

public class demo01 {
    static class Foo{
        int value = 100;
    }
    public static void main(String[] args) {
        Foo obj1 = new Foo();
        Foo obj2 = new Foo();
        System.out.println(obj1 == obj2);
    }
}

 如代码可见,obj1和obj2是否为等?

 答案如下

为什么会出现false呢?原因在于,当你将“==”作用于引用类型变量时,比较的是这两个变量是否引用于同一对象。而引用代表地址,所以本质上上述代码比较的是地址值,所以出现false也是合情合理的了。

(2)自定义构造方法和默认构造方法

  

public class demo01 {
    static class Foo{
        int value;
        public Foo(int initvalue) {
            value = initvalue;
        }
    }
    public static void main(String[] args) {
        Foo obj = new Foo();
    }
}

如图代码。

此代码是无法编译的,因为编译器会报错。错误点在于:

在没有手动输入一个类的构造方法时,编译器会自动提供一个无参的构造方法。而上述代码很明显,编程者手动写了一个构造方法Foo(int initvalue),这是一个有参构造方法,而编译器检测到这个方法后,就不再提供无参构造方法。所以,当编程者实例化无参构造方法时,系统就会报错了。解决方案如下:

public class demo01 {
    static class Foo{
        int value;
        public Foo(int initvalue) {
            value = initvalue;
        }
    }
    public static void main(String[] args) {
        int initvalue = 0;
        Foo obj = new Foo(initvalue);
    }
}

这样的程序是可执行的。

(3)关于类的初始化块

public class demo01 {

    public static void main(String[] args) {
        
        InitializeBlockClass obj=new InitializeBlockClass();
        System.out.println(obj.field);
        
        obj=new InitializeBlockClass(300);
        System.out.println(obj.field);
    }

}
class InitializeBlockClass{
    //下面这句在初始化块之前与之后,会影响到field字段的初始值
    //public int field=100;
    
    {
        field=200;
    }
    public int field=100;
    public InitializeBlockClass(int value){
        this.field=value;
    }
    public InitializeBlockClass(){
        
    }
}

如图代码

当一个类中如果一个类中既有初始化块,又有构造方法,同时还设定了字段的初始值,谁说了算?

上述代码运行结果可见:

所以,根据这道题结论可知:

1、执行类成员定义时指定的默认值或类的初始化块,到底执行哪一个要看哪一个“排在前面”。

2、执行类的构造函数。

(4)静态初始化块的执行顺序

package Demo01;

class Root
{
    static{
        System.out.println("Root的静态初始化块");
    }
    {
        System.out.println("Root的普通初始化块");
    }
    public Root()
    {
        System.out.println("Root的无参数的构造器");
    }
}
class Mid extends Root
{
    static{
        System.out.println("Mid的静态初始化块");
    }
    {
        System.out.println("Mid的普通初始化块");
    }
    public Mid()
    {
        System.out.println("Mid的无参数的构造器");
    }
    public Mid(String msg)
    {
        //通过this调用同一类中重载的构造器
        this();
        System.out.println("Mid的带参数构造器,其参数值:" + msg);
    }
}
class Leaf extends Mid
{
    static{
        System.out.println("Leaf的静态初始化块");
    }
    {
        System.out.println("Leaf的普通初始化块");
    }    
    public Leaf()
    {
        //通过super调用父类中有一个字符串参数的构造器
        super("Java初始化顺序演示");
        System.out.println("执行Leaf的构造器");
    }

}
public class demo01{
    public static void main(String[] args) 
    {
        new Leaf();
    }
}
  1. 静态初始化块的优先级最高,也就是最先执行,并且仅在类第一次被加载时执行;
  2. 非静态初始化块和构造函数后执行,并且在每次生成对象时执行一次;
  3. 非静态初始化块的代码会在类构造函数之前执行。因此若要使用,应当养成把初始化块写在构造函数之前的习惯,便于调试;
  4. 静态初始化块既可以用于初始化静态成员变量,也可以执行初始化代码;
  5. 非静态初始化块可以针对多个重载构造函数进行代码复用。

(5)在静态方法中访问类的实例成员

package Demo01;

public class demo01 {
     int x = 3;//类的实例变量,初始化值为3
     static int  y = 4;//类的静态变量,初始化值为4
     public static void method()//静态方法
      {   
       System.out.println("实例变量x = " + new demo01().x);//在静态方法中访问类的实例变量需首先进行类的实例化
       System.out.println("静态变量y = " + y);//在静态方法中可直接访问类的静态变量
      }

     public static void main(String[] args) 
        {
             demo01.method();
             demo01 ex = new demo01();
            System.out.println("x = " + ex.x);
        }
}

结果:

原文地址:https://www.cnblogs.com/YXSZ/p/9824575.html