qq群推广用什么网站好,沧州网站推广,如何网站全部结构,北京朝阳区网站建设注解 注解是用来干什么的它有什么作用注解的常见分类内置注解Override注解定义 Deprecated注解定义 SuppressWarnings注解定义 元注解Target注解定义ElementType RetentionRetentionTarget注解定义RetentionPolicy Documented注解定义 Inherited注解定义用法 Repeata… 注解 注解是用来干什么的它有什么作用注解的常见分类内置注解Override注解定义 Deprecated注解定义 SuppressWarnings注解定义 元注解Target注解定义ElementType RetentionRetentionTarget注解定义RetentionPolicy Documented注解定义 Inherited注解定义用法 Repeatable(重复注解)注解定义JDK8之前JDK8之后 Native 注解与反射接口相关接口 自定义注解注解的本质(未完结) 注解是用来干什么的
注解的汉语意思: 用浅近的文字解释艰深的词句
注解是JDK1.5版本开始引入的一个特性,用于对代码进行说明,可以对包,类,接口,字段,方法参数,局部变量进行注解.
它有什么作用
主要作用是下面四个方面
生成文档 通过代码里标识的元数据生成javaDoc文档编译检查 通过代码里标识的元数据让编译器在编译期间进行检查验证编译时动态处理 编译时通过代码里标识的元数据动态处理,例如动态生成代码运行时动态处理 运行时通过底阿妈里标识的元数据动态处理,例如使用反射注入实例
注解的常见分类
Java自带的标准注解 用于标明重写某个方法,某个类或方法过时,表明要忽略的警告,用这些注解表明后编译器就会 进行检查元注解 用于定义注解的注解自定义注解 根据自己的需求定义注解,并可用元注解对自定义注解进行注解
内置注解 Override
表示当前的方法定义将覆盖父类中的方法
注解定义
Target(ElementType.METHOD)
Retention(RetentionPolicy.SOURCE)
public interface Override {
}这个注解可以用来修饰方法,并只在编译期有效,编译期后class文件就不存在了
Deprecated
表示代码被弃用,如果使用了被Deprecated注解的代码编译器会发出警告
注解定义
Documented
Retention(RetentionPolicy.RUNTIME)
Target(value{CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE})
public interface Deprecated {
}
它会被文档化可以保留到运行时可以修饰构造方法,属性,局部变量,方法,包,参数,类型
SuppressWarnings
关闭编译器警告信息
注解定义
Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
Retention(RetentionPolicy.SOURCE)
public interface SuppressWarnings {String[] value();
}可以修饰类型,属性,方法,参数,构造器,局部变量只能存活在源码取值为String[] 它可以取的值如下所示:
参数作用all抑制所有警告deprecation抑制启用注释的警告finally抑制finally模块没有返回的警告null忽略对null的操作unused抑制没被使用过的代码的警告等等
元注解
Target
描述注解的使用范围(即被修饰的注解可以在什么地方使用)
注解定义
Documented
Retention(RetentionPolicy.RUNTIME)
Target(ElementType.ANNOTATION_TYPE)
public interface Target {/*** Returns an array of the kinds of elements an annotation interface* can be applied to.* return an array of the kinds of elements an annotation interface* can be applied to*/ElementType[] value();
}可被文档化可以保留到运行时只能在注解类上使用value值在ElementType中
ElementType
public enum ElementType {TYPE, // 类、接口、枚举类FIELD, // 成员变量包括枚举常量METHOD, // 成员方法PARAMETER, // 方法参数CONSTRUCTOR, // 构造方法LOCAL_VARIABLE, // 局部变量ANNOTATION_TYPE, // 注解类PACKAGE, // 可用于修饰包TYPE_PARAMETER, // 类型参数JDK 1.8 新增TYPE_USE // 使用类型的任何地方JDK 1.8 新增}RetentionRetentionTarget
描述注解保留的时间范围(即被描述的注解在它所修饰的类中可以被保留到何时)
注解定义
Documented
Retention(RetentionPolicy.RUNTIME)
Target(ElementType.ANNOTATION_TYPE)
public interface Retention {RetentionPolicy value();
}可被文档化可以保留到运行时只能在注解类上使用value值在RetentionPolicy 中
RetentionPolicy
public enum RetentionPolicy {SOURCE, // 源文件保留CLASS, // 编译期保留默认值RUNTIME // 运行期保留可通过反射去获取注解信息
}我们可以通过执行javap -verbose RetentionTest获取到RetentionTest的class字节码内容如下.
{public retention.RetentionTest();flags: ACC_PUBLICCode:stack1, locals1, args_size10: aload_01: invokespecial #1 // Method java/lang/Object.init:()V4: returnLineNumberTable:line 3: 0public void sourcePolicy();flags: ACC_PUBLICCode:stack0, locals1, args_size10: returnLineNumberTable:line 7: 0public void classPolicy();flags: ACC_PUBLICCode:stack0, locals1, args_size10: returnLineNumberTable:line 11: 0RuntimeInvisibleAnnotations:0: #11()public void runtimePolicy();flags: ACC_PUBLICCode:stack0, locals1, args_size10: returnLineNumberTable:line 15: 0RuntimeVisibleAnnotations:0: #14()
}我们可以得到下面的两个结论:
编译期没有记录下sourcePolicy()方法的注解信息编译期分别使用了RuntimeInvisibleAnnotations, RuntimeVisibleAnnotations 属性去记录了classPolicy()方法和runtimePolicy()方法的注解信息
Documented
描述使用javaDoc工具为类生成帮助文档时是否要保留其注解信息
注解定义
Documented
Target({ElementType.TYPE,ElementType.METHOD})
public interface TestDocAnnotation {public String value() default default;
}可被生成文档使用范围是类,接口,枚举类,成员方法
Inherited
被他修饰的注解具有继承性. 如果某个类使用了被Inherited修饰的注解,则其子类将自动具有该注释
注解定义
Documented
Retention(RetentionPolicy.RUNTIME)
Target(ElementType.ANNOTATION_TYPE)
public interface Inherited {
}
可被生成文档可被保留到运行时只能用于注解类
用法
定义Inherited注解
Inherited
Retention(RetentionPolicy.RUNTIME)
Target({ElementType.TYPE,ElementType.METHOD})
public interface TestInheritedAnnotation {String [] values();int number();
}使用这个注解
TestInheritedAnnotation(values {value}, number 10)
public class Person {
}class Student extends Person{Testpublic void test(){Class clazz Student.class;Annotation[] annotations clazz.getAnnotations();for (Annotation annotation : annotations) {System.out.println(annotation.toString());}}
}输出内容
xxxxxxx.TestInheritedAnnotation(values[value], number10)即使Student类没有显示地被注解TestInheritedAnnotation但是它的父类Person被注解而且TestInheritedAnnotation被Inherited注解因此Student类自动有了该注解.
Repeatable(重复注解)
允许在同一申明类型(类,属性,方法)多次使用同一注解
注解定义
Documented
Retention(RetentionPolicy.RUNTIME)
Target(ElementType.ANNOTATION_TYPE)
public interface Repeatable {Class? extends Annotation value();
}可被生成文档可以保留至运行时只能作用域注解类
JDK8之前
JDK8之前有重复使用注解的解决方案,但是可读性不好 方案: 由另一个注解来存储重复注解,在使用的时候,用存储注解Authorities来扩展重复注解
public interface Authority {String role();
}public interface Authorities {Authority[] value();
}public class RepeatAnnotationUseOldVersion {Authorities({Authority(roleAdmin),Authority(roleManager)})public void doSomeThing(){}
}JDK8之后
方案: 创建重复注解时,加上Repeatable,指向存储注解Authorities,在使用的时候,可以直接重复使用Authority注解.
Repeatable(Authorities.class)
public interface Authority {String role();
}public interface Authorities {Authority[] value();
}public class RepeatAnnotationUseNewVersion {Authority(roleAdmin)Authority(roleManager)public void doSomeThing(){ }
}Native
使用Native注解修饰成员变量,表示这个变量可以被本地代码引用,常常被代码生成工具使用,了解即可.
注解与反射接口
我们如果想自定义注解,那么就必须先了解注解与反射接口的这部分内容. 反射包java.lang.reflect下的AnnotatedElement接口提供这些方法. 注意:只有注解被定义为RUNTIME后,该注解才能是运行时可见,当class文件被装载时,被保存在class文件中的Annotation才会被虚拟机读取.
AnnotatedElement接口是所有程序元素(Class,Method,Constructor)的父接口.
Class类
public final class ClassT implements Serializable, GenericDeclaration, Type, AnnotatedElement, TypeDescriptor.OfFieldClass?, Constable {
xxxx
}
Method类
public final class Method extends Executable {
xxx
}
public abstract sealed class Executable extends AccessibleObject{
xxx
}
public class AccessibleObject implements AnnotatedElement {
xxx
}Constructor类
public final class ConstructorT extends Executable {
xxx
}
和上面Method的继承路径是是一样的,不赘述了.相关接口
boolean isAnnotationPresent(Class?extends Annotation annotationClass) 判断该元素上是否包含指定类型的注解,存在则返回true,否则返回false. (此方法会忽略注解对应的注解容器)T extends Annotation T getAnnotation(ClassT annotationClass) 返回该程序元素上存在的,制定类型的注解,如果该类型的注解不存在,则返回nullAnnotation[] getAnnotations() 返回该程序元素上存在的所有注解,若没有注解,返回长度为0的数组T extends Annotation T[] getAnnotationsByType(ClassT annotationClass) 返回该程序元素上存在的,指定类型的注解数据.若没有,返回长度为0的数组 该方法调用者可以随意修改返回数据,不会对其他调用者返回数组产生影响. (会检测注解对应的重复注解容器)T extends Annotation T getDeclaredAnnotation(ClassT annotationClass 返回直接存在此元素上的所有注解. 该方法忽略继承的注解,如果没有注解直接存在此元素上,返回null.T extends Annotation T[] getDeclaredAnotationsByType(ClassT annotationClass) 返回直接存在此元素上所有指定类型注解, 该方法忽略继承的注解Annotion[] getDeclaredAnnotations() 返回直接存在于此元素上的所有注解机器注解对应的重复注解容器. 该方法忽略继承注解,如果没有注释直接存在于此元素上则返回长度为零的一个数组。该方法的调用者可以随意修改返回的数组而不会对其他调用者返回的数组产生任何影响。
自定义注解
理解注解与反射接口后,我们通过自定义注解来把知识点融合应用一下
定义注解
Target(ElementType.METHOD)
Retention(RetentionPolicy.RUNTIME)
public interface MyMethodAnnotation {public String title() default ;public String description() default ;}使用注解
public class TestMethodAnnotation {OverrideMyMethodAnnotation(title toStringMethod, description override toString method)public String toString() {return Override toString method;}DeprecatedMyMethodAnnotation(title old static method, description deprecated old static method)public static void oldMethod() {System.out.println(old method, dont use it.);}SuppressWarnings({unchecked, deprecation})MyMethodAnnotation(title test method, description suppress warning static method)public static void genericsTest() throws FileNotFoundException {List l new ArrayList();l.add(abc);oldMethod();}
}用反射接口获取注解信息
public static void main(String[] args) {try {// 获取所有methodsMethod[] methods TestMethodAnnotation.class.getClassLoader().loadClass((com.pdai.java.annotation.TestMethodAnnotation)).getMethods();// 遍历for (Method method : methods) {// 方法上是否有MyMethodAnnotation注解if (method.isAnnotationPresent(MyMethodAnnotation.class)) {try {// 获取并遍历方法上的所有注解for (Annotation anno : method.getDeclaredAnnotations()) {System.out.println(Annotation in Method method : anno);}// 获取MyMethodAnnotation对象信息MyMethodAnnotation methodAnno method.getAnnotation(MyMethodAnnotation.class);System.out.println(methodAnno.title());} catch (Throwable ex) {ex.printStackTrace();}}}} catch (SecurityException | ClassNotFoundException e) {e.printStackTrace();}
}测试的输出
Annotation in Method public static void com.pdai.java.annotation.TestMethodAnnotation.oldMethod() : java.lang.Deprecated()
Annotation in Method public static void com.pdai.java.annotation.TestMethodAnnotation.oldMethod() : com.pdai.java.annotation.MyMethodAnnotation(titleold static method, descriptiondeprecated old static method)
old static method
Annotation in Method public static void com.pdai.java.annotation.TestMethodAnnotation.genericsTest() throws java.io.FileNotFoundException : com.pdai.java.annotation.MyMethodAnnotation(titletest method, descriptionsuppress warning static method)
test method
Annotation in Method public java.lang.String com.pdai.java.annotation.TestMethodAnnotation.toString() : com.pdai.java.annotation.MyMethodAnnotation(titletoStringMethod, descriptionoverride toString method)
toStringMethod注解的本质(未完结)
这部分要扯到动态代理和注解的处理器,emmm比较麻烦. 后面发完动态处理后返回来填坑