Java注解的简单说明

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.
 * CSDN: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.
 * CSDN:http://blog.csdn.net/Jsagacity
 */
public enum Gender{
	BOY,GIRL,NONE;
}

赋予特殊功能得类:

/**
 * Created by Layne_Yao on 2017-8-5 上午9:51:42.
 * CSDN: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比这个强大多了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值