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类完成,此类表示构造方法,并通过可变参数传递要求的内容。

  • 相关阅读:
    codeforces 57C 思维
    FOJ 2232 匈牙利算法找二分图最大匹配
    UVA 101 vector
    POJ 3070 矩阵mob
    codeforces 60B bfs
    codeforces 54A
    codeforces 466C 计数 codeforces 483B 二分 容斥
    FOJ 2213 简单几何
    CCF-最优配餐(BFS)
    杂论-FTP
  • 原文地址:https://www.cnblogs.com/alsf/p/6540001.html
Copyright © 2011-2022 走看看