注解和反射(三)类加载器、动态创建对象


注解和反射(三)类加载器、动态创建对象

目录
  • 注解和反射(三)类加载器、动态创建对象
    • 类加载器
      • 类加载器的作用
      • 获得类的信息
      • 动态创建对象
      • 对创建的对象进行操作(方法和属性)
        • 关闭程序的安全检测
      • 对方法操作
      • Object invoke(Object obj,Object[] args)
      • setAccessible(true)
    • 代码实例
      • 获得类的信息
      • 动态的创建对象
      • 对对象的方法和属性进行操作

类加载器

类加载器的作用

  • 将class文件的字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口

获得类的信息

  • 看实例

动态创建对象

  • 创建类的对象:调用Class的newInstance()方法
    • 类必须有一个无参数的构造器
    • 类的构造器的访问权限需要足够
  • 有参数的构造器实现创建:
    • 通过Class类的getDeclaredConstructor(Class ... parameterTypes)获得类的指定形参类型的构造器
    • 向构造器的形参中传递一个对象数组进去,里面包含了构造器中所需的各个参数
    • 通过Constructor实例化对象

对创建的对象进行操作(方法和属性)

  • 当对对象的属性进行操作时,要关闭程序的安全检测
关闭程序的安全检测
name.setAccessible(true);//true代表关闭安全检测

对方法操作

  1. 通过Class类的getDeclaredMethod(String name,Class ... parameterTypes)方法取得一个Method对象,并设置此方法操作时所需要的参数类型
  2. 之后使用Object invoke(Object obj,Object[] args)进行调用,并向方法中传递要设置的obj对象的参数信息

Object invoke(Object obj,Object[] args)

  • Object对应元原方法的返回值,若原方法无返回值,此时返回null
  • 若原方法为静态方法,此时形参Object obj可为null
  • 若原方法形参列表为空,则Object[] args为null
  • 若原方法声明为private,则需要在调用此invoke()方法前,显式调用方法对象的setAccessible(true)方法,将可访问private的方法(关闭安全检测)

setAccessible(true)

  • Method和Field、Constructor对象都有setAccessible()方法
  • setAccessible作用:启动和禁用访问安全检查的开关
  • 参数值为true则指示反射的对象在使用时应该取消Java语言访问检查
    • 提高反射效率,如果代码中必须用反射,而该句代码需要频繁的被调用,那么请设置为true
    • 使得原本无法访问的私有成员也可以访问
  • 参数值为false则指示反射的对象应该实施Java语言访问检查

代码实例

获得类的信息

