创建类对象

既然我们拿到了类的定义,那么是否可以通过Class对象来创建对象、调用方法、修改变量呢?当然是可以的,那我们首先来探讨一下如何创建一个类的对象:

  1. public static void main(String[] args) throws InstantiationException, IllegalAccessException {
  2. Class<Student> clazz = Student.class;
  3. Student student = clazz.newInstance();
  4. student.test();
  5. }
  6. static class Student{
  7. public void test(){
  8. System.out.println("萨日朗");
  9. }
  10. }

通过使用newInstance()方法来创建对应类型的实例,返回泛型T,注意它会抛出InstantiationException和IllegalAccessException异常,那么什么情况下会出现异常呢?

public static void main(String[] args) throws InstantiationException, IllegalAccessException {
    Class<Student> clazz = Student.class;
    Student student = clazz.newInstance();
    student.test();
}

static class Student{

    public Student(String text){

    }

    public void test(){
        System.out.println("萨日朗");
    }
}

当类默认的构造方法被带参构造覆盖时,会出现InstantiationException异常,因为newInstance()只适用于默认无参构造。

public static void main(String[] args) throws InstantiationException, IllegalAccessException {
    Class<Student> clazz = Student.class;
    Student student = clazz.newInstance();
    student.test();
}

static class Student{

    private Student(){}

    public void test(){
        System.out.println("萨日朗");
    }
}

当默认无参构造的权限不是public时,会出现IllegalAccessException异常,表示我们无权去调用默认构造方法。在JDK9之后,不再推荐使用newInstance()方法了,而是使用我们接下来要介绍到的,通过获取构造器,来实例化对象:

public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    Class<Student> clazz = Student.class;
    Student student = clazz.getConstructor(String.class).newInstance("what's up");
    student.test();
}

static class Student{

    public Student(String str){}

    public void test(){
        System.out.println("萨日朗");
    }
}

通过获取类的构造方法(构造器)来创建对象实例,会更加合理,我们可以使用getConstructor()方法来获取类的构造方法,同时我们需要向其中填入参数,也就是构造方法需要的类型,当然我们这里只演示了。那么,当访问权限不是public的时候呢?

public static void main(String[] args) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    Class<Student> clazz = Student.class;
    Student student = clazz.getConstructor(String.class).newInstance("what's up");
    student.test();
}

static class Student{

    private Student(String str){}

    public void test(){
        System.out.println("萨日朗");
    }
}

我们发现,当访问权限不足时,会无法找到此构造方法,那么如何找到非public的构造方法呢?

Class<Student> clazz = Student.class;
Constructor<Student> constructor = clazz.getDeclaredConstructor(String.class);
constructor.setAccessible(true);   //修改访问权限
Student student = constructor.newInstance("what's up");
student.test();

使用getDeclaredConstructor()方法可以找到类中的非public构造方法,但是在使用之前,我们需要先修改访问权限,在修改访问权限之后,就可以使用非public方法了(这意味着,反射可以无视权限修饰符访问类的内容)