JDK源码/轮子分析 :反射包 java.lang.reflect② 之 Constructor 获取类的实例对象

反射机制的概念

    在 前一篇中其实有提到过反射机制相关的概念了,只是没有正式说明,在这里我觉得有必需认真地说明一下。反射就是指在程序运行的时候,对于任何一个类,都可以得到这个类的属性或是方法;对于任何一个对象,都可以调用这个对象的方法和属性。(出自百度百科)

今天的主角:Constructor


    上一篇我们了解到每一个类的信息都有一个抽象的类--Class ,那么再细化下去,类中的构造方法这么重要且特别的存在也肯定有对应的东西去抽象它,那就是我们今天的主角 java.lang.reflect.Constructor<T>。
    它就是抽象我们的构造方法的,那么我们如何获得这个类的实例呢,通过查询 Class 类的方法可以得知有两个方法可以得到构造函数的对象:
         getConstructors() 和 getConstructor(Class<?>... parameterTypes)
    前都返回的是所有的构造方法对象,也是构造方法数组;后者则返回与 Class<?>... parameterTypes 相同入参的构造方法对象。

    在这里我建了两个测试类如下
package com.hlmtest.java.reflect;
public class TestClass {
      private String str1 ;
      private String str2 ;
     
      public TestClass(){}
      public TestClass(String str1 ,String str2 ){
            this . str1 = str1 ;
            this . str2 = str2 ;
           
     }
      public String getStr1() {
            return str1 ;
     }
      public void setStr1(String str1 ) {
            this . str1 = str1 ;
     }
      public String getStr2() {
            return str2 ;
     }
      public void setStr2(String str2 ) {
            this . str2 = str2 ;
     }
      public String toString(){
            return "str1:" + str1 + ";str2" + str2 ;           
     }
           
}
package com.hlmtest.java.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class TestAccessibleObject {
      /**
      * 启动类
      * @param args
      * @throws NoSuchMethodException
      * @throws SecurityException
      * @throws InvocationTargetException
      * @throws IllegalArgumentException
      * @throws IllegalAccessException
      * @throws InstantiationException
      */
      public static void main(String[] args ) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            getConstructor();  

     }
      /**
      * 获取构造方法演示
      * @throws NoSuchMethodException
      * @throws SecurityException
      */
      public static void getConstructor() throws NoSuchMethodException, SecurityException{
           Class<TestClass> clzz = TestClass. class ;
            @SuppressWarnings ( "rawtypes" )
            //构造方法数组
           Constructor[]  conList = clzz .getConstructors();
            for (Constructor<?> r : conList ){
                System. out .println( r .toGenericString());
           }          
            @SuppressWarnings ( "rawtypes" )
           Class[] str = {String. class ,String. class };
            //后者则返回两个及参对象的构造方法对象
           Constructor<TestClass> con = clzz .getConstructor( str );
           System. out .println( con .toGenericString());
           
            @SuppressWarnings ( "rawtypes" )
           Class[] str1 = {String. class ,String. class ,String. class };
            //没有入参为三个参数的构造方法,所以这里会报 NoSuchMethodException 错误,
            //为了能打印我在这里有预见性地把异常截住了
            try {
                 @SuppressWarnings ( "unused" )
                Constructor<TestClass> con1 = clzz .getConstructor( str1 );
                System. out .println( "没有入参为三个参数的构造方法!" );  
           } catch (NoSuchMethodException e ){
                System. out .println( e );     
                System. out .println( "没有入参为三个参数的构造方法!" );  
           }    
     }
}

