第五周动手动脑1

结果:

 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 }
View Code

总结:在执行类成员定义时,指定的默认值或类的初始化块,执行哪个?  看哪个“排在后面”

 注:类的初始化块不接受任何参数,而且,只要创建类的对象,它们就会被执行。

所以,类的初始化块适合于封装那些“对象创建时,必须执行的代码”

二、类的静态字段
1.例如:

1 class Employee{
2 String name;
3 long salary;
4 static int total;
5 }
View Code

2.访问类的静态字段:通过对象名或类名作为前缀访问静态数据

2.1类名直接访问(推荐使用):Employee.total=1;

2.2对象名访问:

Employee newhire=new Employee();

newhire.total=1;

三、类的静态初始化块

1.例子

 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 }
View Code

结果:

2.总结:

2.1静态初始化块只执行一次。

2.2创建子类型的对象时,会导致父类型的静态初始化块的执行

四、类的静态方法(类的静态方法只能访问类的静态成员!!!)

1.例如

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 }
View Code

2.如何在静态方法中访问类的实例成员(即没有附加static关键字的字段或方法)?

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);
    }
}
View Code

解决方案:在静态方法中访问类的实例变量需首先进行类的实例化

类中静态的方法或者属性,本质上来讲并不是该类的成员,在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() {}
    }
复制代码

猜你喜欢

转载自www.cnblogs.com/Evak/p/9825738.html