java的注解与反射

元注解

/**
 **  功能描述:基础元注解
 **            重点掌握 : Target   Retention
 **  @date 2021/2/18 9:57
 **  @return
 **/
// 表示我们的注解可以用在哪些地方
@Target(value = {ElementType.METHOD})
// 表示我们的注解在什么地方还有效
@Retention(value = RetentionPolicy.RUNTIME )
// 表示十分将我们的注解生成在JAVAdoc中
@Documented
// 表示子类可以继承父类的注解
@Inherited
public @interface Myannotation {
        String valve() default "";
}

自定义注解

自定义注解的使用

@Target(value = {ElementType.METHOD})
@Retention(value = RetentionPolicy.RUNTIME )
@interface Myannotation {
        String valve() default "";
        int id() default -1;
        double[] key() default {1L,2L};
}

public class MyannotationTest{
    @Myannotation(valve = "test" , id = 1 , key = {3L,4L})
    public void test(){
       
    }
}

反射(Reflection)

Reflection(反射)是java被视为动态语言的关键,反射机制允许程序在执行期借助于Reflection API取得任何类的内部信息。并能直接操作任意对象的内部属性及方法。

Class string = Class.forName('java.lang.String')

加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个歌对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以,就称之为:反射
在这里插入图片描述

优缺点

优点:
可以实现动态创建对象和编译,体现出很大的灵活性
缺点:
对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求,这类操作总是慢于直接执行相同的操作

反射相关的主要API

java.lang.Class:代表一个类
java.lang.reflect.Method:代表类的方法
java.lang.reflect.Field:代表类的成员变量
java.lang.reflect.Constructor:代表类的构造器

Class类
在Object类中定义了以下的方法,此方法将被所有子类继承

public final Class getClass()

以上的方法返回值的类型是一个class类,此类是java反射的源头,实际上所谓反射从程序的运行结果来看也很好理解,即:可以通过对象反射求出类的名称。

获取Class类的实例

1,已知某个类的实例,调用该实例的getClass()方法获取Class对象

        Class c1 = person.getClass();

2,已知一个类的全类名,且该类在类路径下,可通过class类的静态方法forName()获取,可能抛出ClassNotFoundException

        Class c2 = Class.forName("com.xiaojun.crm.Reflect.Stubent");

3,若已知具体的类,通过累的class属性获取,该方法最为安全可靠,程序性能最高。

    Class c3 = Stubent.class;

4,内置基本数据类型可以直接用类名.TYPE

    Class c4 = Integer.TYPE;

5,还可以利用ClassLoader

package com.xiaojun.crm.Reflect;

public class Test02 {
    public static void main(String[] args) throws ClassNotFoundException {
        Person person = new Person();
        System.out.println(person.name);
        // 方式一:通过对象获得
        Class c1 = person.getClass();
        System.out.println(c1.hashCode());
        // 方式二:forname获得
        Class c2 = Class.forName("com.xiaojun.crm.Reflect.Stubent");
        System.out.println(c2.hashCode());
        // 方式三:通过类名,class获得
        Class c3 = Stubent.class;
        System.out.println(c3.hashCode());
        // 方式四:基本内置类型的包装类都有一个Type属性
        Class c4 = Integer.TYPE;
        System.out.println(c4);
        // 获取父类类型
        Class c5 = c1.getSuperclass();
        System.out.println(c5);
    }
}
class Person{
    String name;
    public Person(String name) {
        this.name = name;
    }
    public Person() {
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
class Stubent extends Person{
    public Stubent() {
        this.name = "学生";
    }
}
class Teacherr extends Person{
    public Teacherr() {
        this.name = "老师";
    }
}

所有对象的class对象

        Class c1 = Object.class; // 类
        Class c2 = Comparable.class; //接口
        Class c3 = String[].class; // 一维数组
        Class c4 = int[][].class; // 二维数组
        Class c5 = Override.class; // 注解
        Class c6 = ElementType.class; // 枚举
        Class c7 = Integer.class; // 基本数据类型
        Class c8 = void.class; // void
        Class c9 = Class.class; // Class

        System.out.println(c1); //class java.lang.Object
        System.out.println(c2); //interface java.lang.Comparable
        System.out.println(c3); //class [Ljava.lang.String;
        System.out.println(c4); //class [[I
        System.out.println(c5); //interface java.lang.Override
        System.out.println(c6); //class java.lang.annotation.ElementType
        System.out.println(c7); //class java.lang.Integer
        System.out.println(c8); //void
        System.out.println(c9); //class java.lang.Class

通过反射,动态创建对象

        // 获得class对象
        Class c1 = Class.forName("com.xiaojun.crm.Reflect.User");

        // 构造一个对象
        User user = (User)c1.newInstance();//本质是调用了类的无参构造器
        System.out.println(user);

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

        // 通过反射调用普通方法
        User user3 = (User)c1.newInstance();
        // 通过反射获取一个方法
        Method setName = c1.getDeclaredMethod("setName", String.class);
        // invoke:激活
        // (对象,"方法的值")
        setName.invoke(user3,"王三");
        System.out.println(user3.getName());

        System.out.println("=========================");
        User user4 = (User)c1.newInstance();
        Field name = c1.getDeclaredField("name");
        // 不能直接操作私有属性,我们需关闭程序的安全检测,属性或者方法的setAccessible(true);
        name.setAccessible(true);
        name.set(user4,"王四");
        System.out.println(user4.getName());

反射操作泛型

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

public class Test04 {

    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 = Test04.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);
                }
            }
        }
        System.out.println("==============================");
        method = Test04.class.getMethod("test02",null);
        // 获取泛型
        Type genericReturnType = method.getGenericReturnType();
        System.out.println("##:"+genericReturnType);
        if (genericReturnType instanceof ParameterizedType){
            Type[] actualTypeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments();
            for ( Type actualTypeArgument : actualTypeArguments ) {
                System.out.println(actualTypeArgument);
            }
        }

    }
}

通过反射获取注解信息

public class AnnoAndReflect {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException {
        Class c1 = Class.forName("com.xiaojun.crm.Reflect.User2");
        // 通过反射获得注解
        Annotation[] annotations = c1.getAnnotations();
        for ( Annotation annotation : annotations ) {
            System.out.println(annotation);
        }
        Table table = (Table)c1.getAnnotation(Table.class);
        String value = table.value();
        System.out.println(value);

        // 获取类属性指定的注解
        Field field = c1.getDeclaredField("name");
        FiledCustomize annotation = field.getAnnotation(FiledCustomize.class);
        System.out.println(annotation.columnName());
        System.out.println(annotation.type());
        System.out.println(annotation.length());


    }
}
@Table("db_user2")
class User2{
    @FiledCustomize(columnName = "db_id", type = "int", length = 10)
    private int id;
    @FiledCustomize(columnName = "db_age", type = "int", length = 10)
    private int age;
    @FiledCustomize(columnName = "db_name", type = "varchar", length = 6)
    private String name;

    public User2() {
    }

    public User2(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 "User2{" +
                "id=" + id +
                ", age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
// 类名的注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Table{
    String value();
}
// 属性的注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@interface FiledCustomize{
    String columnName();
    String type();
    int length();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值