java注解

总结于这位大佬的博客

定义:上面大佬的博客中将注解比作标签,我这边的理解不同,因为标签可以随便贴在哪个瓶子上但是瓶子本身的性质、能力等没有变化。注解实际上是让一个事物拥有了更多特性,一个注解对应一种特性,被该注解标记的事物就拥有了这种特性,就好比游戏里镶嵌在宝剑上的宝石,有加攻击的宝石、有加攻速的宝石等等。

创建注解:public @interface TestAnnotation{}

使用:在需要的地方加上 @TestAnnotation(),如果该注解没有任何属性则可以省略()即@TestAnnotation

元注解

定义

给注解注解的注解,有五种:@Retention、@Documented、@Target、@Inherited、@Repeatable

@Retention:时间标签
取值:	RetentionPolicy.SOURCE 	注解存活在源码阶段,编译时丢弃
		RetentionPolicy.CLASS	注解存活到编译,不会加载到JVM中
		RetentionPolicy.RUNTIME	注解存活到程序运行,加载到JVM中,在程序运行时可以获取注解
		
使用:	@Retention(RetentionPolicy.RUNTIME)
		public @interface TestAnnotation{}
@Documented:将注解中的元素包含到 Javadoc 中去
@Target:注解使用限制
取值:	ElementType.ANNOTATION_TYPE 可以给一个注解进行注解
		ElementType.CONSTRUCTOR 可以给构造方法进行注解
		ElementType.FIELD 可以给属性进行注解
		ElementType.LOCAL_VARIABLE 可以给局部变量进行注解
		ElementType.METHOD 可以给方法进行注解
		ElementType.PACKAGE 可以给一个包进行注解
		ElementType.PARAMETER 可以给一个方法内的参数进行注解
		ElementType.TYPE 可以给一个类型进行注解,比如类、接口、枚举
@Inherited:注解可以继承,如果一个类被该注解注解的注解注解了,他的子类没有其他注解的话也拥有改注解
@Repeatable:可使用多次
声明方式:
	@Repeatable(Peoples.class)
	@interface People
	{
		String role() default "";
	}
	如果想要给被注解的东西注解多次则可以使用@Repeatable
	使用前需要创建一个注解容器用来存放这些注解,注解容器拥有是集合类型的属性的注解
	@interface Peoples
	{
		People[] value();
	}
使用:
	@People(role="artist")
	@People(role="driver")
	public class me{
	}

注解的属性

普通类变量,但是变量名后面要加(),默认值用default指定
public @interface TestAnnotation {
	public int id() default -1;
}
使用时
@TestAnnotation()	这时id用默认值
@TestAnnotation(id=2)	也可以@TestAnnotation(2),因为只有一个属性

Java 预置的注解

@Deprecated:标记过时的元素,如果被改注解的方法被调用会有个删除线

@Override:帮助自己检查是否正确的复写了父类中已有的方法(自动检查父类中是否有这个方法,方法的参数是否和父类中的一致)并且告诉读代码的人,这是一个复写的方法

@SuppressWarnings:阻止警告,使用@Deprecated注解过的方法时会有警告,
@SuppressWarnings("deprecation")忽略警告

@SafeVarargs:参数安全类型注解,提醒开发者不要用参数做一些不安全的操作

@FunctionalInterface:函数式接口注解,即一个具有一个方法的普通接口,函数式接口可以很容易转换为 Lambda 表达式,比如经常用到的Runnable

使用注解

  1. 运行时使用:通过反射获取相应的类、属性或者方法
    调用
    getAnnotation 获取指定类型的注解,没有返回null
    getAnnotations 返回所有注解
    isAnnotationPresent 判断是否有指定类型的注解,有true,没有false
    getDeclaredAnnotations 返回直接存在于此元素上的所有注释,不包含继承过来的注解
  2. 编译时使用:在某些代码元素上(如类型、函数、字段等)添加注解;
    编译时编译器会检查AbstractProcessor的子类,
    然后将添加了注解的所有元素都传递到该类的process函数中;
    使得开发人员可以在编译器进行相应的处理。

实例

android jetpack中的Lifecycle关于注解的使用

注解类:OnLifecycleEvent
@SuppressWarnings("unused")
@Retention(RetentionPolicy.RUNTIME)//由于需要在Activity创建后动态绑定观察者,所以这边是运行时
@Target(ElementType.METHOD) //只会用在方法上面
public @interface OnLifecycleEvent {
    Lifecycle.Event value();
}

//观察者,这边使用播放器去观察Activity的生命周期
public class VideoPlayer implements LifecycleObserver{
	//添加注解,在Activity创建时自动创建播放器
	@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    public void createPlayer(){
        ....
    }
}

//被观察者,Activity
public class Activity extends AppCompatActivity{
	@Override
    protected void onCreate(Bundle savedInstanceState) {
    	//添加生命周期观察,这时当Activity创建完,播放器会自动创建
        getLifecycle().addObserver(mVideoPlayer);
    }
}


在运行时通过反射将需要在相应生命周期触发的方法保存下来
实际保存的类是ClassesInfoCache
private CallbackInfo createInfo(Class klass, @Nullable Method[] declaredMethods) {
	...
	//通过反射获取注解
	Method[] methods = declaredMethods != null ? declaredMethods : getDeclaredMethods(klass);
    booleanhasLifecycleMethods = false;
    for (Method method : methods) {
        OnLifecycleEvent annotation = method.getAnnotation(OnLifecycleEvent.class);
        if (annotation == null) {
            continue;
        }
        //使用一个map来保存
        verifyAndPutHandler(handlerToEvent, methodReference, event, klass);
    }
	...
|

当Activity相应生命周期发生时会调用ClassesInfoCache中invokeCallbacks来触发
void invokeCallback(LifecycleOwner source, Lifecycle.Event event, Object target) {
            //noinspection TryWithIdenticalCatches
            try {
                switch (mCallType) {
                    case CALL_TYPE_NO_ARG:
                        mMethod.invoke(target);
                        break;
                    case CALL_TYPE_PROVIDER:
                        mMethod.invoke(target, source);
                        break;
                    case CALL_TYPE_PROVIDER_WITH_EVENT:
                        mMethod.invoke(target, source, event);
                        break;
                }
            } catch (InvocationTargetException e) {
                throw new RuntimeException("Failed to call observer method", e.getCause());
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值