`
Mr.Zhong
  • 浏览: 11344 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
最近访客 更多访客>>
社区版块
存档分类
最新评论

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  

关键在于LDCxyz”这条指令,明显可以看出,这是用于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);

}

}

 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics