2019.10.14课堂总结

一、动手动脑1

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

 

 

        该段代码定义了Foo函数,但没有给Foo函数提供参数,Java编译器不会提供默认构造方法而是使用以定义的方法。

 

二、动手动脑2

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

代码如下:

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();

    }
}
View Code

运行结果截图:

 

 

 

 总结如下:

1、静态初始化块只执行一次。

2、创建子类型的对象时,也会导致父类型的静态初始化块的执行。

 

三、进行试验1

使用上页幻灯片中定义的类,以下代码输出结果是什么?请依据代码的输出结果,自行总结Java字段初始化的规律。

             

运行结果截图:

总结:

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

2、当有构造函数时执行类的构造函数。

 

 

四、有趣的问题

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

 验证代码如下:

public class fangwen {
    public static void fun(fangwen s) {
        s.fun1();
    }

    public void fun1() {
        System.out.println("访问成功");
    }

    public static void main(String[] args) {
        fangwen s1 = new fangwen();
        fun(s1);
    }
}
View Code

 

 

 五、Integer的“诡异”特性

 神奇代码(StrangeIntegerBehavior.java)输出诡异的结果,原因何在?

代码如下:

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);

    }

}
View Code

结果如下:

 

 使用javap来分析生成class文件,看它调用了Interger类的哪个方法

 

 然后打开JDK源文件查看源码

/**
     * Cache to support the object identity semantics of autoboxing for values between
     * -128 and 127 (inclusive) as required by JLS.
     *
     * The cache is initialized on first usage.  The size of the cache
     * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option.
     * During VM initialization, java.lang.Integer.IntegerCache.high property
     * may be set and saved in the private system properties in the
     * sun.misc.VM class.
     */

    private static class IntegerCache {
        static final int low = -128;
        static final int high;
        static final Integer cache[];

        static {
            // high value may be configured by property
            int h = 127;
            String integerCacheHighPropValue =
                sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
            if (integerCacheHighPropValue != null) {
                try {
                    int i = parseInt(integerCacheHighPropValue);
                    i = Math.max(i, 127);
                    // Maximum array size is Integer.MAX_VALUE
                    h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
                } catch( NumberFormatException nfe) {
                    // If the property cannot be parsed into an int, ignore it.
                }
            }
            high = h;

            cache = new Integer[(high - low) + 1];
            int j = low;
            for(int k = 0; k < cache.length; k++)
                cache[k] = new Integer(j++);

            // range [-128, 127] must be interned (JLS7 5.1.7)
            assert IntegerCache.high >= 127;
        }

 

 

六、课后作业

使用类的静态字段和构造函数,可以跟踪某个类所创建对象的个数。请写一个类,在任何时候都可以向它查询“你已经创建了多少个对象?”

 代码如下:

package HomeTest;

public class Objnumber {
    private static int sum=0;
    public Objnumber() {
        sum++;
    }
    public static void num() {
        System.out.println("你已经创建了"+sum+"个对象");
    }
    public static void main(String[] args) {
        Objnumber obj = new Objnumber();
        Objnumber.num();
    }
}
View Code

posted @ 2019-10-15 21:37  嘉禾旧木  阅读(166)  评论(0编辑  收藏  举报