Annotation
注解(Annotation)是一种可以作用于类、属性或方法的,带有特定功能的,特殊的 "注释"。
且注解不影响程序的运行:不论是否使用注解,代码都可以正常执行。
Annotation接口定义如下
public interface Annotation {
boolean equals(Object obj);
int hashCode();
String toString();
Class<? extends Annotation> annotationType();
}
系统自带的注解 或者 用户自定义的注解都默认实现这个接口。
常用的注解如下:
@Override:确保重写的正确性。
@Deprecated:被荒废(荒废就是不建议使用)
@SuppressWarnings:忽略安全警告
常用的元注解如下: (声明在注解之上的注解,一般是约束自定义注解的功能)
@Target:声明注解可作用范围
@Retention:注解的生命周期
@Inherited:注解可否被子类继承
常用注解
@Override
父类方法被重写时可以使用该注解,主要作用是确保重写的正确性
栗子:
public class Test19 {
public static void main(String[] args) {
Son son = new Son();
son.tell("123");
}
}
class Father{
public void tell(String something){
System.out.println(something);
}
}
class Son extends Father{
@Override
public void tell(String something) {
super.tell(something);//子类调用父类的tell方法
}
}
程序运行结果:
123
下面的栗子是故意错误的重写方法:
public class Test19 {
public static void main(String[] args) {
Son son = new Son();
son.tell("123");
}
}
class Father{
public void tell(String something){
System.out.println(something);
}
}
class Son extends Father{
@Override
public void Tell(String something) {//重写错误,方法名不同
super.tell(something);
}
}
程序运行结果:
java: 方法不会覆盖或实现超类型的方法
@Deprecated
此注解声明的属性、方法或者类会被视为被荒废(荒废就是不建议使用),使用时会出现编译警告。
栗子:
public class Test19 {
public static void main(String[] args) {
Father.say();//方法名会被画横线
}
}
class Father{
@Deprecated
public static void say(){
System.out.println("该方法已荒废,但依旧可以正常执行");
}
}
Father.say();
程序运行结果:
该方法已荒废,但依旧可以正常执行
除了方法,@Deprecated还可以作用于类,属性:
@Deprecated
class Father{
@Deprecated
private int age;
@Deprecated
public static void say(){
System.out.println("该方法已荒废,但依旧可以正常执行");
}
}
Father.say();
@SuppressWarnings
忽略安全警告。之前泛型说过如果没有明确具体的泛型类型会出现安全警告。
不同于上面两个注解,@SuppressWarnings需要传入value具体到忽略哪种类型的安全警告
常用value如下:
deprecation——忽略使用被荒废的类或方法警告
unchecked——忽略泛型未指定警告
fallthrough——忽略switch的case后未加入break警告
all——忽略所有警告
查看@SuppressWarnings定义
public @interface SuppressWarnings {
String[] value(); //接收value数组,可多传入。
@interface就相当于实现了Annotation接口
自定义注解
格式如下:
修饰符 @interface 注解名{
数据类型 属性名() default 默认值;
}
如果注解中定义了属性,则属性名后必须加(),
如果属性没有默认值,实现该注解必须要传入属性值。
栗子:
public class Test19 {
@MyAnnotation2//有默认值不用传入
@MyAnnotation1("123")//属性没有默认值必须要传入
public static void main(String[] args) {
}
}
@interface MyAnnotation1{
String value();
}
@interface MyAnnotation2{
String value() default "默认值";
}
元注解
元注解是作用于注解之上的注解,一般是约束自定义注解的功能
@Target
如果一个注解没有显式使用@Target,则该注解可以作用在任何地方。
使用@Target限制注解作用于某处
查看Target元注解定义
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {
ElementType[] value();
//接收ElementType数组,没有默认值,使用Target元注解必须传入属性值
}
ElementType是枚举,其内部如下:
public enum ElementType {
//属性值 描述
TYPE, 类,接口,枚举
FIELD, 属性
METHOD, 方法
PARAMETER, 参数
CONSTRUCTOR, 构造方法
LOCAL_VARIABLE, 局部属性
ANNOTATION_TYPE, 注解
PACKAGE, 包
}
至此,栗子如下:
public class Test19 {
@MyAnnotation2()
public int x=1;
@MyAnnotation1("123")
public static void main(String[] args) {
}
}
@Target(ElementType.METHOD)//限制只能作用于方法上
@interface MyAnnotation1{
String value() default "默认值";
}
@Target(ElementType.FIELD)//限制只能作用于属性上
@interface MyAnnotation2{
String value() default "默认值";
}
@Retention
该元注解声明某个注解的声明周期
查看元注解Retention定义
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
RetentionPolicy value();
}
RetentionPolicy是枚举,其内部如下:
public enum ElementType {
//属性值 描述
SOURCE, 此注解只保留在源文件中,编译后类文件(class文件)不存在
CLASS, 此注解保留在源文件和类文件中,注解信息不会被加载到JVM中(默认是此属性)
RUNTIME 此注解保留在源文件、类文件中,注解信息会被加载到JVM中。
}
@Override——@Retention(RetentionPolicy.SOURCE)
@Deprecated——@Retention(RetentionPolicy.RUNTIME)
@SuppressWarnings——@Retention(RetentionPolicy.SOURCE)
@Inherited
注解可以被继承
如果一个注解使用@Inherited,实现该注解的类,其子类也会拥有该注解
栗子:
@Inherited
@interface MyAnnotation1{
String value() default "默认值";
}
@MyAnnotation1
class Father{
public void say(){}
}
//子类也拥有MyAnnotation1注解
class Son extends Father{}
使用反射获取注解
栗子:
package moudle2;
import java.lang.annotation.*;
public class Test19 {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("moudle2.Son");
Annotation[] annotations = clazz.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Inherited
@interface MyAnnotation1{
String value() default "默认值";
}
@MyAnnotation1
class Father{
public void say(){}
}
class Son extends Father{}
程序运行结果:
//空 因为MyAnnotation1注解的信息没有被加载到JVM中。
至此,修改栗子如下:
package moudle2;
import java.lang.annotation.*;
public class Test19 {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("moudle2.Son");
Annotation[] annotations = clazz.getAnnotations();
for (Annotation annotation : annotations) {
System.out.println(annotation);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Retention(RetentionPolicy.RUNTIME)//加载到JVM中
@Inherited
@interface MyAnnotation1{
String value() default "默认值";
}
@MyAnnotation1
class Father{
public void say(){}
}
class Son extends Father{}
程序运行结果:
@moudle2.MyAnnotation1(value=默认值)
一般注解都是使用系统注解,使用框架时也是,直接使用框架提供的注解即可。
标签:Java,String,void,Father,class,第十九,注解,public,拾贝 From: https://www.cnblogs.com/Ocraft/p/17815345.html