动手动脑:
(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 }
答:静态方法课以访问对象的实例,不过要求静态方法需要在参数列表中添加类的实体。然后才能在静态方法中访问对象的成员.