反射机制Reflection _ 4.创建运行时类的对象

获取运行时类的完整结构

通过反射获取运行时类的完整结构:

Field,Method,Constructor,Superclass,Interface,Annotation

package com.company.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

//获得类的信息
public class test09 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException {
        Class c1 = Class.forName("com.company.reflection.User");

        //获取类的名字
        System.out.println(c1.getName()); //获得包名+类名
        System.out.println(c1.getSimpleName()); //获得类名

        //获得类的属性
        Field[] fields = c1.getFields();  //只能找到public属性

        fields = c1.getDeclaredFields();  //找到全部属性
        for(Field field:fields) {
            System.out.println(field);
        }

        //获得指定属性的值
        Field name = c1.getDeclaredField("name");
        System.out.println(name);

        //获得类的方法
        Method[] methods = c1.getMethods();  //获得本类及其父类的所有方法
        for(Method method:methods) {
            System.out.println("正常的:"+method);
        }
        methods = c1.getDeclaredMethods();  //获得本类的所有方法
        for(Method method:methods) {
            System.out.println("getDeclaredMethods:"+method);
        }

        //获得指定方法
        Method getName = c1.getMethod("getName",null);
        Method setName = c1.getMethod("setName", String.class);
        System.out.println(getName);
        System.out.println(setName);

        //获得指定的构造器
        Constructor[] constructors = c1.getConstructors();
        for(Constructor constructor:constructors) {
            System.out.println("getConstructors:"+constructor);
        }
        constructors = c1.getDeclaredConstructors();
        for(Constructor constructor:constructors) {
            System.out.println("getDeclaredConstructors"+constructor);
        }

        //获得指定的构造器
        Constructor declaredConstructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        System.out.println("指定的构造器:"+declaredConstructor);
    }
}

动态创建对象执行方法
  • 创建类的对象:调用Class对象的newInstance()方法

    • 类必须有无参构造器
    • 类的构造器必须有足够的权限
  • 如果没有无参构造器,我们需要明确调用类中的构造器,并将参数传递进去,进行实例化。步骤如下:

    • 通过Class类的getDeclaredConstructor(Class...parameterTypes)获取本类指定形参构造器
    • 向构造器的形参中传递一个对象数组进去,里面包含了构造器所需的参数
    • 通过Constructor来实例化对象

通过反射,调用类中的方法,通过Method类完成:

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

    • Object对应原方法的返回值,若无返回值则返回null
    • 原方法若为静态方法,则形参Object obj可为null
    • 原方法的参数列表为空,则Object[] args可为null
    • 原方法声明为private则需要在调用invoke()前,显式调用方法对象的setAccessible(true)方法,然后可以访问private方法
  • SetAccessible

    • Method,Field,Constructor对象都有SetAccessible方法
    • SetAccessible方法的作用是启用或禁用安全访问检查的开关
    • 参数设置为true,反射对象取消Java语言访问检查
      • 提高反射效率,反射代码频繁调用,设置为true可以提示效率
      • 使得原本无法访问的私有成员也可以访问
    • 参数设置为false,反射对象实施Java语言访问检查
package com.company.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

//通过反射动态创建对象
public class test10 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //获得Class对象
        Class c1 = Class.forName("com.company.reflection.User");

        //构造一个对象
        User user = (User) c1.newInstance();
        System.out.println(user);

        //通过构造器创建对象
        Constructor constructor = c1.getDeclaredConstructor(String.class, int.class, int.class);
        User user2 = (User) constructor.newInstance("ZZ", 001, 18);
        System.out.println(user2);

        //通过反射调用不同方法
        User user3 = (User) c1.newInstance();
        //通过反射获取一个方法
        Method setName = c1.getMethod("setName", String.class);

        //invoke: 激活的意思
        //(对象,“方法的值”)
        setName.invoke(user3, "SS");
        System.out.println(user3);

        //通过反射操作属性
        User user4 = (User) c1.newInstance();
        Field name = c1.getDeclaredField("name");

        //不能直接操纵私有属性,我们需要关闭程序的安全检测,通过 属性或者方法.setAccessible(true)
        name.setAccessible(true);
        name.set(user, "AA");
        System.out.println(user4.getName());
    }
}

