动手动脑:
(1)以下代码为何无法通过编译?哪儿出错了?
答: 编译无法通过的原因是类的构造方法有一个参数,而生成对象的时候没有给对象一个参数,所以编译无法通过。如果类提供了一个自定义的构造方法,将导致系统不再提供默认构造方法。所以默认的构造方法不会出现。
(2)请运行TestStaticInitializeBlock.java示例,观察输出结果,总结出“静态初始化块的执行顺序”。
1 class Root 2 { 3 static{ 4 System.out.println("Root的静态初始化块"); 5 } 6 { 7 System.out.println("Root的普通初始化块"); 8 } 9 public Root() 10 { 11 System.out.println("Root的无参数的构造器"); 12 } 13 } 14 class Mid extends Root 15 { 16 static{ 17 System.out.println("Mid的静态初始化块"); 18 } 19 { 20 System.out.println("Mid的普通初始化块"); 21 } 22 public Mid() 23 { 24 System.out.println("Mid的无参数的构造器"); 25 } 26 public Mid(String msg) 27 { 28 //通过this调用同一类中重载的构造器 29 this(); 30 System.out.println("Mid的带参数构造器,其参数值:" + msg); 31 } 32 } 33 class Leaf extends Mid 34 { 35 static{ 36 System.out.println("Leaf的静态初始化块"); 37 } 38 { 39 System.out.println("Leaf的普通初始化块"); 40 } 41 public Leaf() 42 { 43 //通过super调用父类中有一个字符串参数的构造器 44 super("Java初始化顺序演示"); 45 System.out.println("执行Leaf的构造器"); 46 } 47 48 } 49 50 public class TestStaticInitializeBlock 51 { 52 public static void main(String[] args) 53 { 54 new Leaf(); 55 56 57 } 58 }
答:
1. 当程序执行时,需要生成某个类的对象,Java执行引擎会先检查是否加载了这个类,如果没有加载,则先执行类的加载再生成对象,如果已经加载,则直接生成对象。
2. 在类的加载过程中,类的static成员变量会被初始化,另外,如果类中有static语句块,则会执行static语句块。static成员变量和static语句块的执行顺序同代码中的顺序一致。记住,在Java中,类是按需加载,只有当需要用到这个类的时候,才会加载这个类,并且只会加载一次。
3. 在生成对象的过程中,会先初始化对象的成员变量,然后再执行构造器。也就是说类中的变量会在任何方法(包括构造器)调用之前得到初始化,即使变量散步于方法定义之间。
4. 静态初始化块只执行一次。
5. 创建子类型的对象时,也会导致父类型的静态初始化块的执行。
进行试验
(1)请依据代码的输出结果,自行总结Java字段初始化的规律。
public class InitializeBlockDemo { 2 3 /** 4 * @param args 5 */ 6 public static void main(String[] args) { 7 8 InitializeBlockClass obj=new InitializeBlockClass(); 9 System.out.println(obj.field); 10 11 obj=new InitializeBlockClass(300); 12 System.out.println(obj.field); 13 } 14 15 } 16 17 class InitializeBlockClass{ 18 //下面这句在初始化块之前与之后,会影响到field字段的初始值 19 //public int field=100; 20 21 { 22 field=200; 23 } 24 public int field=100; 25 public InitializeBlockClass(int value){ 26 this.field=value; 27 } 28 public InitializeBlockClass(){ 29 30 } 31 }
答:java语言中对类数据的初始化的顺序为 构造函数>类后面的数据赋值>类前面的数据赋值
执行类成员定义时指定的默认值或类的初始化块,到底执行哪一个要看哪一个“排在前面”,排在前面的先执行。
执行类的构造函数。
类的初始化块不接收任何的参数,而且只要一创建类的对象,它们就会被执行。因此,适合于封装那些“对象创建时必须执行的代码”。
(2)静态方法中只允许访问静态数据,那么,如何在静态方法中访问类的实例成员(即没有附加static关键字的字段或方法)?
请编写代码验证你的想法。
public class CreateanObject { 2 public int num=110; 3 private static int number=0; 4 public CreateanObject(){ 5 number++; 6 } 7 public void out() 8 { 9 System.out.println("你已创建了"+number+"个对象"); 10 } 11 public static void put(CreateanObject test){ 12 System.out.print(" "+test.num); 13 } 14 public static void main(String[] args) 15 { 16 CreateanObject test = new CreateanObject(); 17 CreateanObject test1 = new CreateanObject(); 18 test.out(); 19 20 21 } 22 }
答:静态方法课以访问对象的实例,不过要求静态方法需要在参数列表中添加类的实体。然后才能在静态方法中访问对象的成员.