JAVA反射机制--Class类的作用

Class主要是反射的源头,不光可以取得对象所在类的信息,也可以通过Class类的方法进行对象的实例化操作,正常情况下,使用new关键字为对象实例化,如果现在已经实例化好了class对象,则就可以通过Class类中提供的newInstance()方法。

public T newInstance()throws InstantiationException, IllegalAccessException

package com.testClass;

class Person{
    private String name;
    private int age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "姓名:"+this.name+",年龄:"+this.age;
    }
}
public class InstanceDemo01 {
    public static void main(String args[]){
        Class c = null;//声明class对象
        try {
            c= Class.forName("com.testClass.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Person per =null;
        try {
            per = (Person) c.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        per.setName("张三");
        per.setAge(20);
        System.out.println(per);
    }
}

输出结果:

姓名:张三,年龄:20

通过以上代码,可以发现,即使不使用关键字new对象也可以进行实例化操作,但是,在使用以上操作的时候有一点要注意,在操作类中必须存在无参构造方法,否则无法实例化。

package com.testClass;

class Person{
    private String name;
    private int age;

    public Person(String name,int age){
        this.setName(name);
        this.setAge(age);
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "姓名:"+this.name+",年龄:"+this.age;
    }
}
public class InstanceDemo01 {
    public static void main(String args[]){
        Class c = null;//声明class对象
        try {
            c= Class.forName("com.testClass.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Person per =null;
        try {
            per = (Person) c.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        per.setName("张三");
        per.setAge(20);
        System.out.println(per);
    }
}

输出结果:

java.lang.InstantiationException: com.testClass.Person

at java.lang.Class.newInstance(Class.java:364)

at com.testClass.InstanceDemo01.main(InstanceDemo01.java:42)

Exception in thread "main" java.lang.NullPointerException

at com.testClass.InstanceDemo01.main(InstanceDemo01.java:48)

使用以上的方式实际上还是需要类中构造方法的支持,符合于对象的实例化要求。如果要想解决这样的问题,则必须明确的指定要调用的构造方法,并传递参数,但是从实际的开发角度讲,一般使用反射实例化对象的时候,类中都最好存在一个无参构造,这样的操作比较合理。

如果要想调用有参,则必须按照以下的步骤进行:

  1. 通过Class类中的getConstructors()取得本类中的全部构造方法。
  2. 向构造方法中传递一个对象数组进去,里面包含了构造方法中需的各个参数。
  3. 之后通过Constructor实例化对象。

在Constructor类中存在一个方法:

public T newInstance(Object... initargs)

              throws InstantiationException,

                     IllegalAccessException,

                     IllegalArgumentException,

                     InvocationTargetException

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

package com.testClass;

import java.lang.reflect.Constructor;

class Person{
    private String name;
    private int age;

    public Person(String name,int age){
        this.setName(name);
        this.setAge(age);
    }
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "姓名:"+this.name+",年龄:"+this.age;
    }
}
public class InstanceDemo01 {
    public static void main(String args[]){
        Class c = null;//声明class对象
        try {
            c= Class.forName("com.testClass.Person");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        Person per =null;
        Constructor constructor[]=null;
        constructor=c.getConstructors();
        try {
            per = (Person)constructor[0].newInstance("张三",18);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println(per);
    }
}

输出结果:

姓名:张三,年龄:18

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

总结:

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

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

你可能感兴趣的:(java)