美文网首页
二、Java高级特性(注解与反射)

二、Java高级特性(注解与反射)

作者: 大虾啊啊啊 | 来源:发表于2021-05-23 16:12 被阅读0次

    一、前言

    注解可以理解成标记,打标签。单独的一个注解是没用的,需要搭配使用,例如搭配反射等等。我们需要通过使用注解上的值来做相应的操作。

    二、自定义一个注解

    package com.example.myapplication;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    /**
     * 自定义一个注解
     * InjectAnnotation
     * 注解可以理解成标记,打标签,
     * 1、设置Retention注解,表示定义注解的级别、也可以理解为注解的生命周期
     * (1)RetentionPolicy.SOURCE源码上
     * 表示注解存在源码中,当通过JAVAC编译成字节码之后,注解便不存在。此类型注解可以用在我们的注解处理中
     * 因为注解处理器的方法执行在编译器,我们可以在注解处理器的方法执行时候获取我们的注解内容,做相应的一些操作,例如生成一些我们需要的辅助类
     * 比如Arouter框架。也可以用于源代码的检查。例如当我们的方法希望传递指定的类型的时候,可以使用注解来限制。
     * (2)RetentionPolicy.CLASS字节码上
     * 此类型注解表示注解在字节码中存在,即源码编译成字节码,注解一直存在。可以用在字节码增强、插装的一些实现。
     * 也就是在字节码中获取注解内容,针对原有字节码进行一些修改,而达到字节码增强的效果。例如我们的热修复
     * <p>
     * (3)RetentionPolicy.RUNTIME 运行期间,也叫运行行注解
     * 运行时注解,也就是从编译到运行,注解一直存在,在程序运行的时候,我们可以使用我们的注解。例如:我们程序运行的时候,我们可以通过获取注解+反射来实现一些功能,例如
     * 实现view.findId
     * <p>
     * <p>
     * 2、设置注解作用目标的对象
     * 常用的有
     * (1)TYPE 作用在类上
     * (2)FIELD  变量上
     * (3)METHOD 方法上
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface ValueAnnotation {
        
        String value();
        
        DataType dataType();
    
    
    }
    

    自定义注解使用@interface关键字,并在注解上使用@Retention注解和@Target注解

    • 1、设置Retention注解,表示定义注解的级别、也可以理解为注解的生命周期

    (1)RetentionPolicy.SOURCE源码上
    表示注解存在源码中,当通过JAVAC编译成字节码之后,注解便不存在。此类型注解可以用在我们的注解处理中
    因为注解处理器的方法执行在编译器,我们可以在注解处理器的方法执行时候获取我们的注解内容,做相应的一些操作,例如生成一些我们需要的辅助类。比如Aruter框架。也可以用于源代码的检查。例如当我们的方法希望传递指定的类型的时候,可以使用注解来限制。

    (2)RetentionPolicy.CLASS字节码上
    此类型注解表示注解在字节码中存在,即源码编译成字节码,注解一直存在。可以用在字节码增强、插装的一些实现。 也就是在字节码中获取注解内容,针对原有字节码进行一些修改,而达到字节码增强的效果。例如我们的热修复。

    (3)RetentionPolicy.RUNTIME 运行期间上的注解
    也叫运行时注解,运行时注解,也就是从编译到运行,注解一直存在,在程序运行的时候,我们可以使用我们的注解。例如:我们程序运行的时候,我们可以通过获取注解+反射来实现一些功能,例如: 实现findById

    • 2、设置注解作用目标的对象(Target注解)
      常用的有:
      (1)TYPE 作用在类上
      (2)FIELD 变量上
      (3)METHOD 方法上
    • 3、设置注解的值
      例如代码中的,value和dataType,注解值可以有多个

    三、注解结合反射实现Android中Activity页面跳转Intent值的获取

    1、自定义一个注解,也就是上面的注解
    2、创建一个工具类
    主要功能就是通过反射获取Activity中的成员属性,并且是获取带有我们自定义注解的属性成员。然后获取注解上的值,注解上设置了两个值:字符串参数名和枚举类型的数据类型。
    根据数据类型和参数名,通过activity.getIntent()来获取Intent上的值,拿到值之后,给成员赋值即可

    package com.example.myapplication;
    
    import java.lang.reflect.Field;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    public class InjectUtils {
    
        public static void init(AppCompatActivity activity) {
            //1、通过actibity对象获取class对象
            Class<? extends AppCompatActivity> activityClass = activity.getClass();
            //2.获取该类的所有成员
            Field[] fields = activityClass.getDeclaredFields();
            //3.遍历获取:有打上ValueAnnotation注解的成员
            for (int i = 0; i < fields.length; i++) {
                if (fields[i].isAnnotationPresent(ValueAnnotation.class)) {
                    try {
                        //4、给成员设置访问权限、
                        fields[i].setAccessible(true);//也就是当成员是private的时候,允许访问
                        //5、获取成员上的注解的值
                        ValueAnnotation valueAnnotations = fields[i].getAnnotation(ValueAnnotation.class);
                        String value = valueAnnotations.value();
                        DataType dataType = valueAnnotations.dataType();
                        //6、判断数据类型,设置值
                        if (dataType == DataType.IntegerData) {
                            Integer result = activity.getIntent().getIntExtra(value, 0);
                            fields[i].set(activity, result);
                        }
                        if (dataType == DataType.StringData) {
                            String result = activity.getIntent().getStringExtra(value);
                            fields[i].set(activity, result);
                        }
    
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
    
    
                }
    
    
            }
    
        }
    
    }
    
    

    在Activity上使用

    package com.example.myapplication;
    
    import android.os.Bundle;
    import android.util.Log;
    
    import java.lang.reflect.Type;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    public class ResultActivity extends AppCompatActivity {
        @ValueAnnotation(value = "result", dataType = DataType.StringData)
        private String result;
        @ValueAnnotation(value = "age", dataType = DataType.IntegerData)
        private Integer age;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            InjectUtils.init(this);
            Log.e("ResultActivity", "result =  " + result);
            Log.e("ResultActivity", "age =  " + age);
    
    //        //通过反射获取泛型类型
    //        //通过匿名内部类来实现,获取泛型的类型
    //        TypeClass<String> typeClass = new TypeClass<String>() {
    //        };
    //        Log.e("ResultActivity", "getType =  "+typeClass.getType());
    
    
        }
    }
    
    

    相关文章

      网友评论

          本文标题:二、Java高级特性(注解与反射)

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