反射操作泛型
  • Java采用泛型擦除的机制来引入泛型,Java中的泛型仅仅javac是给编译器使用的,确保数据的安全性和免去强制类型转换问题,但是,一旦编译完成,所有和泛型有关的类型全部擦除
  • 为了通过反射操作这些类型,Java新增了ParameterizedTypeGenericArrayTypeTypeVariableWildcardType几种类型来代表不能被归一到 Class类中的类型但是又和原始类型齐名的类型
  • ParameterizedType:表示一种参数化类型,比如Collection
  • GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型
  • TypeVariable:是各种类型变量的公共父接口
  • WildcardType:代表一种通配符类型表达式
package com.company.reflection;

import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

//通过反射获取泛型
public class test11 {

    public void test01(Map<String,User> map, List<User> list) {
        System.out.println("test01");
    }

    public Map<String, User> test02() {
        System.out.println("test02");
        return null;
    }

    public static void main(String[] args) throws NoSuchMethodException {
        Method method = test11.class.getMethod("test01", Map.class, List.class);
        Type[] genericParameterTypes = method.getGenericParameterTypes();
        for(Type genericParameterType:genericParameterTypes) {
            System.out.println(genericParameterType);
            if(genericParameterType instanceof ParameterizedType) {
                Type[] actualTypeArgumrnts = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for(Type actualTypeArgumrnt:actualTypeArgumrnts) {
                    System.out.println(actualTypeArgumrnt);
                }
            }
        }

        method = test11.class.getMethod("test02", null);
        Type genericReturnType = method.getGenericReturnType();
        if(genericReturnType instanceof ParameterizedType) {
            Type[] actualTypeArgumrnts = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for(Type actualTypeArgumrnt:actualTypeArgumrnts) {
                System.out.println(actualTypeArgumrnt);
            }
        }
        /*
        1. 获取当前类
        2. 获取目标字段
        3. 获取包含泛型类型的类型 getGenericType()
        4. 强转至子类ParameterizedType因为Type没有任何对应的方法
        5. 获得泛型真正的类型getActualTypeArguments()
         */
    }
}
反射操作注解

练习:

  • ORM:Object Relationship Mapping 对象关系映射

    • 类和表结构对应
    • 属性和字段对应
    • 对象和记录对应
  • 利用注解和反射完成类和表的结构的映射关系

package com.company.reflection;

import java.lang.annotation.*;
import java.lang.reflect.Field;

//练习反射操作注解
public class test12 {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("com.company.reflection.Student2");

        //通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for(Annotation annotation:annotations) {
            System.out.println(annotation);
        }

        //获得注解的value值
        Table1 table = (Table1) c1.getAnnotation(Table1.class);
        String value = table.value();
        System.out.println(value);

        //获得类指定的注解
        Field f = c1.getDeclaredField("name");
        Field1 annotation = f.getAnnotation(Field1.class);
        System.out.println(annotation.columName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());
    }
}

@Table1("db_student")
class Student2 {

    @Field1(columName = "db_name", type = "varchar", length = 3)
    private String name;
    @Field1(columName = "db_id", type = "int", length = 10)
    private int id;
    @Field1(columName = "db_age", type = "int", length = 10)
    private int age;

    public Student2() {

    }

    public Student2(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 "Student2{" +
                "name='" + name + '\'' +
                ", id=" + id +
                ", age=" + age +
                '}';
    }
}

//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table1 {
    String value();
}

//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface  Field1 {
    String columName();
    String type();
    int length();
}
posted @ 2021-03-03 13:49  又又又8  阅读(118)  评论(0编辑  收藏  举报