执行 TestAccessibleObject的main 方法得到的结果为:
public com.hlmtest.java.reflect.TestClass()
public com.hlmtest.java.reflect.TestClass(java.lang.String,java.lang.String)
public com.hlmtest.java.reflect.TestClass(java.lang.String,java.lang.String)
java.lang.NoSuchMethodException : com.hlmtest.java.reflect.TestClass.<init>(java.lang.String, java.lang.String, java.lang.String)
没有入参为三个参数的构造方法!
    (Constructor类中还有很多其他方法,在些我就不一一举例了,毕竟今天的主要任务是通过构造方法的实例来获取主类的实例。大不了我在后面贴一下api的网址嘛

    下面的代码是在上面的代码基础上添加一个利用构造方法实例来获得主类实例对象的方法,为了方便直观看结果,我违反反射原则来给得到的实例设置属性方便打印信息(后面讲到相关类时会修改过来)。
package com.hlmtest.java.reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
public class TestAccessibleObject {
      /**
      * 启动类
      * @param args
      * @throws NoSuchMethodException
      * @throws SecurityException
      * @throws InvocationTargetException
      * @throws IllegalArgumentException
      * @throws IllegalAccessException
      * @throws InstantiationException
      */
      public static void main(String[] args ) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
            //getConstructor();  
            getInstanceByConstructor ();
     }
      /**
      * 通过构造方法实例来获取Class实例表示类的实例对象
      * @throws SecurityException
      * @throws NoSuchMethodException
      * @throws InvocationTargetException
      * @throws IllegalArgumentException
      * @throws IllegalAccessException
      * @throws InstantiationException
      */
      public static void getInstanceByConstructor() throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
            //先获取Constructor对象
           Class<TestClass> clzz = TestClass. class ;
            //先获取无参的构造方法对象
            @SuppressWarnings ( "rawtypes" )
           Class[] str1 = null ;
           Constructor<TestClass> con1 = clzz .getConstructor( str1 );
            //调用Constructor 的newInstance(Object... initargs ) 方法获得主对象实例
           TestClass obj1 = con1 .newInstance( str1 ) ;
            obj1 .setStr1( "我是obj1入参1" );
            obj1 .setStr2( "我是obj1入参2" );
           System. out .println( obj1 .toString());
           
            //获取有参的构造方法对象
            @SuppressWarnings ( "rawtypes" )
           Class[] str2 = {String. class ,String. class };
           Constructor<TestClass> con2 = clzz .getConstructor( str2 );
            //调用Constructor 的newInstance(Object... initargs ) 方法获得主对象实例
           TestClass obj2 = con2 .newInstance( "我是obj2入参1" , "我是obj2入参2" );
           System. out .println( obj2 .toString());
           
     }
      /**
      * 获取构造方法演示
      * @throws NoSuchMethodException
      * @throws SecurityException
      */
      public static void getConstructor() throws NoSuchMethodException, SecurityException{
           Class<TestClass> clzz = TestClass. class ;
            @SuppressWarnings ( "rawtypes" )
            //构造方法数组
           Constructor[]  conList = clzz .getConstructors();
            for (Constructor<?> r : conList ){
                System. out .println( r .toGenericString());
           }          
            @SuppressWarnings ( "rawtypes" )
           Class[] str = {String. class ,String. class };
            //后者则返回两个及参对象的构造方法对象
           Constructor<TestClass> con = clzz .getConstructor( str );
           System. out .println( con .toGenericString());
           
            @SuppressWarnings ( "rawtypes" )
           Class[] str1 = {String. class ,String. class ,String. class };
            //没有入参为三个参数的构造方法,所以这里会报 NoSuchMethodException 错误,
            //为了能打印我在这里有预见性地把异常截住了
            try {
                 @SuppressWarnings ( "unused" )
                Constructor<TestClass> con1 = clzz .getConstructor( str1 );
                System. out .println( "没有入参为三个参数的构造方法!" );  
           } catch (NoSuchMethodException e ){
                System. out .println( e );     
                System. out .println( "没有入参为三个参数的构造方法!" );  
           }    
     }
}

    打印信息为
str1:我是obj1入参1;str2我是obj1入参2
str1:我是obj2入参1;str2我是obj2入参2

    以上便是通过反射的方式,利用构造方法的实例来得到反射类的实例对象。

    Constructor 的更多API可以查询:

    20180528












猜你喜欢

转载自blog.csdn.net/mottohlm/article/details/80490118