网站首页 > java教程 正文
Java注解(Annotation)是JDK1.5引入的一种新特性,可以标注在类、方法、变量、参数上,官方定义如下:
Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的
一般官方定义都给的晦涩难懂,其实我们简单理解一下,注解就是标注在类、方法、变量、参数上的一种标签,你可以使用JDK内置的注解,也可以自定义注解,通常情况下我们都是使用自定义注解来完成自己的注解功能
注解分为:JDK内置的注解和元注解
JDK内置的注解
1、@Override
只要学过Java面向对象特性的人对于这个注解应该都很熟悉,@Override用来标注子类覆盖父类的方法,当标注了这个注解后父类中的方法有变更,编译器会给出错误提示
2、 @Deprecated
此注解主要是用来标识一些方法已经过时了,不推荐使用了
3、@SuppressWarnings
这个注解用于告诉编译器忽略特定的警告信息,当你不希望编译器在你的方法上有警告信息时,可以通过@SuppressWarnings注解来消除警告信息
4、@SafeVarargs
Java 7 开始支持,忽略任何使用参数为泛型变量的方法或构造函数调用产生的警告
5、@FunctionalInterface
Java 8 开始支持,标识一个匿名函数或函数式接口
使用示例
public class AnnotationTest extends HashMap {
@Override
public Object put(Object key, Object value) {
return super.put(key, value);
}
@Deprecated
public String testDeprecated(){
return "Deprecated";
}
@SuppressWarnings("uncheck")
public String testSuppressWarnings(){
return "SuppressWarnings";
}
}
123456789101112131415161718
public class SafeVarargsTest<T> {
private T[] params;
//构造函数可以使用@SafeVarargs
@SafeVarargs
public SafeVarargsTest(T... params){
this.params = params;
}
//普通方法不能使用@SafeVarargs,如果要忽略警告信息可以使用@SuppressWarnings("uncheck")
//@SafeVarargs
@SuppressWarnings("uncheck")
public void normalMethod(T... params){
for(T t : params){
System.out.println(t);
}
}
//static方法可以使用@SafeVarargs
@SafeVarargs
public static<T> void staticMethod(T... params){
for(T t : params){
System.out.println(t);
}
}
//final方法可以使用@SafeVarargs
@SafeVarargs
public final void finalMethod(T... params){
for(T t : params){
System.out.println(t);
}
}
}
12345678910111213141516171819202122232425262728293031323334353637
/**
* 函数式接口:有且仅有一个抽象方法
* @FunctionalInterface 是用来标注函数式接口的,其实不用@FunctionalInterface标注也可以表示函数式接口
* 只是加了注解就可以从编译器的层面来限制只能包含一个抽象方法,超过一个抽象方法会报编译错误
*/
@FunctionalInterface
public interface TestFunctionInterface {
public void test();
//public void test1(); //会报编译错误
//Object中的方法不是抽象方法
@Override
public boolean equals(Object var1);
//default 不是抽象方法
public default void defaultMethod(){
}
//static方法不是抽象方法
public static void staticMethod(){
}
}
12345678910111213141516171819202122232425
元注解
元注解就是用来标记注解的注解,也就是用来自定义注解的
1、@Retention
@Retention注解用来表示注解保留的阶段(源码、字节码、运行时)
- @Retention(RetentionPolicy.SOURCE) 注解仅存在于源码中,在class字节码文件中不包含
- @Retention(RetentionPolicy.CLASS),默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得
- @Retention(RetentionPolicy.RUNTIME),注解会在class字节码文件中存在,在运行时可以通过反射获取到
自定义注解只能使用RetentionPolicy.RUNTIME
@Retention(RetentionPolicy.RUNTIME)
public @interface FirstAnnotation {
}
1234
2、@Target
@Target用来限定注解可以使用的范围,可以是类、方法、参数等
- @Target(ElementType.TYPE) 作用接口、类、枚举、注解
- @Target(ElementType.FIELD) 作用属性字段、枚举的常量
- @Target(ElementType.METHOD) 作用方法
- @Target(ElementType.PARAMETER) 作用方法参数
- @Target(ElementType.CONSTRUCTOR) 作用构造函数
- @Target(ElementType.LOCAL_VARIABLE)作用局部变量
- @Target(ElementType.ANNOTATION_TYPE)作用于注解
- @Target(ElementType.PACKAGE) 作用于包
- @Target(ElementType.TYPE_PARAMETER) 作用于类型泛型
- @Target(ElementType.TYPE_USE) 类型使用.可以用于标注任意类型除了 class
一般比较常用的是ElementType.TYPE
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FirstAnnotation {
}
12345
3、@Documented
@Documented的作用是能够将注解中的元素包含到 Javadoc 中去
4、@Inherited
当一个类被@Inherited标记时,如果子类没有被其他注解标记,那么子类会继承父类的注解
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FirstAnnotation {
}
1234567
5、@Repeatable
@Repeatable标记的注解表示可以同时标记一个对象多次
@Inherited
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface FirstAnnotation {
RepeatAnnotionTest[] value();
}
12345678
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(FirstAnnotation.class)
public @interface RepeatAnnotionTest {
String value() default "";
}
123456
@RepeatAnnotionTest(value = "Java")
@RepeatAnnotionTest(value = "C++")
@RepeatAnnotionTest(value = "Python")
public class TestRepeat {
}
123456
注解解析
上面我们介绍了元注解,也自己完成了注解的定义,但是注解只是定义出来并没有什么意义,最终我们要使用注解来帮我们完成一定的功能
这就要使用到注解解析,在Java反射中有专门用来解析注解的方法,我们可以直接使用,下面我们通过一个例子来看一下如何完成注解的解析
假如我们现在要写一个校验的注解,用来校验年龄不能低于多少岁
1、首先我们定义一个注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ValidateAge {
int minAge() default 1;
}
12345
2、解析注解
public class TestValidateAge {
public static void main(String[] args){
TestValidateAge testValidateAge = new TestValidateAge();
testValidateAge.validateAge(15);
}
@ValidateAge(minAge = 20)
public void validateAge(int age){
System.out.println(processAnnotion(age));
}
//解析注解
private String processAnnotion(int age){
try {
//通过反射拿到对应的方法
Method validateAge = TestValidateAge.class.getDeclaredMethod("validateAge",int.class);
//判断方法上是否存在指定的注解
boolean isPresent = validateAge.isAnnotationPresent(ValidateAge.class);
if(isPresent){
//获取方法上的注解
ValidateAge annotation = validateAge.getAnnotation(ValidateAge.class);
//获取注解中属性的值
int minAge = annotation.minAge();
if(age < minAge ){
return "年龄不能低于" + minAge + "岁,校验失败";
} else {
return "你的年龄是" + age + "岁,校验通过";
}
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return "校验失败";
}
}
1234567891011121314151617181920212223242526272829303132333435
输出结果:
年龄不能低于20岁,校验失败
1
通过上面的例子,我们完成了一个简单的校验注解,其实注解本身并不难,注解更像是我们对类、方法、参数等打一个标签,然后我通过反射来对我指定的标签进行相应的业务逻辑处理
我们常用的框架,如Spring、MyBatis都定义了自己的注解,原理都一样,都是定义一个注解,然后复用注解解析器来对指定的注解进行不同的业务处理
明白了这其中的原理,我们就可以自定义一些注解来完成我们的业务处理
猜你喜欢
- 2024-09-27 在Spring Boot项目中创建和使用自定义注解
- 2024-09-27 这一篇 Java 注解,写得太好了(java注解使用)
- 2024-09-27 学习廖雪峰的JAVA教程---注解(定义注解@interface)
- 2024-09-27 自定义注解妙用,一行代码搞定用户操作日志记录,你学会了吗?
- 2024-09-27 Spring Boot 整合mybatis,使用注解的方式(自动生成注解)
- 2024-09-27 面试官:实际工作中哪里用到了自定义注解?
- 2024-09-27 使用自定义注解和切面AOP实现Java程序增强
- 2024-09-27 Java-注解有什么用?该怎么用?(java 注解的作用)
- 2024-09-27 Java 17中的元注解:自定义注解的行为
- 2024-09-27 自定义注解你真会用吗?(说说自定义注解的场景及实现)
你 发表评论:
欢迎- 05-16SpringBoot整合Redis实现常用功能
- 05-16基于Redis实现简单的延时消息队列
- 05-16安装Redis
- 05-16Spring系列之Redis的两种集成方式
- 05-16Django连接Redis集群问题排查思路和总结
- 05-16只需5分钟,完成Redis所有命令操作~
- 05-16熟练使用 Redis 的 5 大数据结构:Java 实战教程
- 05-16Redis 常见业务场景及实例(Java)
- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)