Java之美-注解和反射

注解

注解定义

Annotation (注解) 是 Java5 开始引入的新特性,可以看作是一种特殊的注释,主要用于修饰类、方法或者变量,提供某些信息供程序在编译或者运行时使用。但是注解并不是所装饰代码的一部分,它对代码的运行效果没有直接影响,由编译器决定该执行哪些操作

Java所有的注解,默认实现Annotation接口

package java.lang.annotation; 
public interface Annotation { 

boolean equals(Object obj); 

int hashCode(); String toString();

 Class<? extends Annotation> annotationType();
 
 }

元注解

  • 元注解是注解的注解,是一张特殊的标签,即标签的标签。
  • 元注解是用于给其他普通标签进行解释说明的。
  • 元标签有:@Retention, @Documented, @Targrt, @Inherited, @Repeatable 共5种。

@Retention

注解的生命周期有 3 种策略,定义在 RetentionPolicy 枚举中。

  • SOURCE:在源文件中有效,在编译阶段被编译器丢弃。
  • CLASS:注解只被保留到编译进行的时,在编译器生成的字节码文件中有效,但在运行时会被处理类文件的 JVM 丢弃。
  • RUNTIME:注解可以保留到程序运行的时候,在运行时有效。这也是注解生命周期中最常用的一种策略,它允许程序通过反射的方式访问注解,并根据注解的定义执行相应的代码。

@Documented

该注解将被包含在javadoc中

@Targrt

注解标记另一个注解,以限制可以应用注解的 Java 元素类型。目标注解指定以下元素类型之一作为其值:

  • ElementType.ANNOTATION_TYPE 可以应用于注解类型。
  • ElementType.CONSTRUCTOR 可以应用于构造函数。
  • ElementType.FIELD 可以应用于字段或属性。
  • ElementType.LOCAL_VARIABLE 可以应用于局部变量。
  • ElementType.METHOD 可以应用于方法级注解。
  • ElementType.PACKAGE 可以应用于包声明。
  • ElementType.PARAMETER 可以应用于方法的参数。
  • ElementType.TYPE 可以应用于类的任何元素。

@Inherited

子类可以继承父类中的该注解

@Repeatable

用于标注可重复的注解。

如下所示:
Logme

package dynamic.annotation;

import java.lang.annotation.*;

/**
 * @author yangmiao
 */
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Logme {
    String value() default "";
    Class<?> clz();
}

反射

参考文档:

通过反射你可以获取任意一个类的所有属性和方法,你还可以调用这些方法和属性。

优缺点

缺点:

  • 破坏封装:由于反射允许访问私有字段和私有方法,所以可能会破坏封装而导致安全问题。
  • 性能开销:由于反射涉及到动态解析,因此无法执行 Java 虚拟机优化,再加上反射的写法的确要复杂得多,所以性能要比“正射”差很多,在一些性能敏感的程序中应该避免使用反射。

优点:

  • 可以实现动态创建对象和编译,体现出很大的灵活性。

应用场景

  • 开发通用框架:像 Spring,为了保持通用性,通过配置文件来加载不同的对象,调用不同的方法。
  • 动态代理:在面向切面编程中,需要拦截特定的方法,就会选择动态代理的方式,而动态代理的底层技术就是反射。
  • 注解:注解本身只是起到一个标记符的作用,它需要利用发射机制,根据标记符去执行特定的行为。

创建对象

  • 使用newInstance()方法。
  • 反射获取构造函数,使用构造函数的方式创建对象。用 Constructor 对象的 newInstance() 方法

Class 对象提供了以下方法来获取构造方法 Constructor 对象:

  • getConstructor():返回反射类的特定 public 构造方法,可以传递参数,参数为构造方法参数对应 Class 对象;缺省的时候返回默认构造方法。
  • getDeclaredConstructor():返回反射类的特定构造方法,不限定于 public 的。
  • getConstructors():返回类的所有 public 构造方法。
  • getDeclaredConstructors():返回类的所有构造方法,不限定于 public 的。

