首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

Java 种的显性实例化

2012-08-25 
Java 类的显性实例化Java 类的显性实例化Java类的实例化具有显性和隐性的区别,我们编程时一般使用new方法

Java 类的显性实例化

Java 类的显性实例化

Java类的实例化具有显性和隐性的区别,我们编程时一般使用new方法直接实例化,这是最简单直接的显性实例化。另外还有三种实例化,分别为反射机制中的newInstance()方法,类的Clone()方法和解串行化使用的ObjecInputStream中的getObject()方法。

??? 在这里我主要讲一下java类显性实例化及其应注意的问题,隐性实例化的相关内容和问题会在以后补充上。

一、显的性实例化

直接使用new关键字实例化新的对象:

调用相应的构造函数完成实例化。(类中的非静态成员变量如果有初始化语句,都会被隐式的加入到构造函数中),具体如下:

?public?class?Test??{????

???????String?strA?=?"xyz";??

???????String?strB?;????????????

???????public?Test(String?str){??

????????????strB?=?str?;??

????????}??

??????public?static?void?main(String[]?args){??

??????????????Test?t?=?new?Test("abc");??

????}???

}??

在eclipse中装了ASM bytecode插件后,观察.class文件中的构造函数对应的字节码如下:

? INVOKESPECIAL?Object.<init>()?:?void??

???????ALOAD?0:?this??

???????LDC?"xyz"??

?????PUTFIELD?Test.strA?:?String??

????ALOAD?0:?this??

??????ALOAD?1:?str??

??????PUTFIELD?Test.strB?:?String??

??????RETURN??

关键在于LDC“xyz”这条指令,明显可以看出,这是用于strA初始化的字符串。

?

由此我们可以归纳出,在没有调用本类中的其他的构造函数的情况下,每次类的构造函数都会按如下的顺序进行:

a)隐式(或显性)的调用构造函数;

b)然后执行写在构造函数外的成员变量的初始化;

c)最后在执行构造函数中的命令。

?????? 如果是有显性的调用本类其他构造函数(必须是放在构造函数的第一步执行),那么对于这个构造函数,处理过程就简单些了:

a) 调用这个构造函数;

b)? 执行之后的代码。

? public?class?Test??{???????

?????String?strA?=?"xyz";??

?????String?strB?;??????????

??????public?Test(String?str){??

?????????this();??

???????}??

????????public?Test(){??

?????????strB?=?"mno";??

????}???????

???public?void?print(){??

?????????System.out.println(strB);??

??????}??????????

????public?static?void?main(String[]?args){??

??????????????Test?t?=?new?Test("abc");??

?????????????t.print();??

?????}??????

?}??

执行结果为:

mno??

?

?

至于为什么一定要将另外一个构造函数放在构造函数的第一步:必须先处理好heap中的变量初始化后才能下一步执行。

?

二、显性实例化中遇到的问题及解决

以上是对java类中的显性实例化的介绍,下面看看本人在写代码中遇到的问题,进一步认识显性实例化过程中应注意的问题,当然,可能只是涉及问题的某一部分,不足之处请加以谅解。

??? 在该程序中共有三个类,希望通过构造函数初始化的方法,把第一个类中的对象传给第二个类,第二个类再用同样的方法传给第三个类。

?

具体如下:(代码是模拟的,主要是为了简单明了,不保证可运行)

?

Public class First{

??? Public static void main(String []args ){

??????? First first = new First();

??????? first.test1();

}

//该方法实例化了一个对象,通过第二个类的构造函数传至第二个类中

Public void test1(){

??? String s = “student”;

??? System.out.println(“第一个类中的s打印值:”+s );

??? //初始化话第二个类,并通过构造函数传值s

??? Second second = new Second(s);

}

}

?

Public class Second{

??? Private String s;

Three three = new Three(s);

?

??? Public Second(String s){

??? This.s = s;

??? System.out.println(“第二个类中的s打印值:”+s );

}

}

?

Public class Three{

??? Private String s;

?

??? Public Three(String s){

this.s = s;

System.out.println(“第三个类中的s打印值:”+s );

}

}

如果运行上面的代码,则会得出下面的输出结果:

??? “第一个类中的s打印值:”student

“第三个类中的s打印值:”null

“第二个类中的s打印值:”student。

由此可见,测试的输出结果与我们的设计思路相反,第三个类的构造函数运行先于第二个类的构造函数,这是由于在第二个类中,由于显性实例化的缘故,Three three = new Three(s);的初始化在第二个类的构造函数之前,而此时Three的构造函数中传入的值还是空的,有与构造函数还没有执行的缘故。如此,程序虽然通过编译,但是运行时则会出现逻辑错误,而这个错误的排除,由于个人的思维定式,难度也就有所增加了。

那么,该如何去解决这个问题呢,很简单,根据显性实例化的特点,我们只需把作为第二个类中的变量 three的实例化,放到该类中的一个方法中,当需要实例化第三个类的变量,变传值的时候再调用该方法。具体如下:

Public class Second{

??? Private String s;

Three three;

?

??? Public Second(String s){

??? This.s = s;

??? System.out.println(“第二个类中的s打印值:”+s );

}

Public void test2(){

Three three = new Three(s);

}

}

?

?

热点排行