Java注解 1.1 注解介绍 从Java 5 版本之后可以在源代码中嵌入一些补充信息,这种补充信息称为注解(Annotation),注解是 Java 平台中非常重要的一部分。注解都是 @ 符号开头, 例如我们在学习方法重写时使用过的 @Override 注解。同 Class 和 Interface 一样,注解也属于一种类型。 Annotation 可以翻译为“注解”或“注释”,一般翻译为“注解”,因为“注释”一词已经用于说明“//”、“/**...*/”和“/*...*/”等符号了,这里的“注释”是英文Comment 翻译。 说明:注解并不能改变程序的运行结果,也不会影响程序运行的性能。有些注解可以在编译时给用户提示或警告,有的注解可以在运行时读写字节码文件信息。 1.2 注解介绍 注解的作用: 1,生成帮助文档。这是最常见的,也是 Java 最早提供的注解。常用的有 @see、@param 和 @return 等; 2,跟踪代码依赖性,实现替代配置文件功能。作用就是减少配置。现在的框架基本都使用了这种配置来减少配置文件的数量; 3,在编译时进行格式检查。如把 @Override 注解放在方法前,如果这个方法并不是重写了父类方法,则编译时就能检查出。 说明:无论是哪一种注解,本质上都一种数据类型,是一种接口类型。到 Java 8 为止 Java SE 提供了 11 个内置注解。其中有 5 个是基本注解,它们来自于 java.lang包。有 6 个是元注解,它们来自于 java.lang.annotation 包,自定义注解会用到元注解 1.3 注解介绍 5个基本注解: @Override、@Deprecated、@SuppressWarnings、 @SafeVarargs 和 @FunctionalInterface 6个元注解: @Documented、@Target、@Retention 和 @Inherited @Repeatable 和 @Native 1.4 注解介绍 @Override 注解: 该注解是用来指定方法重写的,只能修饰方法并且只能用于方法重写,不能修饰其它的元素。它可以强制一个子类必须重写父类方法或者实现接口的方法。 @Override 的作用是告诉编译器检查这个方法,保证父类要包含一个被该方法重写的方法,否则就会编译出错。这样可以帮助程序员避免一些低级错误。 比如: public class Person { @Override public String toString() { return “Person [====重写Object类的toString方法====]"; } } 1.5 注解介绍 @Deprecated 可以用来注解类、接口、成员方法和成员变量等,用于表示某个元素 (类、方法等)已过时。当其他程序使用已过时的元素时,编译器将会给出警告。 比如: @Deprecated public class Person { @Deprecated protected String name; @Deprecated public void setNameAndAge(String name, int age) { this.name = name; this.age = age; } } 1.6 注解介绍 @SuppressWarnings 注解指示被该注解修饰的程序元素(以及该程序元素中的所有 子元素)取消显示指定的编译器警告,且会一直作用于该程序元素的所有子元素。 @SuppressWarnings注解的使用有以下三种: 抑制单类型的警告:@SuppressWarnings("unchecked") 抑制多类型的警告:@SuppressWarnings("unchecked","rawtypes") 抑制所有类型的警告:@SuppressWarnings("all") 比如: @SuppressWarnings({ "deprecation" }) public static void main(String[] args) { Person p = new Person(); p.setNameAndAge("多测师", 20); p.name = "duoceshi"; } 1.7 注解介绍 @SuppressWarnings中的关键字:
1.8 注解介绍 @SafeVarargs 注解抑制编译器警告,但不适用于非 static 或非 final 声明的方法 比如: public class HelloWorld { public static void main(String[] args) { // 传递可变参数,参数是泛型集合 display(10, 20, 30); // 传递可变参数,参数是非泛型集合 display("10", 20, 30); // 没有@SafeVarargs会有编译警告 } @SafeVarargs public static <T> void display(T... array) { for (T arg : array) { System.out.println(arg.getClass().getName() + ":" + arg); } } } 1.9 注解介绍 @FunctionalInterface 就是用来指定某个接口必须是函数式接口, 所以 @FunInterface 只能修饰接口,不能修饰其它程序元素。 函数式接口就是为 Java 8 的 Lambda 表达式准备的,Java 8 允许使用 Lambda 表 达式创建函数式接口的实例,因此 Java 8 专门增加了 @FunctionalInterface。 比如: @FunctionalInterface public interface FunInterface { void test(); // 只定义一个抽象方法 } 说明:使用了@FunctionalInterface注解修饰的接口只能包含一个抽象方法。包含多 个则会报错。 2.1 自定义注解 声明自定义注解使用@interface 关键字(interface 关键字前加 @ 符号)实现。 定义注解和定义类相似,注解前面的访问修饰符和类一样有两种,分别是公有访问权限(public)和默认访问权限。一个源程序文件中可以声明多个注解,但只能有一个是公有访问权限的注解。且源程序文件命名和公有访问权限的注解名一致。 自定义注解分类: 1,标记注解:没有定义成员变量的注解类型被称为标记注解。这种注解仅利用自身的存在与否来提供信息,如前面介绍的 @Override、@Test 等都是标记注解。 2,元数据注解:包含成员变量的注解,因为它们可以接受更多的元数据,所以也被称为元数据注解。 2.2 自定义注解 自定义标记注解 例如: // 定义一个简单的标记注解 public @interface Lesson22_2 { } @Lesson22_2 // 使用自定义注解 class LessonDemo{ } 2.3 自定义注解 自定义元数据注解 例如: public @interface MyTag { // 定义带两个成员变量的注解,注解中的成员变量以方法的形式来定义 String name(); int age(); } 注解中的成员变量也可以有默认值,可使用 default 关键字,例如: public @interface MyTag { // 定义了两个成员变量的注解 使用default为两个成员变量指定初始值 String name() default "多测师"; int age() default 5; } 2.4 自定义注解 使用自定义元数据注解,例如: public class Test { // 使用带成员变量的注解时,需要为成员变量赋值 @MyTag(name="dcs", age=6) public void info() { } } 如果为注解的成员变量指定了默认值,那么使用该注解时就可以不为这些成员变量赋 值,而是直接使用默认值。 public class Test { @MyTag public void info() { } } //如果为 MyTag 的成员变量指定了值,则默认值不会起作用。 3.1 元注解作用及使用 元注解是负责对其它注解进行说明的注解,自定义注解时可以使用元注解。Java 5 定义了 4 个注解,分别是 @Documented、@Target、@Retention 和 @Inherited。 Java 8 又增加了 @Repeatable 和 @Native 两个注解。 @Documented 是一个标记注解,没有成员变量。用 @Documented 注解修饰的注 解类会被 JavaDoc 工具提取成文档。 @Retention 用于描述注解的生命周期,也就是该注解被保留的时间长短。 @Inherited 是一个标记注解,用来指定该注解可以被继承。 @Repeatable 注解是 Java 8 新增加的,它允许在相同的程序元素中重复注解。 @Native 注解修饰成员变量,则表示这个变量可以被本地代码引用,常常被代码生 成工具使用 3.2 元注解作用及使用 @Target 注解用来指定一个注解的使用范围,即被 @Target 修饰的注解可以用在什 么地方。@Target 注解有一个成员变量(value)用来设置适用目标, value 是 java.lang.annotation.ElementType 枚举类型的数组。 ElementType常用的枚举常量:
3.3 元注解作用及使用 自定义一个 MyTarget 注解,使用范围为方法,代码如下所示。 @Target({ ElementType.METHOD }) public @interface MyTarget { } class Test { @MyTarget public void demo(){ // @MyTarget 只能修饰方法,修饰类或成员变量则会报错 } } 3.4 元注解作用及使用 @Retention 用于描述注解的生命周期,也就是该注解被保留的时间长短。 @Retention 注解中的成员变量(value)用来设置保留策略,value 是 java.lang.an notation.RetentionPolicy 枚举类型,RetentionPolicy 有 3 个枚举常量,如下所示。 SOURCE:在源文件中有效(即源文件保留) CLASS:在 class 文件中有效(即 class 保留) RUNTIME:在运行时有效(即运行时保留) 生命周期大小排序为 SOURCE < CLASS < RUNTIME,前者能使用的地方后者一定也能使用。如果需要在运行时去动态获取注解信息,那只能用 RUNTIME 注解;如果要在编译时进行一些预处理操作,比如生成一些辅助代码(如 ButterKnife),就用CLASS 注解;如果只是做一些检查性的操作,比如 @Override 和 @SuppressWarnings,则可选用 SOURCE 注解 3.5 元注解作用及使用 自定义注解: //注解的使用范围为类,方法,成员变量 @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) // RUNTIME:在运行时有效(即运行时保留) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String name() default "defaultValue"; // 默认值 } 4.1 通过反射获取注解信息 1,自定义注解: @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String name() default "defaultValue"; // 默认值 } 4.2 通过反射获取注解信息 2,定义一个类,使用注解: //注解里使用了默认值可不填参数 @MyAnnotation(name = "I am A class") public class Dcs { @MyAnnotation(name = "I am a field") public String name; @MyAnnotation(name = "I am a method") public void testMethod() { System.out.println("testMethod"); } } 4.3 通过反射获取注解信息 3,测试代码: public static void main(String[] args) throws Exception { Class<Dcs> c = Dcs.class; // 获取类上的所有注解 Annotation[] a1 = c.getAnnotations(); // 获取类上的指定注解 MyAnnotation a2 = c.getAnnotation(MyAnnotation.class); // 获取字段上的注解 Field n = c.getField("name"); MyAnnotation a3 = n.getAnnotation(MyAnnotation.class); //获取方法上的注解 Method method = c.getMethod("testMethod"); MyAnnotation a4 = method.getAnnotation(MyAnnotation.class); // 获取注解里的信息 String name = a4.name(); } 课后练习题 1,自定义一个学生注解,注解中有3个成员变量,name,age,sex。3个成员变量都有默认值,name=张三,age=18,sex=男。注解的修饰范围为类。新建一个学生类,在学生类上使用自定义注解。使用反射机制创建学生对象,并根据注解里面的成员变量的值来初始化学生对象。 标签:__,sir,Java,name,自定义,class,注解,public From: https://www.cnblogs.com/xiaolehong/p/16747172.html