Java注解介绍
JAVA注解
一、注解和注释区别:
1.1 注释:comment
给程序员看的
,对程序做出解释。用于描述代码的作用和一些关键性的知识点,使用文字描述程序。
1.2 注解:annotation
-
JDK5.0后引入的新技术,他不是程序本身,但可以对程序做出解释。(这一点和注释没有区别)
-
给程序员看,但主要目的是给程序看
(多的这个“解”字)
二、注解详细定义
叫元数据,一种代码级别的说明,它是JDK1.5及以后版本引入的一个特性,与类、接口(注解本质上是一种特殊的接口)、枚举在同一个层次,它可以声明在
包、类、字段、局部变量、方法参数
等的前面,用来对这些元素进行说明、注释。很多框架的底层都是通过注解实现,比如spring boot,spring cloud。(框架的底层就是注解和反射)
2.1 注解的作用分类
编写文档:
通过代码里表示的元数据生成文档【生成doc文档】
代码分析:
通过代码里表示的元数据进行分析【使用反射】
编译检查:
通过代码里表示的元数据让编译器能够实现基本的编译检查【Override】
2.2 注解按照运行机制分类
源码注解:
注解只在源码中存在,编译成.class文件之后就不存在了。常见的注解为@Override,@SuppressWarnings
编译时注解:
注解在源码存在的基础上,
也会在.class文件中存在
,但是在运行阶段中就不存在了
这是默认的注解保留策略。这种策略下,注解将存在与.class文件,但是不能被运行时访问。通常这种注解策略用来处于一些字节码级别的操作。
运行时注解:
注解在运行阶段依然存在,且能够影响程序的运行过程,例如:@Autowired
通常情况下,我们都会结合反射来做一些事情。
2.3 注解的作用
-
不是程序本身,可以对程序做出解释(这一点和注释一样)
-
可以被其他程序(比如:编译器)读取
,注解+反射。 -
可以附加在package,class,method,field等上面,相当于给他们
额外的辅助信息
,我们可以通过反射机制编程
实现对这些元数据的访问。
2.4 注解的格式
注解是以“@注解名”在代码中存在的;还可以添加一些参数值
,例如:@suppressWarning(value=“unchecked”)
三、注解入门
分为内置注解和自定义注解
3.1 内置注解示例:
@Override:重写Object的toString()
@Override表示重写父类方法,在编译时存在
。
package com.happy; //什么是注解 public class AnnotationStudy extends Object { //@Override 重写的注解 @Override public String toString() { return super.toString(); } public void testTread(){ Thread thread=new Thread(); } }
@FunctionalInterface:Runnable接口用
线程接口Runnable的@FunctionalInterface
,表示该接口是一个函数式编程接口
(即只有一个待实现方法),不定义也没有影响程序执行。
package java.lang; /** * The <code>Runnable</code> interface should be implemented by any * class whose instances are intended to be executed by a thread. The * class must define a method of no arguments called <code>run</code>. * <p> * This interface is designed to provide a common protocol for objects that * wish to execute code while they are active. For example, * <code>Runnable</code> is implemented by class <code>Thread</code>. * Being active simply means that a thread has been started and has not * yet been stopped. * <p> * In addition, <code>Runnable</code> provides the means for a class to be * active while not subclassing <code>Thread</code>. A class that implements * <code>Runnable</code> can run without subclassing <code>Thread</code> * by instantiating a <code>Thread</code> instance and passing itself in * as the target. In most cases, the <code>Runnable</code> interface should * be used if you are only planning to override the <code>run()</code> * method and no other <code>Thread</code> methods. * This is important because classes should not be subclassed * unless the programmer intends on modifying or enhancing the fundamental * behavior of the class. * * @author Arthur van Hoff * @see java.lang.Thread * @see java.util.concurrent.Callable * @since JDK1.0 */ @FunctionalInterface public interface Runnable { /** * When an object implementing interface <code>Runnable</code> is used * to create a thread, starting the thread causes the object's * <code>run</code> method to be called in that separately executing * thread. * <p> * The general contract of the method <code>run</code> is that it may * take any action whatsoever. * * @see java.lang.Thread#run() */ public abstract void run(); }
destroy():Thread类的方法用@Deprecated
表示该方法废弃
,在调用该方法时,IDE会以删除线标志该方法,不推荐程序员使用,但可以使用。
如下
@Deprecated public void destroy() { throw new NoSuchMethodError(); }
package com.happy; //什么是注解 public class AnnotationStudy extends Object { //@Override 重写的注解 @Override public String toString() { return super.toString(); } public void testTread(){ Thread thread=new Thread(); thread.destroy(); } }
@suppressWarnings
镇压警告,用来抑制编译时的警告信息,与前面的注释不同,你需要添加一个参数才能正确使用,这些参数都是已经定义好的,我们选择性使用就好了。平时不建议镇压,
@SuppressWarnings("all") @SuppressWarnings("unchecked") @SuppressWarnings(value={"unchecked","deprecation"})
package java.lang; import java.lang.annotation.*; import static java.lang.annotation.ElementType.*; /** * Indicates that the named compiler warnings should be suppressed in the * annotated element (and in all program elements contained in the annotated * element). Note that the set of warnings suppressed in a given element is * a superset of the warnings suppressed in all containing elements. For * example, if you annotate a class to suppress one warning and annotate a * method to suppress another, both warnings will be suppressed in the method. * * <p>As a matter of style, programmers should always use this annotation * on the most deeply nested element where it is effective. If you want to * suppress a warning in a particular method, you should annotate that * method rather than its class. */ @Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE}) @Retention(RetentionPolicy.SOURCE) public @interface SuppressWarnings { /** * The set of warnings that are to be suppressed by the compiler in the * annotated element. Duplicate names are permitted. The second and * successive occurrences of a name are ignored. The presence of * unrecognized warning names is <i>not</i> an error: Compilers must * ignore any warning names they do not recognize. They are, however, * free to emit a warning if an annotation contains an unrecognized * warning name. * * <p> The string {@code "unchecked"} is used to suppress * unchecked warnings. Compiler vendors should document the * additional warning names they support in conjunction with this * annotation type. They are encouraged to cooperate to ensure * that the same names work across multiple compilers. * @return the set of warnings to be suppressed */ String[] value(); }
注意:上面value()看似方法,实际为属性,而Sring为属性的类型,这是注解特殊的地方。
另外注意@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Retention(RetentionPolicy.SOURCE) 这两个注解,为元注解,将在下面讲解。
加入镇压告警前:
加入压制后,idea不再暗黑提示
3.2 元注解
元注解的作用就是负责注解其他注解,就是
解释其他注解的注解
,Java定义了4个标准的meta-annotation类型,他们被用来提供对其他annotation类型做说明。也是内置注解。
这些类型和他们所支持的类在java.lang.annotation
包中可以找到,分别是:
@Target:(重点)
用于描述注解的使用范围
(即:被描述的注解可以用在什么地方)
@Retention:(重点)
表示需要在什么级别保存该注释信息,用于描述注解的生命周期:SOURCE<CLASS<
RUNTIME
一般我们使用定义为RUNTIME,即运行的时候依然存在有用,重点记忆。
例如:
Runtime定义的,将会在Runtime,Class和Source都存在和生效
而Class定义的,会在Class和Source生效
@Document:
说明该注解将包含在javadoc中
@Inherited:
说明子类可以继承父类中的该注解
测试元注解:
自定义注解,使用元注解,示例如下:
下图Target方法指定用在Method,固注解在类上时报错。
用数组引入多个Target范围后,不再报错
四、自定义注解
使用@ interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,注意前面有@,如果没有@就是普通接口
要点如下:
@interface用来声明一个注解,格式public @interface 注解名{定义内容}。
如果是内部类方式申明注解,就省去public
其中每一个方法实际上是声明了一个配置参数(或者理解为属性),
方法的名称就是参数的名称。返回值的类型就是参数的类型
。返回值类型只能是
基本类型、class、String、enum
可以通过default类声明参数的默认值
如果只有一个参数成员,
一般为参数取名为value,使用时还可以起取消掉
。注解元素必须要有值,我们定义注解元素时,通常使用空字符串、0作为默认值
package com.happy; import java.lang.annotation.*; @MyAnnotation public class MetaAnnotationUseStudy { @MyAnnotation public void test() { } // 注解可以显示赋值,如果没有默认值,我们必须显示赋值 @MyAnnotation2(name = "happytest",schools = {"哈佛"}) public void test2() { } } @Target(value = {ElementType.METHOD, ElementType.TYPE}) @Retention(RetentionPolicy.SOURCE) @interface MyAnnotation { } @Target({ElementType.METHOD, ElementType.TYPE}) @Documented @Inherited //作用范围为到运行时 @Retention(value = RetentionPolicy.RUNTIME) @interface MyAnnotation2 { // 注解的参数,注意这里不是方法 String name() default ""; int age() default 0; int id() default -1;//如果默认值为-1,代表不存在 String[] schools() default {"北郵","清華"}; }
后面会介绍反射,注解必须+反射,才能读取注解里的东西,才能发挥最大功效,是框架的基础。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)