首页 > 代码库 > Java类和对象动手动脑

Java类和对象动手动脑

动手动脑1

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

 技术分享

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

动手动脑2

进行试验

  • 使用上页幻灯片中定义的类,以下代码输出结果是什么?
  • 技术分享

public class Test

{

         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=200;

         }

         public int field=100;

         public InitializeBlockClass(int value)

         {

                  this.field=value;

         }

         public InitializeBlockClass()

         {

         }

}

实验结果:

 技术分享

当你在使用构造函数定义时根据参数的个数和类型自动调用相应的构造函数,同样在调用类的初始化函数时有全局变量时,也要执行全局变量的赋值。

类字段的初始化顺序

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

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

 

动手动脑3

请运行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();

         }

}

 技术分享

静态初始化块的执行顺序

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

动手动脑4

一个有趣的问题

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

public class ButtonFactory

{

private static ButtonFactory _instance = null;

public static  ButtonFactory getInstance()

{

    if(null == _instance)

           _instance = new ButtonFactory();

           return _instance;

}

}

动手动脑5

Integer类的装箱和拆箱到底是怎样实现的?

 

public class BoxAndUnbox

{

         public static void main(String[] args)

{

                  int value=http://www.mamicode.com/100;

                  Integer obj=value;  //装箱

              int result=obj*2;     //拆箱

         }

}

搜索“装箱”与“拆箱”的秘密 (了解)

  • 使用javap反编译class文件

 技术分享

反汇编工具javap的参数说明

 

 技术分享

动手动脑6

Integer诡异特性

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源文件查看源码,就可以找到答案。

 技术分享

 

课后作业1

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

public class Objictnumber

{

     int number;

     public Objictnumber()

     {

        ++number;

        System.out.println("目前创建了"+number+"个对象");

     }

 

     public static void main(String[]args)

     {

      @SuppressWarnings("unused")

      Objictnumber obj=new Objictnumber();

     }

}

技术分享

Java类和对象动手动脑