浅谈利用反射(二)(框架设计的灵魂)技术获取类中的构造方法(基础版),并使用获取到构造方法实例化对象

实现步骤:

  1. 获取类的class文件对象(反射(一)中的任意一种方式)
  2. 使用class文件对象中的方法getConstructor / getConstructors获取类中的构造方法Constructor
  3. 使用构造方法Constructor类中的方法newInstance实例化对象(创建对象)

现在拆分开详细描述:

第一步:获取类的class文件对象

详见:https://blog.csdn.net/qq_45083975/article/details/91959244

第二步:使用class文件对象中的方法getConstructor / getConstructors获取类中的构造方法Constructor
  1. Constructor<?>[] getConstructors() 获取类中所有公共构造方法。
  2. Constructor<?>[] getDeclaredConstructors() 获取类声明的(私有,默认,受保护,公共)所有构造方法。
  3. Constructor getConstructor(Class<?>… parameterTypes) 获取类的指定公共构造方法。
  4. Constructor getDeclaredConstructor(Class<?>… parameterTypes) 获取类的指定(私有,默认,受保护,公共)构造方法。

参数说明:

         Class<?>… parameterTypes:传递构造方法参数的class文件对象,
         比如:int.class,double.class,String.class,Student.class
         可以理解为是可变参数:参数可以是任意个(不传,1个,多个)

第三步:使用构造方法Constructor类中的方法newInstance实例化对象(创建对象)

java.lang.reflect.Constructor类中的方法
          Constructor T newInstance(Object… initargs) 用于实例化对象
参数:
         Object… initargs:调用构造方法创建对象传递的实际参数 比如:张三 18
返回值:
         T:返回的就是创建好的对象,类型使用Object
那么假如需要获取私有的构造方法:private Person(String name, int age)呢?
         私有的构造方法我们没有权限运行,运行私有的构造方法,会抛出IllegalAccessException:非法访问异常
解决(了解):
         使用Constructor父类AccessibleObject里边的方法
         java.lang.reflect.AccessibleObject类中的方法
                  Constructor void setAccessible(boolean flag) 将此对象的 accessible 标志设置为指示的布尔值。
                  值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
                  值为 false 则指示反射的对象应该实施 Java 语言访问检查。
(上面的这种获取私有的构造方法的方式属于暴力反射,不推荐使用,因为它破坏了类的封装性

下面我们举例说明:(使用了@Test,可换为main方法)
package com.ccc.demo02Reflect;

import org.junit.Test;
import java.lang.reflect.Constructor;

public class Demo02Reflect {
    @Test
    public void demo01() throws Exception {

        //1.获取类的class文件对象(手术刀)
        Class clazz = Class.forName("com.ccc.demo03domain.Person");

        //2.使用class文件对象中的方法getConstructor/getConstructors获取类中的构造方法Constructor
        /*
            Constructor<?>[] getConstructors()  获取类中所有公共构造方法。
            Constructor<?>[] getDeclaredConstructors()  
            			获取类声明的(私有,默认,受保护,公共)所有构造方法。
         */
        Constructor[] cons = clazz.getConstructors();
        for(Constructor con : cons){
            System.out.println(con);
        }

        System.out.println("===============================");

        Constructor[] declaredCons = clazz.getDeclaredConstructors();
        for (Constructor declaredCon : declaredCons){
            System.out.println(declaredCon);
        }

        System.out.println("===============================");

        /*
            Constructor<T> getConstructor(Class<?>... parameterTypes)  
            						获取类的指定公共构造方法。
            Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)  
           							 获取类的指定(私有,默认,受保护,公共)构造方法。
            参数:
                Class<?>... parameterTypes:传递构造方法参数的class文件对象
                    比如:int.class,double.class,String.class,Student.class
                可变参数:参数可以是任意个(不传,1个,多个)
         */

        //获取 public Person()
        Constructor con1 = clazz.getConstructor();
        System.out.println(con1);	//输出 public com.ccc.demo03domain.Person()

        System.out.println("===============================");

        //获取 public Person(String name, int age, String sex)
        Constructor con2 = clazz.getConstructor(String.class, int.class, String.class);
        System.out.println(con2);
        //输出 public com.ccc.demo03domain.Person(java.lang.String,int,java.lang.String)

        System.out.println("===============================");

        //获取 private Person(String name, int age)
        Constructor con3 = clazz.getDeclaredConstructor(String.class, int.class);
        System.out.println(con3);
        //输出 private com.itheima.demo03domain.Person(java.lang.String,int)

        System.out.println("===============================");

        //3.使用构造方法Constructor类中的方法newInstance实例化对象(创建对象)

        //获取 public Person()
        Object obj1 = con1.newInstance();//就相当于 new Person();
        System.out.println(obj1);	//输出 Person{name='null', age=0, sex='null'}

        System.out.println("===============================");

        //获取 public Person(String name, int age, String sex)
        Object obj2 = con2.newInstance("张三", 18, "男");
        //上面这一句就相当于 new Person("张三", 18, "男");
        
        System.out.println(obj2);	//输出 Person{name='张三', age=18, sex='男'}

        System.out.println("===============================");

        /*
        获取 private Person(String name, int age)
            私有的构造方法我们没有权限运行,运行私有的构造方法,
            会抛出IllegalAccessException:非法访问异常
            解决:
                使用Constructor父类AccessibleObject里边的方法
                java.lang.reflect.AccessibleObject
                    void setAccessible(boolean flag) 
                    	将此对象的 accessible 标志设置为指示的布尔值。
                        值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
                        值为 false 则指示反射的对象应该实施 Java 语言访问检查。
            注意:
                暴力反射不推荐,破坏了类的封装性
         */
        //获取 private Person(String name, int age)
        con3.setAccessible(true);//取消访问的权限检查-->暴力反射
        Object obj3 = con3.newInstance("李四", 20);
        System.out.println(obj3);	//输出 Person{name='李四', age=20, sex='null'}
    }
}
Person类:
package com.ccc.demo03domain;

public class Person {
    private String name;
    private int age;
    private String sex;

    public Person() {
        System.out.println("Person类的空参数构造方法");
    }

    public Person(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        System.out.println("Person类的全参数构造方法");
    }

    private Person(String name, int age) {
        this.name = name;
        this.age = age;
        System.out.println("Person类的私有构造方法");
    }

    //私有方法
    private void method(){
        System.out.println("Person类的私有方法");
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }

    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;
    }

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_45083975/article/details/91960990
今日推荐