public class Test04 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("com.reflect.User2");
        System.out.println("-----------获得类1-------------");
        //获得类的名字1
        System.out.println(c1.getName());//获得包名+类名
        System.out.println(c1.getSimpleName());//获得类名
        System.out.println("==获得类的属性=============================");
        //获得类的属性
        Field[] fields1=c1.getFields();//只能找到public属性
        Field[] fields2=c1.getDeclaredFields();//找到所有属性
        for (Field field : fields2) {
            System.out.println(field);
        }
        System.out.println("==获得指定属性=============================");
        //获得指定属性
        Field name=c1.getDeclaredField("name");
        System.out.println(name);
        System.out.println("==获得类的方法=============================");
        //获得类的方法
        Method[] m2 = c1.getMethods();//获得本类极其父类的全部方法
        Method[] m1 = c1.getDeclaredMethods();//获得本类的所有方法
        for (Method method : m1) {
            System.out.println(method);
        }
        System.out.println("==获得指定方法=============================");
        //获得指定方法
        Method getName = c1.getMethod("getName", null);
        Method setName = c1.getMethod("setName", String.class);//方法名,属性值
        System.out.println(getName);
        System.out.println(setName);
        System.out.println("==获得构造器=============================");
        //获得构造器
        Constructor[] d1 = c1.getConstructors();//获得public方法
        for (Constructor constructor : d1) {
            System.out.println(constructor);
        }
        Constructor[] d2 = c1.getDeclaredConstructors();//获得全部方法
        for (Constructor constructor : d2) {
            System.out.println(constructor);
        }
        System.out.println();
        System.out.println("==获得指定的构造器=============================");
        //获得指定的构造器
        Constructor d3 = c1.getDeclaredConstructor(String.class, int.class, int.class);
        System.out.println(d3);
        System.out.println("===============================");
        //获得类的名字2
        System.out.println("-----------获得类2-------------");
        Class c2 = Class.forName("com.reflect.User2");
        User2 user=new User2();
        c2=user.getClass();
        System.out.println(c2.getName());//获得包名+类名
        System.out.println(c2.getSimpleName());//获得类名
    }
}
//实体类
class User2{
    private String name;
    private int id;
    private int age;
    public User2(){

    }
    public User2(String name, int id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", age=" + age +
                '}';
    }
}
//输出:
-----------获得类1-------------
com.reflect.User2
User2
==获得类的属性=============================
private java.lang.String com.reflect.User2.name
private int com.reflect.User2.id
private int com.reflect.User2.age
==获得指定属性=============================
private java.lang.String com.reflect.User2.name
==获得类的方法=============================
public java.lang.String com.reflect.User2.toString()
public java.lang.String com.reflect.User2.getName()
public int com.reflect.User2.getId()
public void com.reflect.User2.setName(java.lang.String)
public void com.reflect.User2.setId(int)
public void com.reflect.User2.setAge(int)
public int com.reflect.User2.getAge()
==获得指定方法=============================
public java.lang.String com.reflect.User2.getName()
public void com.reflect.User2.setName(java.lang.String)
==获得构造器=============================
public com.reflect.User2()
public com.reflect.User2(java.lang.String,int,int)
public com.reflect.User2()
public com.reflect.User2(java.lang.String,int,int)

==获得指定的构造器=============================
public com.reflect.User2(java.lang.String,int,int)
===============================
-----------获得类2-------------
com.reflect.User2
User2

动态的创建对象

//动态创建对象,通过反射
public class Test05 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        //获得class对象
        Class c1 = Class.forName("com.reflect.User3");
        //构造一个对象(无参)
        User3 user=(User3) c1.newInstance();
        System.out.println(user);
        //构造一个对象(有参)
        //通过构造器创建对象
        Constructor c2 = c1.getDeclaredConstructor(String.class, int.class, int.class);
        User3 sxp = (User3) c2.newInstance("sxp", 001, 18);
        System.out.println(sxp);
    }
}
//实体类
class User3{
    private String name;
    private int id;
    private int age;
    public User3(){

    }
    public User3(String name, int id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", age=" + age +
                '}';
    }
}
//输出:
User{name='null', id=0, age=0}
User{name='sxp', id=1, age=18}

对对象的方法和属性进行操作

//动态创建对象,通过反射
public class Test06 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //获得class对象
        Class c1 = Class.forName("com.reflect.User4");
        //构造一个对象(无参)
        User4 user=(User4) c1.newInstance();
        System.out.println("==========通过反射操作方法============");
        //通过反射获取一个方法
        Method setName = c1.getDeclaredMethod("setName", String.class);
        //通过invoke激活方法
        //方法.invoke(对象,内容)
        setName.invoke(user,"史小鹏");//方法.invoke(对象,内容)
        System.out.println(user.getName());
        System.out.println("==========通过反射操作属性============");
        User4 user4 = (User4) c1.newInstance();
        //获取属性值
        Field name=c1.getDeclaredField("name");
        //不能直接操作私有属性,我们需要关闭程序的安全检测
        name.setAccessible(true);
        name.set(user4,"张三");//(对象,内容)
        System.out.println(user4.getName());
    }
}
//实体类
class User4{
    private String name;
    private int id;
    private int age;
    public User4(){

    }
    public User4(String name, int id, int age) {
        this.name = name;
        this.id = id;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", age=" + age +
                '}';
    }
}
//输出:
==========通过反射操作方法============
史小鹏
==========通过反射操作属性============
张三