zoukankan      html  css  js  c++  java
  • 反射机制2,Class类的使用

    class是反射源头,不光可以取得对象所在类信息,也可直接通过class类的方法进行对象的实例化操作。

    使用关键字new为对象实例化。如果已经实例化好了class对象,就可以通过class类中提供的newInstance()操作 

    public T newInstance()
                  throws InstantiationException,
                         IllegalAccessException

    来个例子:

    package 类集;
    
    class Person{
        private String name ;    // name属性
        private int age ;        // age属性
        public void setName(String name){
            this.name = name ;
        }
        public void setAge(int age){
            this.age = age ;
        }
        public String getName(){
            return this.name ;
        }
        public int getAge(){
            return this.age ;
        }
        public String toString(){    // 覆写toString()方法
            return "姓名:" + this.name + ",年龄:" + this.age  ;
        }
    };
    public class test1{
        public static void main(String args[]){
            Class<?> c = null ;        // 声明Class对象
            try{
                c = Class.forName("类集.Person") ;
            }catch(ClassNotFoundException e){
                e.printStackTrace() ;
            }
            Person per = null ;    // 声明Person对象
            try{
                per = (Person)c.newInstance() ;    // 实例化对象
            }catch(Exception e){
                e.printStackTrace() ;
            }
            per.setName("小明") ;        // 设置姓名
            per.setAge(23) ;                // 设置年龄
            System.out.println(per) ;    // 内容输出,调用toString()
        }
    }

    返回结果:

    姓名:小明,年龄:23

    上面的newInstance返回的类型是一个泛型,但是Class<?> c可知,这个类型是一个“?”,实际上是一个object类型,

    所以需要向下转型,(Person)c.newInstance()

    通过以上代码发现,即使不使用new关键字也能进行实例化操作,反射作用。

    但是,使用以上操作,必须注意:在操作中,类中必须存在无参构造方法。否则无法实例化。

    例如:

    package 类集;
    
    class Person{
        private String name ;    // name属性
        private int age ;        // age属性
        public Person(String name,int age){
            this.setName(name) ;
            this.setAge(age);
        }
        public void setName(String name){
            this.name = name ;
        }
        public void setAge(int age){
            this.age = age ;
        }
        public String getName(){
            return this.name ;
        }
        public int getAge(){
            return this.age ;
        }
        public String toString(){    // 覆写toString()方法
            return "姓名:" + this.name + ",年龄:" + this.age  ;
        }
    };
    public class test1{
        public static void main(String args[]){
            Class<?> c = null ;        // 声明Class对象
            try{
                c = Class.forName("类集.Person") ;
            }catch(ClassNotFoundException e){
                e.printStackTrace() ;
            }
            Person per = null ;    // 声明Person对象
            try{
                per = (Person)c.newInstance() ;    // 实例化对象
            }catch(Exception e){
                e.printStackTrace() ;
            }
            per.setName("李兴华") ;        // 设置姓名
            per.setAge(30) ;                // 设置年龄
            System.out.println(per) ;    // 内容输出,调用toString()
        }
    }

    结果;

    java.lang.InstantiationException: 类集.Person
        at java.lang.Class.newInstance(Class.java:427)
        at 类集.test1.main(test1.java:36)
    Caused by: java.lang.NoSuchMethodException: 类集.Person.<init>()
        at java.lang.Class.getConstructor0(Class.java:3082)
        at java.lang.Class.newInstance(Class.java:412)
        ... 1 more
    Exception in thread "main" java.lang.NullPointerException
        at 类集.test1.main(test1.java:40)

      所以发现,使用以上方式,实际上还是需要无参构造方法的支持。符合于对象实例化要求。(实际上跟正常实例化new 类()方式一样,调用构造方法)。

    要想解决这样问题,则必须明确指定要调用的构造方法,并且传递参数。从实际开发角度,一般使用反射实例化对象的时候,类中最好存在一个无参构造,比较合理。

    操作步骤如下:

    1,通过class类中的getConstructors()取得本类中全部构造方法,返回的结果是一个数组,见下面例子

    2,向构造方法中传递一个对象数组进去,里面保护构造方法所需要的各个参数。

    3,之后通过Constructor实例化对象

    在constructor类中存在方法newInstance(),

    public T newInstance(Object... initargs)
                  throws InstantiationException,
                         IllegalAccessException,
                         IllegalArgumentException,
                         InvocationTargetException

    传递初始化参数,以进行对象的实例化操作。

    明确调用有参构造,实例化对象

    package 类集;
    
    import java.lang.reflect.Constructor;
    
    class Person{
        private String name ;    // name属性
        private int age ;        // age属性
        public Person(String name,int age){
            this.setName(name) ;
            this.setAge(age);
        }
        public void setName(String name){
            this.name = name ;
        }
        public void setAge(int age){
            this.age = age ;
        }
        public String getName(){
            return this.name ;
        }
        public int getAge(){
            return this.age ;
        }
        public String toString(){    // 覆写toString()方法
            return "姓名:" + this.name + ",年龄:" + this.age  ;
        }
    };
    public class test1{
        public static void main(String args[]){
            Class<?> c = null ;        // 声明Class对象
            try{
                c = Class.forName("类集.Person") ;
            }catch(ClassNotFoundException e){
                e.printStackTrace() ;
            }
            Person per = null ;    // 声明Person对象
            Constructor<?> cons[] = null ;//返回的是一个数组。
            cons = c.getConstructors() ;//取得所有构造方法
            try{
                per = (Person)cons[0].newInstance("校华",18) ;    // 实例化对象,因为只有一个构造方法,所以使用第一个构造方法,也就是cons[0],通过newInstance("",“”)传给构造方法
        别忘了后面还要向下转型,因为返回结果是object类型
    }catch(Exception e){ e.printStackTrace() ; } System.out.println(per) ; // 内容输出,调用toString() } }

    运行结果:

    姓名:校华,年龄:18

    注意:接收的原理如下:

    但是,如果要使用反射进行对象的实例化操作,最好在类中存在无参数构造

    总结:

    1,本周功能是class用的最多的功能,而且开发中也会经常用到的模式

    2,在使用class实例化对象的时候,必须保证类中存在无参构造,否则无法使用。

    3,如果要想调用有参构造进行对象的实例化操作,必须使用constructor类完成,此类表示构造方法,并通过可变参数传递要求的内容。

  • 相关阅读:
    Java实现各种内部排序算法
    Java实现堆排序(大根堆)
    Java对象的序列化和反序列化
    Java实现链式存储的二叉查找树(递归方法)
    337. House Robber III(包含I和II)
    318. Maximum Product of Word Lengths
    114. Flatten Binary Tree to Linked List
    106. Construct Binary Tree from Inorder and Postorder Traversal
    105. Construct Binary Tree from Preorder and Inorder Traversal
    96. Unique Binary Search Trees(I 和 II)
  • 原文地址:https://www.cnblogs.com/alsf/p/6540001.html
Copyright © 2011-2022 走看看