Java注解的简单说明

xiaoxiao2021-02-28  150

Java5开始,Java开始对元数据的支持,也就是annotation(注解/标签) 元数据:metadata:描述数据的数据: 所有的Annotation都是java.lang.annotation.Annotation接口的子接口,所以Annotation是一种特殊的接口(枚举也是特殊的类) 枚举:所有的枚举类型都是java.lang.Enum类的子类。--->枚举是一种特殊的类。 注解:所有的注解都是java.lang.annotation.Annotation接口的子接口,注解是一种特殊的接口。 使用注解: 注意:注解本身不具有任何功能,得提供第三方的程序来赋予它功能。 使用注解有三方程序参与: 1、首先必须存在一个注解类; 2、其次必须存在被贴的程序元素; 3、必须有第三方的程序来赋予注解特殊的功能(反射操作)。 在Java中,自带有5个注解:(Java5出现3个,Java7出现1个,Java8出现1个): @Override                                限定子类是否覆写父类方法 @Deprecated                           标记已过时,过时的方法/类不推荐使用 @SuppressWarings                  抑制编译器发出的警告,仅仅是抑制警告,问题依然存在 @SuppressWarings(value="all") @safeVarargs                           抑制堆污染警告(Java7开始出现的) @FunctionalInterface               Java8出现,表示函数式接口,只允许该接口中只有一个抽象方法。如果一个接口中就只有一个抽象方法,也可以不使用注解。可以运用函数式编程(lambda语法)。 Java5才开始出现注解,才开始有@Deprecated注解,但是java.util.Date类中在JDK1.1的时候很多方法就过时了: 在Java5之前标记某一个方法过时,使用文档注释。

/** * Created by Layne_Yao on 2017-8-5 上午9:51:42. * :http://blog.csdn.net/Jsagacity */ public class AnnotationDemo { //从Java5开始 @Deprecated public void annotation1() { } //在Java5之前 /** * @deprecated */ public void annotation2() { } public static void main(String[] args) { } }

注解:用来贴在类,方法,构造器,字段,参数等之上,用于给被贴的程序元素赋予一定的功能。 元注解:在注解定义的时候,必须使用元注解来标注,元注解的注解。 @Retention:决定了注解可以保持在哪一个时期,一共三个时期,都封装在RetentionPolicy枚举类中:        SOURCE:该注解在编译时期就会丢弃,不会存在于字节码文件中,只能存在于源文件中;        CLASS:该注解可以存在源文件和字节码文件中,但是一旦加载进JVM,就丢失;        RUNTIME:该注解可以存在源文件,字节码,JVM中。 自定义的注解类,都是要RUNTIME,因为我们需要在运行时期通过反射赋予注解特殊功能。 @Target:决定了注解可以贴在哪些成员元素之上。可以贴的成员元素都很多,都封装在ElementType枚举类中。           ElementType.ANNOTATION_TYPE 只能修饰注释类型声明            ElementType.CONSTRUCTOR       只能修饰构造方法声明            ElementType.FIELD                        只能修饰字段声明(包括枚举常量)            ElementType.LOCAL_VARIABLE    只能修饰局部变量声明            ElementType.METHOD                  只能修饰方法声明            ElementType.PACKAGE                 只能修饰包声明            ElementType.PARAMETER            只能修饰参数声明            ElementType.TYPE                       只能修饰类、接口(包括注释类型)或枚举声明  @Documentd:使用@Documentd标注的标签会保存字API文档中。 @Inherited:@Inherited标注的标签可以被子类所继承。

在Class,Method,Field,Constructor中有获取/判断注解存在的方法 常用的API: Annotation getAnnotation(Class annotationClass):判断当前类、方法、字段上是否拥有指定的注解,若有,则返回当前对象,若没有返回null; Annotation[] getAnnotations():返回此元素上存在的所有注释。

boolean isAnnotationPresent(Class annotationClass):如果指定类型的注释存在于此元素上,则返回 true,否则返回 false。 

注解类:

//定义注解 @Target(ElementType.TYPE)//只能修饰类、接口(包括注释类型)或枚举声明 @Retention(RetentionPolicy.RUNTIME)//该注解可以存在源文件,字节码,JVM中。 public @interface INFO { //注解是特殊的接口,接口中有抽象方法,在注解八抽象方法称为属性 String username(); int age() default 20;//default是设置默认值 String[] hobby(); Gender sex() default Gender.NONE; } Gender需要设置成public:

/** * Created by Layne_Yao on 2017-8-5 上午11:11:03. * :http://blog.csdn.net/Jsagacity */ public enum Gender{ BOY,GIRL,NONE; } 赋予特殊功能得类:

/** * Created by Layne_Yao on 2017-8-5 上午9:51:42. * :http://blog.csdn.net/Jsagacity */ // 被贴程序元素 @INFO(username = "Layne", age = 18, sex = Gender.BOY, hobby = { "Java", "Android", "C++" }) class User { @Deprecated public void doWork() { } } // 赋予注解特殊功能得 public class AnnotationDemo1 { public static void main(String[] args) throws Exception { // 获取Person类上的VIP注解中的信息 Class cls = User.class; // 获取Person类上所有的注解 Annotation[] as = cls.getAnnotations(); // 判断Person类上是否有VIP注解 boolean isPresent = cls.isAnnotationPresent(INFO.class); if (isPresent) { // 取出Person类上的注解 Annotation a = cls.getAnnotation(INFO.class); // 获取VIP注解中的属性值(调用VIP的抽象方法) INFO vip = (INFO) a; System.out.println(vip.username()); System.out.println(vip.age()); System.out.println(vip.sex()); } // 需求:获取doWork方法上的Deprecated注解 // 1:获取doWork方法所在类的字节码文件 Class doWorkCls = User.class; // 2:获取doWork方法的Method对象 Method m = doWorkCls.getMethod("doWork"); System.out.println(m); // 3:获取当前方法上的注解 Deprecated depre = m.getAnnotation(Deprecated.class); System.out.println(depre); } } 运行结果:

上面程序并没有赋予注解功能。

接下来新建一个Android项目,布局文件里面添加两个控件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.annomationdemo.MainActivity" > <TextView android:id="@+id/tv_show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="180dp" android:text="@string/hello_world" /> <Button android:id="@+id/bt_show" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:text="Button" /> </RelativeLayout> 新建一个注解类:

import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface getViewTo { int value() default -1; } MainActivity.java中:

public class MainActivity extends ActionBarActivity { @getViewTo(R.id.tv_show) private TextView tv_show; @getViewTo(R.id.bt_show) private Button bt_show; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //通过注解生成View getAllAnnomationView(); bt_show.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { tv_show.setText("注解获取成功"); } }); } /** * 解析注解,获取控件 */ private void getAllAnnomationView() { //获取成员变量 Field[] fields = this.getClass().getDeclaredFields(); for (Field field : fields) { try { //判断注解是否为空 if(field.getAnnotations()!=null){ //确定注解类型 if(field.isAnnotationPresent(getViewTo.class)){ //允许修改反射属性 field.setAccessible(true); getViewTo getViewTo = field.getAnnotation(getViewTo.class); //通过findViewById将注解的id,找到View并注入成员变量中 field.set(this, findViewById(getViewTo.value())); } } } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } } } } 这里就不演示运行结果了,大家运行过后可能有点感觉像ButterKnife,不过ButterKnife比这个强大多了。

转载请注明原文地址: https://www.6miu.com/read-19381.html

最新回复(0)