首页 > 技术文章 > java 对象 拆箱装箱 编译和反编译的验证

news1997 2017-10-20 08:46 原文

创建对象

package 创建对象的个数;

public class main {
public static void main(String[] agrs){
Check c1=new Check();
Check c2=new Check();
Check c3=new Check();
System.out.println("你已创建了"+c1.a+"个对象");
}

}
class Check{
static int a=0;
//{
// a=a+1;
//}
public Check(){
a=a+1;
}
}

 

一,验证的代码

1,变量判等

运行结果为:false

==”施加于原始数据类型变量时,是比较变量所保存的数据是否相等;当“==”施加于引用类型变量时,是比较这两个变量是否引用同一对象。

2,初始化块,构造方法和字段的初始值哪一个说了算?

运行结果为:

100

300

总结:若是有参的构造方法,则输出带参数的值;若是无参的构造方法,则输出的值与初始化块和字段的额初始值的顺序有关;类的初始化块不接收任何的参数,而且只要创建类的对象,它们就会被执行。因此,适合于封装那些“对象创建时必须执行的代码”。

3,静态方法只允许访问静态数据,那么,如何在静态方法中访问类的实例成员(即没有附加static关键字的字段或方法)?

 可以在静态方法中添加类的对象的参数,在静态初始化块中创建类的对象,通过对象来访问实例数据。

 代码如下:

  public class text2{

 public static void main(String[] args){

  Foo obj1=new Foo();

  obj1.Foo1(obj1);

 }

}

class Foo{

 

    int field=100;

public static void Foo1(Foo f){

System.out.println("静态方法访问的实例数据为:"+f.field);;

}

static{

Foo f1=new Foo();

System.out.println("静态初始化块访问的实例数据为:"+f1.field);

      }

public Foo(){

 

}

 

}

运行结果

静态初始化块访问的实例数据为:100

静态方法访问的实例数据为:100

4,装箱和拆箱

  代码和运行结果

 

 

javap反编译class文件

 

 

由图可知,装箱时调用Integer类的valueOf(int)方法,拆箱时调用的是Integer类的intValue()方法,装箱是将基本数据类型转换为包装器类型,拆箱是将包装器类型转换为基本数据类型。

5,两对完全相同的整数,为何一个输出true,一个输出false

 代码及运行结果

 

 

Javap反编译class

 

 

 

 

由图可知,它调用了Integer类的valueOf()方法,通过JDK源码可以看出,在通过valueOf()方法创建Integer对象的时候,如果数值在【-128127】之间便返回指向已经存在的对象的引用,for则创建一个新的Integer对象,因为i1j1的值为100,所以会直接从擦车中取已经存在的对象,所以i1j1指向的是同一个对象,为i2j2指向的是不同的对象。

6,创建对象的个数计算

package 创建对象的个数;

 

public class main {

public static void main(String[] agrs){

Check c1=new Check();

Check c2=new Check();

Check c3=new Check();

System.out.println("你已创建了"+c1.a+"个对象");

}

 

}

class Check{

    static int a=0;

//{

// a=a+1;

//}

public Check(){

a=a+1;

}

}

 

 

二,动手动脑

1,以下代码为何无法通过编译?哪出错了?

public class text2{

 public static void main(String[] args){

  Foo obj1=new Foo();

 }

}

class Foo{

int value;

public Foo(int initValue){

value=initValue;

}

}

因为用户自己定义了一个构造方法,所以系统不再提供默认的构造方法,所以类Foo中没有无参的构造方法,而新建立的对象没有参数。

2,运行程序观察结果,总结“静态初始化块的执行顺序”

运行结果如下:

Root的静态初始化块

Mid的静态初始化块

Leaf的静态初始化块

Root的普通初始化块

Root的无参数的构造器

Mid的普通初始化块

Mid的无参数的构造器

Mid的带参数构造器,其参数值:Java初始化顺序演示

Leaf的普通初始化块

执行Leaf的构造器

总结:

静态初始化块只在创建对象时执行一次;创建子类型的对象时,也会导致父类型的静态初始化块的执行;类的静态初始化块从父类开始先执行,然后执行子类的普通初始化块和构造方法。

 

推荐阅读