1.默认构造方法与自定义的构造方法的冲突
package com.xu; class fool { int value; fool(int nowvalue) { value=nowvalue; } } public class hello { public static void main(String[] args) { // TODO Auto-generated method stub fool f=new fool(); } }
可他为什么会报错呢?
原因是:假如不去自定义构造函数方法,java编译器在编译时会自动提供一个没有参数的“默认构造方法”,上述代码即可成立
然而,如果你自己定义了一个构造方法,将导致系统不再提供默认的构造方法,因此会报错,报错原因是你没有初始化的时候传入参数。
2.java初始化的先后顺序
package com.xu; public class hello { hello() { System.out.println("调用无参构造"); } hello(int nowvalue) { this.value=nowvalue; System.out.println("调用有参构造"); } { value=900; System.out.println("999"); } public int value=200; public static void main(String[] args) { // TODO Auto-generated method stub hello h1=new hello(); System.out.println("无参构造的输出为:"+h1.value); hello h2=new hello(1000); System.out.println("有参构造的输出为:"+h2.value); } }
输出为:
999
调用无参构造
无参构造的输出为:200
999
调用有参构造
有参构造的输出为:1000
在初始化块和数据的指定值之间的执行数序是:谁在前就先执行谁
对于构造函数在他们之后执行。
3.静态初始化块的执行顺序
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(); } }
输出为:
Root的静态初始化块
Mid的静态初始化块
Leaf的静态初始化块
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值:Java初始化顺序演示
Leaf的普通初始化块
执行Leaf的构造器
在构造子类对象时,会先构造父类对象,静态初始化块优先执行,其次是父类的非静态初始化块,父类的构造函数,然后是子类的非静态初始化块,子类的构造函数。
4.在静态方法中访问非静态成员和方法
我们都知道在静态方法中不能直接访问非静态的成员及方法
那么,我们就真的不能吗?
当然也可以,我们可以在静态方法中实例化包含非静态方法的类的对象。这样通过对象就可以间接的访问非静态方法和数据
package com.xu; public class hello { public int value=0; public int getValue() { return value; } public void setValue(int value) { this.value = value; } //静态方法中调用非静态的成员及方法 static void f() { hello s=new hello(); System.out.println(s.getValue()); int k=10; s.setValue(k); System.out.println(s.getValue()); } public static void main(String[] args) { // TODO Auto-generated method stub f(); } }
输出:
0
10
5.诡异的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); } }
输出:
true
false
为什么第二个会是false呢?
java在编译Integer x = yyy ;时,会翻译成为Integer x = Integer.valueOf(yyy)。而java API中对Integer类型的valueOf的定义如下,对于-128到127之间的数,会进行缓存,Integer i = 127时,会将127进行缓存,下次再写Integer j = 127时,就会直接从缓存中取,就不会new了。如果超过128就会重新new一个新对象。
所以i2和j2都是重新new的对象,故他们的地址不同,输出为false。
而i1和j1都是缓存过的,用的时候直接提取出来即可,因而他们的地址是一样的。
课后作业
1.使用类的静态字段和构造函数,可以跟踪某个类所创建对象的个数。请写一个类,在任何时候都可向他查询生成多少个对象
package com.xu; public class hello { static int num=0; hello() { num++; System.out.println("已创建"+num+"个对象"); } public static void main(String[] args) { // TODO Auto-generated method stub hello h1=new hello(); hello h2=new hello(); hello h3=new hello(); System.out.println("一共创建了"+num+"个对象"); } }
输出:
已创建1个对象
已创建2个对象
已创建3个对象
一共创建了3个对象