结果:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 package second; 2 3 public class Test { 4 /* 5 * 类的初始化块 6 */ 7 { 8 value=100; 9 } 10 public int value=200;//字段的初始值 11 12 public Test(){ 13 } 14 /* 15 * 构造函数初始化 16 */ 17 public Test(int value){ 18 this.value=value; 19 } 20 public static void main(String[] args){ 21 Test obj=new Test(); 22 System.out.println(obj.value);//结果 100 23 24 obj=new Test(300); 25 System.out.println(obj.value);//结果 300 26 } 27 }
总结:在执行类成员定义时,指定的默认值或类的初始化块,执行哪个? 看哪个“排在后面”
注:类的初始化块不接受任何参数,而且,只要创建类的对象,它们就会被执行。
所以,类的初始化块适合于封装那些“对象创建时,必须执行的代码”
二、类的静态字段
1.例如:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 class Employee{ 2 String name; 3 long salary; 4 static int total; 5 }
2.访问类的静态字段:通过对象名或类名作为前缀访问静态数据
2.1类名直接访问(推荐使用):Employee.total=1;
2.2对象名访问:
Employee newhire=new Employee();
newhire.total=1;
三、类的静态初始化块
1.例子
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 package first; 2 3 4 class Root//父类 5 { 6 static{ 7 System.out.println("Root的静态初始化块"); 8 } 9 { 10 System.out.println("Root的普通初始化块"); 11 } 12 public Root() 13 { 14 System.out.println("Root的无参数的构造器"); 15 } 16 } 17 class Mid extends Root 18 { 19 static{ 20 System.out.println("Mid的静态初始化块"); 21 } 22 { 23 System.out.println("Mid的普通初始化块"); 24 } 25 public Mid() 26 { 27 System.out.println("Mid的无参数的构造器"); 28 } 29 public Mid(String msg) 30 { 31 //通过this调用同一类中重载的构造器 32 this(); 33 System.out.println("Mid的带参数构造器,其参数值:" + msg); 34 } 35 } 36 class Leaf extends Mid//子类 37 { 38 static{ 39 System.out.println("Leaf的静态初始化块"); 40 } 41 { 42 System.out.println("Leaf的普通初始化块"); 43 } 44 public Leaf() 45 { 46 //通过super调用父类中有一个字符串参数的构造器 47 super("Java初始化顺序演示"); 48 System.out.println("执行Leaf的构造器"); 49 } 50 51 } 52 53 public class TestStaticInitializeBlock 54 { 55 public static void main(String[] args) 56 { 57 new Leaf(); 58 59 } 60 }
结果:
2.总结:
2.1静态初始化块只执行一次。
2.2创建子类型的对象时,会导致父类型的静态初始化块的执行
四、类的静态方法(类的静态方法只能访问类的静态成员!!!)
1.例如
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 class Employee{ 2 String name; 3 long salary; 4 short employee_id; 5 static int total; 6 static void clear(){ 7 total=0; 8 } 9 }
2.如何在静态方法中访问类的实例成员(即没有附加static关键字的字段或方法)?
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
public class Example { int x = 3;//类的实例变量,初始化值为3 static int y = 4;//类的静态变量,初始化值为4 public static void method()//静态方法 { System.out.println("实例变量x = " + new Example().x);//在静态方法中访问类的实例变量需首先进行类的实例化 System.out.println("静态变量y = " + y);//在静态方法中可直接访问类的静态变量 } public static void main(String[] args) { Example.method(); Example ex = new Example(); System.out.println("x = " + ex.x); } }
解决方案:在静态方法中访问类的实例变量需首先进行类的实例化
类中静态的方法或者属性,本质上来讲并不是该类的成员,在java虚拟机装在类的时候,这些静态的东西已经有了对象,它只是在这个类中"寄居",不需要通过类的构造器(构造函数)类实现实例化;而非静态
的属性或者方法,在类的装载是并没有存在,需在执行了该类的构造函数后才可依赖该类的实例对象存在。
在外部调用静态方法时,可以使用"类名.方法名"的方式,也可以使用"对象名.方法名"的方式。而实例方法只有后面这种方式。也就是说,调用静态方法可以无需创建对象。
五、Integer的诡异性
public static void main(String[] args){ Integer i1=100; Integer j1=100; System.out.println(i1=j1);//true Integer i2=129; Integer j2=129; System.out.println(i2=j2);//false }
原因:查看源码可知,在通过valueOf方法创建Integer对象的时候,如果数值在[-128,127]之间,便返回指向IntegerCache.cache中已经存在的对象的引用;否则创建一个新的Integer对象。
1 * This method will always cache values in the range -128 to 127, 2 * inclusive, and may cache other values outside of this range. 3 * 4 * @param i an {@code int} value. 5 * @return an {@code Integer} instance representing {@code i}. 6 * @since 1.5 7 */ 8 public static Integer valueOf(int i) { 9 if (i >= IntegerCache.low && i <= IntegerCache.high) 10 return IntegerCache.cache[i + (-IntegerCache.low)]; 11 return new Integer(i); 12 }
/** * Cache to support the object identity semantics of autoboxing for values between * -128 and 127 (inclusive) as required by JLS. * * The cache is initialized on first usage. The size of the cache * may be controlled by the {@code -XX:AutoBoxCacheMax=<size>} option. * During VM initialization, java.lang.Integer.IntegerCache.high property * may be set and saved in the private system properties in the * sun.misc.VM class. */ private static class IntegerCache { static final int low = -128; static final int high; static final Integer cache[]; static { // high value may be configured by property int h = 127; String integerCacheHighPropValue = sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high"); if (integerCacheHighPropValue != null) { try { int i = parseInt(integerCacheHighPropValue); i = Math.max(i, 127); // Maximum array size is Integer.MAX_VALUE h = Math.min(i, Integer.MAX_VALUE - (-low) -1); } catch( NumberFormatException nfe) { // If the property cannot be parsed into an int, ignore it. } } high = h; cache = new Integer[(high - low) + 1]; int j = low; for(int k = 0; k < cache.length; k++) cache[k] = new Integer(j++); // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; } private IntegerCache() {} }