一、注解
- 它是 jdk1.5 的新特性,它应用在类、接口及枚举等方面,它的作用就是打标记,它不能执行。
-
jdk 的基础注解
- Deprecated 表示类的成员已过时,不建议使用。
- SuppressWarnings 让编译器不要输出警告信息。
- Override
-
用于注解的注解,元注解
- Target 它规定被修饰的注解可以使用在类的哪种成员上,比如类上,方法上,字段上等。
- Retention 它规定被修饰的注解在哪个阶段起作用,比如源代码编写阶段,编译阶段,运行时阶段。
-
注解的来源
- 来源于 jdk ,对基础编程有作用。
- 来源于框架,对于实现框架的功能或应用程序的功能起作用。在使用框架的早期,都是用配置文件来写配置信息,可以把配置信息与源程序分开,实现解耦,让程序结构良好。但是工作量会大,为了让写配置变得更简单方便,出现了注解的应用,它减少了配置工作量,在程序中使用注解是当前所有框架推荐的方式。但是有一小部分的配置没有注解可以替代,因此现代的基于框架的程序开发即会写配置,又要用注解。
-
自定义注解
-
通过自己设计注解来了解注解的工作方式及使用方法。
-
创建注解
-
在新的注解上使用 @Retention() 注解,该注解要求指定一个属性值,取值来自于 RetentionPolicy 的枚举类型,该枚举定义了三个常量
- SOURCE:将被编译器丢弃,指定新注解只能应用在代码的编写阶段,java 程序的开发工具会对这种注解进行解释并处理。
- CLASS:将由编译器记录在类文件中,但 jvm 不需要在运行时保留,在编译期起作用,编译器会解释并处理。
- RUNTIME:将由编译器记录在类文件中,并由 jvm 在运行时保留,因此可以反射读取。
-
综上可见,第一开发工具不是我们写的,编译器也不是我们设计的,对于SOURCE和CLASS指定的阶段,我们自定义注解起不了作用,只有JDK提供的注解才能起作用。我们自定义的往解只能在运行时起作用,因为可能利用反射技术去读取并解释。因此,所有框架提供的注解只能在运行时起作用。
-
在新的注解上使用 @Target() 元注解,该注解规定被指定的注解的使用位置,比如方法上,类上,字段等。
- ElementType 枚举提供了该注解可以使用的属性值
- TYPE:规定注解只能使用在类上
- METHOD:只能使用在方法上
- FIELD:只能使用在字段上
-
注解可以带有属性,也可以没有属性
- 如果注解的作用很单一,可以不写属性
- 如果注解的作用很复杂,也就是在其表达的功能上有很多细分项目,就必须要使用属性,属性可以有多个。
-
属性的分类
- 名称为 value 的属性为默认属性,指定该属性时可以不用指定属性名称(没有指定其它的属性),如,String value() default “default”;(default 属性默认取值)
- 名称不为 value 的属性为一般属性,指定一般属性的值时一定要带有属性名称
-
自定义注解本身没有任何作用,但通过反射技术读取到该注解,然后依据注解的规定来实现不同的功能。
-
框架如果提供了注解,就必须要提供对注解的读取和解释的程序,以便让注解发生作用。
package com.zhong; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME)//注解在运行期起作用 @Target(ElementType.METHOD)//注解使用在方法上 public @interface MyAnnotation { String value() default "default";//默认属性 int[] ary() default {};//一般属性 }
package com.zhong.test_8; import com.zhong.MyAnnotation; public class AnnotationTest { @MyAnnotation(value = "abc", ary = {1, 2, 3}) public void annotationUse(String name) { System.out.println("依照注解属性传入的参数值:" + name); } }
package com.zhong.test_8; import com.zhong.MyAnnotation; import java.lang.reflect.Method; //采用反射读取注解并解释执行的方式 public class UseAnnotation { public static void main(String[] args) throws Exception { Class<?> aClass = Class.forName("com.zhong.test_8.AnnotationTest"); Method method = aClass.getMethod("annotationUse", String.class); /*Annotation[] annotations = method.getDeclaredAnnotations(); for (Annotation annotation : annotations) { System.out.println(annotation.annotationType().getName()); }*/ AnnotationTest o = (AnnotationTest) aClass.newInstance(); MyAnnotation annotation = method.getDeclaredAnnotation(MyAnnotation.class); if (annotation != null) {//成立就表示注解被读取了 String value = annotation.value(); int[] ary = annotation.ary(); for (int i : ary) { System.out.print(i + " "); } method.invoke(o, value); //System.out.println(value); } } }
-
二、枚举
-
我们在编程过程中,需要用一个变量的值来表示星期几。
package com.zhong.test_8; //枚举是一种特殊的类型,它具有有限个的元素,这些元素是本类型的对象 public enum WeekDay { SUN(0), MON(1), TUE(2), WED(3), THU(4), FRI(5), SAT(6);//枚举的元素,必须出现在最前面,元素的类型就是本枚举的类型 //枚举可以有成员变量 private int index; //枚举可以有私有的构造方法 WeekDay() { } WeekDay(int index) { this.index = index; } public int getIndex() { return index; } }
package com.zhong.test_8; public class EnumDemo { public static void main(String[] args) { WeekDay day1 = WeekDay.SUN; WeekDay day2 = WeekDay.MON; WeekDay day3 = WeekDay.TUE; System.out.println(day1.getIndex()); System.out.println(day2.getIndex()); System.out.println(day3.getIndex()); } }