动手动脑3

动手动脑1:

以下代码为何无法通过编译?哪儿出错了?

package dongshou;

 

public class Test {

public static void main(String[] args)

{

    Foo obj1=new Foo();

}

}

class Foo

{

int value;

public Foo(int intValue)

{

    value=intValue;

}

}

结论:如果类提供了一个自定义的构造方法,将导致系统不再提供默认构造方法。

动手动脑2:

请依据代码的输出结果,自行总结Java字段初始化的规律。

package dongshou;

public class InitializeBlockClass {

{

field=200;

}

public int field=100;

public InitializeBlockClass(int value)

{

this.field=value;

}

public InitializeBlockClass() {

 

}

public static void main(String[] args)

{

InitializeBlockClass obj=new InitializeBlockClass();

System.out.println(obj.field);

obj=new InitializeBlockClass(300);

System.out.println(obj.field);

}

}

运行结果:

 

 

结论:执行类成员定义时指定的默认值或类的初始化块,到底执行哪一个要看哪一个“排在前面”。实例化对象时,当public int field=100;在初始化块之后是=时输出100;在其之前输出便是200;所以是与谁排在前有关系。此外,类的初始化块不接收任何的参数,而且只要一创建类的对象,它们就会被执行。

之后执行类的构造函数

动手动脑3:

请运行TestStaticInitializeBlock.java示例,观察输出结果,总结出“静态初始化块的执行顺序”。

package kehsang;

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 TestStaticInitializeBlock

{

    public static void main(String[] args)

    {

        new Leaf();

       

 

    }

}

运行结果:

 

 

结论:静态初始化块只执行一次。创建子类型的对象时,也会导致父类型的静态初始化块的执行,父类的静态初始化块先于子类执行。

 

一个有趣的问题:

静态方法中只允许访问静态数据,那么,如何在静态方法中访问类的实例成员(即没有附加static关键字的字段或方法)?

package kehsang;

 

public class ShiLi {

    public void output() {

        System.out.println("通过实例化对象调用");

    }

    public static void main(String[] args) {

        //output();出现错误

        ShiLi r=new ShiLi();

        r.output();//调用成功,正常运行

    }

}

Integer的“诡异特性”

package kehsang;

public class StrangeIntegerBehavior

{

 

   

    public static void main(String[] args)

    {

 

       

        Integer i1=100;

      

        Integer j1=100;

       

        System.out.println(i1==j1);

 

       

        Integer i2=129;

       

        Integer j2=129;

       

        System.out.println(i2==j2);

   

    }

 

 

}

运行结果:

 

 

使用javap来分析生成class文件,看它调用了Interger类的哪个方法,然后打开JDK源文件查看源码,就可以找到答案

 

 

原因:Integer类型的常量池范围为-128~127。i1=100java调用了Integer.valueOf()方法,该方法中缓存了-128~127之间的值,如果赋值时在此范围内便是在缓存中取值,而不在此范围中时,相当于使用了new创建了一个新的Integer类故而使用==不会相等。

posted @ 2020-10-16 11:45  chenghaixinag  阅读(43)  评论(0编辑  收藏  举报