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

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

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

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

三、注解结合反射实现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());


    }
}

上一篇下一篇

猜你喜欢

热点阅读