属性操作

  • getField(String name) 获取某个public类型的属性
  • getFields() 获取所有的public类型的属性
  • getDeclaredField(String name) 获取某个属性对象
  • getDeclaredFields() 获取所有的属性对象

函数操作

  • getMethod(String name, Class…<?> parameterTypes) 获取与参数类型匹配的public类型的函数
  • getMethods() 获取所有的public类型的函数(包含继承的函数)
  • getDeclaredMethod(String name, Class…<?> parameterTypes) 获取与参数类型匹配的所有函数
  • getDeclaredMethods() 获取所有的函数

Demo

User

package dynamic.annotation;

/**
 * @Author: Yangmiao
 * @Date: 2022/10/21 19:48
 * @Desc:
 */
@Logme(value = "print me",clz = User.class)
public class User {

    private String userName;

    private String password;

    public void setPassword(String password) {
        this.password = password;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public String getUserName() {
        return userName;
    }

    private String addStr(String userName,String password){
        return userName+"_"+password;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

TestAnnotation

package dynamic.annotation;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

/**
 * @Author: Yangmiao
 * @Date: 2022/10/21 19:50
 * @Desc:
 */
public class TestAnnotation {

    public static void main(String[] args) {
        User user = new User();
        user.setPassword("1323");
        user.setUserName("yyyy");

        Class<? extends User> userClass = user.getClass();
        Logme logme = userClass.getAnnotation(Logme.class);
        String value = logme.value();
        Class<?> clz = logme.clz();

        System.out.println("value: "+value+" clz: "+clz);

        System.out.println("constructor: "+userClass.getConstructors());

        for (Field field:userClass.getDeclaredFields()) {
            System.out.println("field: "+field);
        }

        try {
            Class<?> userTemp = Class.forName("dynamic.annotation.User");
//            for (Method method:userClass.getMethods()) {
//                System.out.println("method: "+method);
//            }

            System.out.println("*********reflect**********");
            Method addStr = userClass.getDeclaredMethod("addStr", String.class, String.class);
            addStr.setAccessible(true);
            Object invoke = addStr.invoke(userClass.newInstance(), "yymm", "haha");
            System.out.println("addStr: "+invoke.toString());

            System.out.println("*********stream**********");
            Arrays.stream(userTemp.getDeclaredFields()).forEach(System.out::println);

        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        }
    }
}

测试结果:

/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/bin/java -Dvisualvm.id=119516826323250 -javaagent:/Applications/IntelliJ IDEA CE.app/Contents/lib/idea_rt.jar=56814:/Applications/IntelliJ IDEA CE.app/Contents/bin -Dfile.encoding=UTF-8 -classpath /Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/charsets.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/ext/cldrdata.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/ext/dnsns.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/ext/jaccess.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/ext/jfxrt.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/ext/localedata.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/ext/nashorn.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/ext/sunec.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/ext/sunjce_provider.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/ext/sunpkcs11.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/ext/zipfs.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/jce.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/jfr.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/jfxswt.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/jsse.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/management-agent.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/resources.jar:/Users/yangmiao/Library/Java/JavaVirtualMachines/liberica-1.8.0_322/jre/lib/rt.jar:/Users/yangmiao/Documents/javaSource/codeme/target/classes dynamic.annotation.TestAnnotation
value: print me clz: class dynamic.annotation.User
constructor: [Ljava.lang.reflect.Constructor;@6e0be858
field: private java.lang.String dynamic.annotation.User.userName
field: private java.lang.String dynamic.annotation.User.password
*********reflect**********
addStr: yymm_haha
*********stream**********
private java.lang.String dynamic.annotation.User.userName
private java.lang.String dynamic.annotation.User.password

Process finished with exit code 0


欢迎大家关注个人微信公众号:一杯Java不加糖呢,不定期更新文章,谢谢🙏~
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫哥说

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值