Java中的注解和反射

反射和注解

反射

常用方法1

 @Test
    public void t1() {
        String str = "";
        System.out.println(str instanceof String);
        System.out.println(str.getClass() == String.class);   //直接判断是否为这个类型
//      如果需要判断是否为子类或是接口/抽象类的实现,我们可以使用asSubClass()方法:
        Integer i = 10;
        i.getClass().asSubclass(Number.class);   //当Integer不是Number的子类时,会产生异常
//      通过getSuperclass()方法,我们可以获取到父类的Class对象:
        System.out.println(i.getClass().getSuperclass());
//      通过getGenericSuperclass()获取父类的原始类型的Type:
        Type type = i.getClass().getGenericSuperclass();
        System.out.println(type);
        System.out.println(type instanceof Class);
    }

针对public 反射

    //    反射的方法
    @Test
    public void t2() throws Exception {
//        通过Class.forName()方法获取Class对象
        Class<?> clazz = Class.forName("ref.Stu");
//        使用getConstructor()方法来获取类的构造方法
        Constructor<?> constructor = clazz.getConstructor(String.class);
        Object instance = constructor.newInstance("what's up");
//        通过调用getMethod()方法,我们可以获取到类中所有声明为public的方法
        Method method = clazz.getMethod("test", String.class);   //通过方法名和形参类型获取类中的方法
//        我们可以通过Method对象的invoke()方法(返回值就是方法的返回值,因为这里是void,返回值为null)来调用已经获取到的方法,注意传参
        method.invoke(instance, "what's up");   //通过Method对象的invoke方法来调用方法
//        通过getField()方法来获取一个类定义的指定字段:
        Field field = clazz.getField("i");
        field.set(instance, 10);   //通过Field对象的set方法来设置属性值

    }

反射的目标类

class Stu {
    public int i;
    public Stu(String str) {
    }
    public void test(String str) {
        System.out.println("萨日朗" + str);
    }
}

针对private 反射

       @Test
    public void t3() throws Exception {


//        处理私有构造器,私有方法
        Class<?> clazz2 = Class.forName("ref.Stu2");
//        使用getDeclaredConstructor()方法可以找到类中的非public构造方法
        Constructor<?> declaredConstructor = clazz2.getDeclaredConstructor(String.class);
//        但是在使用之前,我们需要先修改访问权限
        declaredConstructor.setAccessible(true);
        Object instance1 = declaredConstructor.newInstance("what's up");
//        使用getDeclaredMethod()方法可以找到类中的非public方法
        Method declaredMethod = clazz2.getDeclaredMethod("test", String.class);
//        Method method = clazz.getDeclaredMethod("test", String[].class);   //如果方法的形参是数组,我们需要使用数组的Class对象
//        同样,我们需要先修改访问权限
        declaredMethod.setAccessible(true);
//        调用invoke()方法
        declaredMethod.invoke(instance1, "what's up");
//        使用getDeclaredField()方法可以找到类中的非public字段
        Field field1 = clazz2.getDeclaredField("i");
//        同样,我们需要先修改访问权限
        field1.setAccessible(true);
//        调用set()方法
        field1.set(instance1, 10);
    }

反射的目标类

class Stu2 {
    private int i;
    private Stu2(String str) {
    }
    private void test(String str) {
        System.out.println("萨日朗" + str);
    }
}

针对注解

无论是方法、类、还是字段,都可以使用getAnnotations()方法(还有几个同名的)来快速获取我们标记的注解。

    //    反射获取注解
    @Test
    public void t4() throws Exception {
        Class<?> clazz = Class.forName("ref.Stu");
        Method method = clazz.getMethod("test", String.class);
        Annotation[] annotations = method.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
        Annotation annotation = method.getAnnotation(Test.class);
        System.out.println(annotation);

    }

注解

常见注解

  1. JDK预设了以下注解,作用于代码:
  • @Override - 检查(仅仅是检查,不保留到运行时)该方法是否是重写方法。如果发现其父类,或者是引用的接口中并没有该方法时,会报编译错误。
  • @Deprecated - 标记过时方法。如果使用该方法,会报编译警告。
  • @SuppressWarnings - 指示编译器去忽略注解中声明的警告(仅仅编译器阶段,不保留到运行时)
  • @FunctionalInterface - Java 8 开始支持,标识一个匿名函数或函数式接口。
  • @SafeVarargs - Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告。

元注解

元注解是作用于注解上的注解,用于我们编写自定义的注解:

  • @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。
  • @Documented - 标记这些注解是否包含在用户文档中。
  • @Target - 标记这个注解应该是哪种 Java 成员。
  • @Inherited - 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)
  • @Repeatable - Java 8 开始支持,标识某注解可以在同一个声明上使用多次。

自定义注解

//自定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@interface Test2 {
    String value() default "都看到这里了,给个三连吧!";
//     String[] value();也可以是数组
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值