• 课程作业06:验证课件上的代码,并将所有的动手动脑或要求发表博客作业部分整理成一篇博客发表。


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

     

    验证结论:如果类提供了一个自定义的构造方法,将导致系统不再提供默认的构造方法。所以此时需要无参的构造方法时,需要自己写一个空的构造方法,即系统默认的构造方法。

     

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

     

     

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

     

    规律一:类字段的初始化顺序

    1.执行类成员定义时指定的默认值或类的初始化块,到底执行哪一个要看哪一个“排在前面”,输出结果是排在后边的那个,先执行的被修改为后执行的。

    2.执行类的构造函数。

    规律二:类初始化块的应用

    类的初始化块不接收任何的参数,而且只要一创建类的对象,它们就会被执行。因此,适合于封装那些“对象创建时必须执行的代码”。

     

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

    package give3;

     

    public class TestStaticInitializeBlock {

     

        public static void main(String[] args) {

           new Leaf();

           }

    }

     

    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的构造器");

        }

    }

    结果截图:

     

    静态初始化的执行顺序:

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

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

    4.静态方法中只允许访问静态数据,那么,如何在静态方法中访问类的实例成员(即没有附加static关键字的字段或方法)?请编写代码验证你的想法。

     

    类的静态成员(变量和方法)属于类本身,在类加载的时候就会分配内存,可以通过类名直接去访问;非静态成员(变量和方法)属于类的对象,所以只有在类的对象产生(创建类的实例)时才会分配内存,然后通过类的对象(实例)去访问。

    5. 两对整数明明完全一样,为何一个输出true,一个输出false?

     

    输出结果表明i1和i2指向的是同一个对象,而i3和i4指向的是不同的对象。此时只需一看源码便知究竟,下面这段代码是Integer的valueOf方法的具体实现:

    public static Integer valueOf(int i) {

            if(i >= -128 && i <= IntegerCache.high)

                return IntegerCache.cache[i + 128];

            else

                return new Integer(i);

        }

    而其中IntegerCache类的实现为:

     private static class IntegerCache {

            static final int high;

            static final Integer cache[];

     

            static {

                final int low = -128;

     

                // high value may be configured by property

                int h = 127;

                if (integerCacheHighPropValue != null) {

                    // Use Long.decode here to avoid invoking methods that

                    // require Integer's autoboxing cache to be initialized

                    int i = Long.decode(integerCacheHighPropValue).intValue();

                    i = Math.max(i, 127);

                    // Maximum array size is Integer.MAX_VALUE

                    h = Math.min(i, Integer.MAX_VALUE - -low);

                }

                high = h;

     

                cache = new Integer[(high - low) + 1];

                int j = low;

                for(int k = 0; k < cache.length; k++)

                    cache[k] = new Integer(j++);

            }

     

            private IntegerCache() {}

        }

     

    从这2段代码可以看出,在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。上面的代码中i1和i2的数值为100,因此会直接从cache中取已经存在的对象,所以i1和i2指向的是同一个对象,而i3和i4则是分别指向不同的对象。

     

  • 相关阅读:
    外部排序
    oceanbase tpcc 关键总结
    TPCC测试
    最简单的oracle 19c安装教程
    unix进程环境
    tars以docker方式安装
    异常安全的赋值运算符函数
    linux 定时器setitimer使用
    libevent学习-reactor设计模式及代码示例
    linux中可执行程序搜索动态链接库的顺序
  • 原文地址:https://www.cnblogs.com/iCheny/p/7700615.html
Copyright © 2020-2023  润新知