动手动脑3
验证结果:输出false,原因是这里比较的是两个引用变量的地址值,显然两个变量并非指向同一块内存,所以输出false。由此可以知道不要通过==对两个同一类型的实例进行值大小的判等。
以下代码无法编译通过?原因在哪里?
原因:Foo类型没有Foo()的构造方法。如果定义一个类,显式定义了一个带参数的构造方法却没显式定义没有参数的默认构造方法,那么实际上该类就只有那个带参数的构造方法。若有需要的话,两种构造方法可同时重载定义。
以下代码的输出结果是什么?
输出结果:100 300
Java字段初始化顺序:
1.实例化类时在调用构造方法之前,可能类变量有指定默认值或者有初始化块,到底先执行哪一个要看哪一个在前面,然后再执行后一个。
2.实例化类时调用构造方法时初始化字段。
观察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 }
结果如下:
根据上面的结论和本例的结果补全Java字段初始化顺序规律:
1.类加载时优先对静态初始块进行处理
2.实例化类时在调用构造方法之前,可能类变量有指定默认值或者有初始化块,到底先执行哪一个要看哪一个在前面,然后再执行后一个。
3.实例化类时调用构造方法时初始化字段。
还有,一个静态方法不能直接访问本类中的非静态字段或非静态方法。
代码情况如下:
很显然,不可以。不过要真的想使用也可以,那就是像主函数(主函数本身就是一个静态方法)中一样,通过建立类实例,通过实例对象来调用非静态方法或直接使用非静态字段。
比如:
1 public class Test3 { 2 public int result = 0; 3 public static void Testshow() { 4 Test3 t1 = new Test3(); 5 t1.result++; 6 t1.resultShow(); //输出1 7 } 8 public void resultShow() { 9 System.out.println("测试使用:"+result); 10 } 11 public static void main(String[]args) { 12 Testshow(); 13 } 14 }
最后一个例子:
输入结果为:true false
原因在看过Java中Integer类源码之后可以知道,在创建Integer对象时,要调用valueOf方法:如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。
所以第一次输出true,第二次输出false。