Java基础知识陷阱(三)

本文发表于本人博客

之前都讲了有关字符串的陷阱,那今天来说下关于静态这个东西,这分为静态变量、静态方法,先看下面的代码请问结果输出是什么?:

class Person01{
private static Person01 person = new Person01();
public static int age;
public static int hight = 0;
private Person01(){
age++;
hight++;
}
public static Person01 GetInstance(){
return person;
}
}

在main中进行调用

        Person01 person = Person01.GetInstance();
System.out.println("age:" + person.age + ";hight:" + person.hight);

这 个有可能有工作1年2年的也没有说出正确的答案。这个题目考察的是静态变量初始化顺序,现在我们来分析下:当main函数中使用Person01 person = Person01.GetInstance();调用静态方法的时候,首先回去查找有静态变量存在不,如果存在则从上往下先执行,这里是从person, 在到age、hight,由于person是需要调用构造的所以这句完毕后age、hight都已经是为0了,再往下执行static变量,然而对于 age它只是申明并没有赋值操作,所以跳过了,再往下就是对hight赋值了,都完毕后则return person返回这个对象,所以输出是:

   age:1;hight:0

如果还有怀疑可以把对age以及hight这2句放到person对象前面再执行查看结果,可以看到输出的结果是:

   age:1;hight:1

至此你不相信总之我是信了!那接下来我们修改下代码,如下:

class Person01{
private static Person01 person = new Person01(10,100);
public static int age;
public static int hight = 0;
private Person01(int age,int hight){
age = age;
hight = hight;
}
public static Person01 GetInstance(){
return person;
}
}

上面代码跟之前的代码相比只是在new构造的时候传递参数了,请问现在输出又是什么?我估计这里有些人被打虎眼了,先看结果:

    age:0;hight:0

为 什么呢?我们可以再new Person01(10,100)处开始说说,这里new构造传递了参数了,在构造函数中,age、以及hight2个变量是临时变量不是类 Person01的变量哦,所以这里的操作是改变这个构造函数方法内的变量的值而已,不会影响类的变量,这样结果可想而知了。大家这里可以想象如果使用 this关键字呢,结果如何?结果还是:

    age:10;hight:0

上面的例子只是说了静态函数以及静态字段,现在我们来看看如果在继承子类父类都出现了构造以及静态代码库,那么这样的执行顺序是怎样的呢,看下面代码:

class Person{
static String name = "www.luoliang.me";
static{
System.out.println("Person");
}
public Person(){
System.out.println("Person()");
}
}
class Man extends Person {
static String name = "luoliang.me";
static{
System.out.println("Man");
}
public Man(){
System.out.println("Man()");
}
}

main方法中调用如下:

    public static void main(String[] args) {
new Man();
}

输出结果是什么呢,这个问题确实是TMD的,带了好多代码但是唯独这个静态代码快的基本没用,最后问朋友也没说对答案,看答案:

Person
Man
Person()
Man()

这个答案没有想到吧,不过想想又觉得是非常合符的,毕竟有静态代码的先执行静态代码,这个比构造函数优先级还高啊!这次先到这里,明天继续。

上一篇:Java基础知识陷阱(一)


下一篇:nrm使用报错internal validators.js 124 throw new ERR_INVALID_ARG_TYPE(name, 'string', value);