美文网首页
注解 反射

注解 反射

作者: 30cf443c3643 | 来源:发表于2018-11-04 12:53 被阅读2次

    注解分类

    分为标准注解和元注解

    标准注解

    • @Override 对覆盖超类中的方法进行标记
    • @Deprecated 标记方法将被抛弃。如果某个类成员的提示中出现了个词,就表示这个并不建议使用这个类成员
    • @SuppressWarnings 取消特定代码中的警告

    元注解

    用来注解其他注解,有以下几种

    • @Target 注解所修饰的对象范围
    • @Inherited 表示注解的内容可以被子类继承
    • @Documented 表示这个注解应该被JavaDoc工具记录
    • @Retention 注解的保留策略

    Target有以下取值范围

    ElementType 能修饰 说明
    TYPE 类、接口或枚举类型
    FIELD 成员变量
    METHOD 方法
    PARAMETER 参数
    CONSTRUCTOR 构造器
    LOCAL_VARIABLE 局部变量
    ANNOTATION_TYPE 注解
    PACKAGE

    Retention 自定义注解的有效范围

    • RetentionPolicy.SOURCE: 源码级注解 只在源代码中保留 一般都是用来增加代码的理解性或者帮助代码检查之类的,比如我们的Override;
    • RetentionPolicy.CLASS: 编译时注解 默认的选择,能把注解保留到编译后的字节码class文件中,仅仅到字节码文件中,运行时是无法得到的;
    • RetentionPolicy.RUNTIME: 运行时注解,注解不仅 能保留到class字节码文件中,还能在运行通过反射获取到,这也是我们最常用的。

    注解代替枚举

    通过View.VISIBLE的源码,我们可以发现VISIBLE,INVISIBLE和GONE是用注解来实现枚举的作用的

        @IntDef({VISIBLE, INVISIBLE, GONE})
        @Retention(RetentionPolicy.SOURCE)
        public @interface Visibility {}
        
        public static final int VISIBLE = 0x00000000;
        public static final int INVISIBLE = 0x00000004;
        public static final int GONE = 0x00000008;
    

    Android注解

    在android.support.annotation包中也提供了许多资源的注解

    name exp
    AnimRes 动画
    AnimatorRes animator资源类型
    AnyRes 任何资源类型
    ArrayRes 数组资源
    AttrRes attr
    BoolRes bool资源
    ColorRes 颜色资源
    DimenRes 尺寸资源
    DrawableRes 图片资源
    IdRes id资源
    InterpolatorRes 插值器资源
    LayoutRes 布局资源
    MenuRes 菜单资源
    RawRes raw资源
    StringRes 字符资源
    StyleRes 风格资源
    StyleableRes styleable资源
    TransitionRes transition资源类型
    XmlRes xml资源

    资源注解是为了防止我们在使用程序资源的时候,错误传递资源类型给函数,导致程序错误

    Null注解

    • @NonNull:不能为空
    • @Nullable:可以为空

    线程注解

    • @UiThread
    • @BinderThread只在绑定线程上
    • @WorkerThread子线程
    • @AnyThread任意

    其他

    • IntDef
    • StringDef
    • LongDef
    • RequiresApi 表示注释的元素只应在给定API级别或更高级别上调用。
    • RequiresPermission
       @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
       public abstract Location getLastKnownLocation(String provider);
       
       @RequiresPermission(allOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
       public abstract Location getLastKnownLocation(String provider);
     
    
    • IntRange
    private void testDo(@IntRange(from = 1,to = 100)int s){
            Log.e("tag","-------->"+s);
        }
    
    • Size 表示注释的元素应该具有给定的大小或长度。注意“-1”的意思是“未设置”
    • floatRange
      可以在google文档中查看

    注解处理器

    是javac的一个工具,用来扫描和处理注解。就是在编译时期,通过注解生成.java文件。针对运行时,采用反射机制。针对编译时,注解会采用AbstractProcessor处理

    1647e53e3d5d3365.jpg

    Step 1 新增注解类

    新建Module来存放注解,取名为annotations

    1647def00161e26d.jpg

    同时新增一个注解类

    @Retention(RetentionPolicy.CLASS)
    @Target(ElementType.FIELD)
    public @interface BindView {
        int value();
    }
    

    Step 2 编写注解处理器

    新建一个java library,命名为apt-processor

    1647df7689b1ffaf.jpg

    里面的build.gradle跟android library的内容有些不一样,同时添加依赖apt-annotations

    apply plugin: 'java-library'
    
    dependencies {
        implementation fileTree(dir: 'libs', include: ['*.jar'])
        implementation project(':apt-annotations')   //implementation替代了之前的compile
    }
    
    sourceCompatibility = "1.7"
    targetCompatibility = "1.7"
    

    接着编写注解处理器ClassProcessor,继承自AbstractProcessor

    public class ClassProcessor extends AbstractProcessor{
    
        @Override
        public synchronized void init(ProcessingEnvironment processingEnvironment) {
            super.init(processingEnvironment);
        }
    
        @Override
        public Set<String> getSupportedAnnotationTypes() {
            return super.getSupportedAnnotationTypes();
        }
    
        @Override
        public SourceVersion getSupportedSourceVersion() {
            return super.getSupportedSourceVersion();
        }
    
        @Override
        public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
            return false;
        }
    }
    
    • init
      初始化。可以得到ProcessingEnviroment,ProcessingEnviroment提供很多有用的工具类Elements, Types 和 Filer
    • process
      可以在这里写扫描、评估和处理注解的代码,生成Java文件
    • getSupportedAnnotationTypes
      指定这个注解处理器是注册给哪个注解的,这里说明是注解BindView
    • getSupportedSourceVersion
      返回java版本。通常返回SourceVersion.latestSupported

    Step 3 注册注解处理器

    在processor中添加依赖

    implementation 'com.google.auto.service:auto-service:1.0-rc4'

    在注解处理器ClassProcessor中添加@AutoService(Processor.class)

    Step 4 app依赖

    dependencies {
        implementation project(':apt-annotation')
        annotationProcessor project(':apt-processor')
    }
    

    注解处理器只在编译期间用到,处理完后没有作用,
    使用apt插件可以减少引入不必要的文件。官方(Android)提供了annotationProcessor来代替android-apt

    参考APT,里面写了如何去生成一个java文件,可以通过javapoet工具

    反射

    Java反射机制是指在运行状态中
    对于任意一个类,都能知道这个类的所有属性和方法;
    对于任何一个对象,都能够调用它的任何一个方法和属性;
    这样动态获取新的以及动态调用对象方法的功能就叫做反射。

    1.获取Clas的三种方法

    Class c = Class.forName("java.lang.String");
    
    Class c1 = String.Class;
    
    String str = new String();
    Class c2 = str.getClass();
    

    2.获取成员变量

    Field[] fields = c.getDeclaredFields();
    
    获取字段的修饰符
    int fieldValue = field.getModifiers();//如:private、static、final等
    
    与某个具体的修饰符进行比较
    Modifier.isStatic(fieldValue)//看此修饰符是否为静态(static)
    
    获取字段的声明类型
    field.getType();//返回的是一个class
    

    3.获取类的方法

    Method[] methods = c.getDeclaredMethods();
    
                    方法                              含义        
          m.getParameterTypes()             获取传入参数类型Class<?>[]
            m.getReturnType()                获取方法返回类型Class<?> 
    

    c.getDeclaredMethod("方法名",类型.class...) 获取特定的方法
    c.getDeclaredConstructors() 获取所有的构造方法
    c.getDeclaredConstructor(类型.class...) 获取指定的构造方法
    c.getSuperclass() 获取父类Class
    c.getInterfaces() 获取实现的接口Class<?>[]

    运行时注解,是通过反射获取

    public <T extends Annotation> T getAnnotation(Class<T> annotationClass)

    如果存在于此元素,则返回该元素注释指定的注释类型,否则返回为null

    @Retention(RetentionPolicy.RUNTIME)
    //Retention注解决定MyAnnotation注解的生命周期
    @Target( { ElementType.METHOD, ElementType.TYPE })
    public @interface MyAnnotation {
        String color() default "blue";//为属性指定缺省值
    }
    
    private void ResolveClass(String className) {
            try {
                Class<?> clazz = classLoader.loadClass(className);
                Class<?> aClass = classLoader.loadClass(MyAnnotation .class.getName());
                System.out.println(clazz.getName());
                MyAnnotation annotation = clazz.getAnnotation(MyAnnotation .class);
                if(annotation != null) {
                    System.out.println(annotation.color());
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            }
        }
    

    相关文章

      网友评论

          本文标题:注解 反射

          本文链接:https://www.haomeiwen.com/subject/pmawwftx.html