通过反射操作泛型和注解

总结

  • 在实际的操作中,取得类的信息的操作代码,并不会经常开发。

  • 一定要熟悉java.lang.reflect包的作用,反射机制。

  • 如何取得属性、方法、构造器的名称,修饰符等。

1.1、有了Class对象能做什么

创建类的对象:调用Class对象的newInstance()方法

  1. 类必须要有一个无参数的构造器。

  2. 类的构造器的访问权限需要足够。

难道没有无参构造器就不能创建对象了吗?只要在操作的时候明确的调用类中的构造器,并将参数传递进去之后,才可以实例化操作。

步骤如下:

  1. 通过Class类的getDeclaredConstructors(Class...parameterTypes)取得本类的指定形参类型的构造器

  2. 向构造器的形参传递一个对象数组进去,里面包含了构造器中所需的各个参数。

  3. 通过Constructors实例化对象

调用方法

  1. 通过反射,调用类中的方法,通过getMethod完成。

  2. 通过invoke

invoke(对象,"方法的值")

setAccessible

  • Method和Field、Constructors对象都有setAccessible()方法。

  • setAccessible作用是启动和禁用访问安全检查的开关。

  • 参数值为true则指示反射的对象在使用时应该取消Java语言访问检查。

    • 提高反射的效率。如果代码中必须用反射,而该句代码需要频繁的被调用,那么设置为true。

    • 使得原本无法访问的私有成员也可以访问

  • 参数值为false则指示反射的对象应该实施Java语言访问检查

测试代码,测试性能

复制代码
//分析性能问题
public class Test10 {
​
    //普通方式调用
    public static void test01(){
        User user = new User();
​
        long startTime = System.currentTimeMillis();
​
        for (int i = 0; i < 1000000000; i++) {
            user.getName();
        }
​
​
        long endTime = System.currentTimeMillis();
​
        System.out.println("普通方式执行10亿次:"+(endTime - startTime) + "ms");
​
    }
    //反射方式调用
    public static void test02() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();
​
        Method getName = c1.getMethod("getName", null);
​
        long startTime = System.currentTimeMillis();
​
        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user,null);
        }
​
​
        long endTime = System.currentTimeMillis();
​
        System.out.println("反射方式执行10亿次:"+(endTime - startTime) + "ms");
​
    }
​
    //反射方式调用 关闭检测
    public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c1 = user.getClass();
​
        Method getName = c1.getMethod("getName", null);
        getName.setAccessible(true);//关闭权限检测
long startTime = System.currentTimeMillis();
​
        for (int i = 0; i < 1000000000; i++) {
            getName.invoke(user,null);
        }
​
​
        long endTime = System.currentTimeMillis();
​
        System.out.println("关闭检测执行10亿次:"+(endTime - startTime) + "ms");
​
    }
​
    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        test01();
        test02();
        test03();
    }
​
}
复制代码

 

结果

普通方式执行10亿次:0ms 反射方式执行10亿次:1132ms 关闭检测执行10亿次:621ms

反射操作泛型

  • Java采用泛型擦除的机制来引入泛型,Java中的泛型仅仅是给编译器Javac使用 的,确保数据的安全性和免去强制类型转换问题 ,但是一旦编译完成,所有和泛型有关的类型全部擦除。

  • 为了通过反射操作这些类型,Java新增了ParameterizedType,GenericArrayType,TypeVariable和WildcardType几种类型来代表不能被归一到Class类中的类型但是又和原始类型齐名的类型。

ParameterizedType:表示一种参数化类型,比如Collection<String>

GenericArrayType:表示一种元素类型是参数化类型或者类型变量的数组类型

TypeVariable:是各种类型变量的公共父接口

WildcardType:代表一种通配符类型表达式

测试代码

复制代码
//通过反射获取泛型
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[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments();
                for (Type actualTypeArgument : actualTypeArguments) {
                    System.out.println(actualTypeArgument);
                }
            }
        }
        method = Test11.class.getMethod("test02", null);
        Type genericReturnType = method.getGenericReturnType();
​
        if(genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for (Type actualTypeArgument : actualTypeArguments) {
                System.out.println(actualTypeArgument);
            }
        }
    }
}
复制代码

 

获取注解信息

通过反射操作注解

getAnnotations

getAnnotation

ORM

Object relationship Mapping——>对象关系映射

  • 类和表结构对应

  • 属性和字段对应

  • 对象和记录对应

利用注解和反射完成类和表结构读到映射关系。

测试代码

复制代码
//练习反射操作注解
public class Test12 {
​
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("com.kuang.reflection.Student2");
​
        //通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
​
        //获得注解的value的值
        Table table = (Table)c1.getAnnotation(Table.class);
        String value = table.value();
        System.out.println(value);
​
        //获得类指定的注解
        java.lang.reflect.Field f = c1.getDeclaredField("id");
        Field annotation = f.getAnnotation(Field.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());
    }
​
}
​
@Table("db_student")
class Student2{
​
    @Field(columnName = "db_id",type = "int",length = 10)
    private int id;
    @Field(columnName = "db_age",type = "int",length = 10)
    private int age;
    @Field(columnName = "db_name",type = "varchar",length = 3)
    private String name;
​
    public Student2() {
    }
​
    public Student2(int id, int age, String name) {
        this.id = id;
        this.age = age;
        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;
    }
​
    public String getName() {
        return name;
    }
​
    public void setName(String name) {
        this.name = name;
    }
​
    @Override
    public String toString() {
        return "Student2{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
​
​
//类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
    String value();
}
​
//属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface Field{
    String columnName();
    String type();
    int length();
}
复制代码

 

 
posted @   Resign~as  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示