欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java注解应用场景

程序员文章站 2022-07-12 11:27:25
...

注解有三种级别,注解的保留级别不同,对注解的使用场景自然不同,
源码级别: 1.APT 在编译期能够获取注解与注解声明的类,包括类中的 所有成员信息,一般用于生成额外的辅助类.
2.可以提供IDE语法检查,取代枚举的使用
字节码: 1.在编译出Class后,通过修改Class数据以实现修改代码逻辑目的。
2.对于是否需要修改的区分或者修改为不同逻辑的判断可以使用注解(这块还没用应用实例)
运行期: 在程序运行期间,通过反射技术动态获取注解与其元素,从而完成不同的逻辑判断 应用场景(自动注入一个View的findViewById操作)
下面介绍:源码级别提供IDE语法检查案例:

public enum Teacher {
    LIGUOJING,ZHUPENG
}

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {1,2})//提供语法检查需要传递的值
public @interface Teacher2 {
}

public class IdeTest {
    /*
    * 我们定义的test方法,只能传递 LIGUOJING 和 ZHUPENG其中一个,为了进行内存优化
    * 我们现在不使用枚举,则定义方法为:
    * */
    private static final int LIGUOJING = 1;
    private static final int ZHUPENG = 2;

//    然而此时,调用test2方法由于采用基本数据类型int,将无法进行类型限定。
//    此时使用@IntDef增加自定义注解:
    public void test2(int t){
        test3(LIGUOJING);
        test3(ZHUPENG);
        test3(3);//IDE 提供语法检查,3 不符合语法规范,但是编译运行还是没有问题
    }
    // test3方法提供了语法检查,传递的int值必须是@Teacher2里面定义的
    public void test3(@Teacher2 int t){
    }
    public void test(Teacher teacher){
    }
}

在程序运行期间,通过反射技术动态获取注解,并自动完成findViewById操作和成员变量的赋值

public class MainActivity extends AppCompatActivity {
    @Inject(resId = R.id.tvText)
    private TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        InjectUtils.injectViewId(this);
        textView.setText("通过注解进行findViewById操作");
        textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Intent intent = new Intent(MainActivity.this, MainActivity2.class);
                // 这些传递的值,需要在MainActivity2中,通过注解进行赋值操作
                intent.putExtra("zhupeng", "失恋好了吗");
                intent.putExtra("userId", 110);
                intent.putExtra("user", new User("李国菁", 29));
                intent.putExtra("userArray",new User[]{new User("李菁",31),new User("李国伟",22)});
                startActivity(intent);
            }
        });
    }
}

Inject 和 Autowired注解类代码

@Target(ElementType.FIELD)//作用在成员变量上
@Retention(RetentionPolicy.RUNTIME)// 保留在运行时期
public @interface Inject {
    @IdRes int resId();// 其中IdRes 的意思是:必须指定这个int 值为 R.id.xx 类型
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {
    String value() default "";
}

Javabean类

public class User implements Parcelable {
    private String name;
    private int age;

    public User(String name,int age){
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    protected User(Parcel in) {
        name = in.readString();
        age = in.readInt();
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(name);
        dest.writeInt(age);
    }

    @Override
    public int describeContents() {
        return 0;
    }

    public static final Creator<User> CREATOR = new Creator<User>() {
        @Override
        public User createFromParcel(Parcel in) {
            return new User(in);
        }

        @Override
        public User[] newArray(int size) {
            return new User[size];
        }
    };

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
public class MainActivity2 extends AppCompatActivity {
    @Inject(resId = R.id.tvText)
    private TextView textView;
    @Autowired(value = "zhupeng")
    private String zhupeng;
    @Autowired
    private int userId;
    @Autowired
    private User user;
    @Autowired
    private User[] userArray;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        InjectUtils.injectViewId(this);
        InjectUtils.injectAutowired(this);
//      InjectUtils.injectIntentValue(this); 这个方法只能赋值String 和int值
        String str = "";
        for (int i = 0; i <userArray.length ; i++) {
            str+= userArray[i];
        }
        textView.setText(zhupeng + userId + user + "\n" + str);
    }
}

InjectUtils 这块是重点内容,需要仔细查看

public class InjectUtils {
    public static void injectViewId(Activity activity) {
        if (activity == null) {
            throw new RuntimeException("Activity is not null");
        }
        Class<? extends Activity> clazz = activity.getClass();
        //获取所有的成员变量,包括 private类型的成员变量
        Field[] allFields = clazz.getDeclaredFields();
        for (Field field : allFields) {
            // 判断该字段上面是否有注解
            boolean isPresent = field.isAnnotationPresent(Inject.class);
            if (isPresent) {
                // 获取字段上的注解
                Inject fieldAnnotation = field.getAnnotation(Inject.class);
                int viewId = fieldAnnotation.resId();
                View view = activity.findViewById(viewId);
                // 修改 private 成员变量的值,必须加上下面这句,否则会有问题
                field.setAccessible(true);
                // 给这个字段进行赋值
                try {
                    field.set(activity, view);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    public static void injectIntentValue(Activity activity) {
        if (activity == null) {
            throw new RuntimeException("Activity is not null");
        }
        Class<? extends Activity> clazz = activity.getClass();
        //获取所有的成员变量,包括 private类型的成员变量
        Field[] allFields = clazz.getDeclaredFields();
        for (Field field : allFields) {
            // 判断该字段上面是否有注解
            boolean isPresent = field.isAnnotationPresent(Autowired.class);
            if (isPresent) {
                // 获取字段上的注解
                Autowired fieldAnnotation = field.getAnnotation(Autowired.class);
                String key = TextUtils.isEmpty(fieldAnnotation.value()) ? field.getName() : fieldAnnotation.value();
                try {
                    Object value = getValue(field.getType(), activity, key);
                    field.setAccessible(true);
                    field.set(activity, value);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    public static Object getValue(Class clazz,Activity activity,String key){
        System.out.println("clazz : " + clazz);
        if (clazz == String.class){
            return activity.getIntent().getStringExtra(key);
        }else if (clazz == int.class){
            return activity.getIntent().getIntExtra(key,0);
        }
        return new Object();
    }

    public static void injectAutowired(Activity activity) {
        if (activity == null) {
            return;
        }
        Intent intent = activity.getIntent();
        if (intent == null) {
            return;
        }
        // intent 传递参数,都是把参数封装在 bundle里面进行传输的
        Bundle bundle = intent.getExtras();
        if (bundle == null) {
            return;
        }
        Class<? extends Activity> clazz = activity.getClass();
        // 获取所有的成员变量
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            // 判断成员变量上有没有Autowired的注解
            if (field.isAnnotationPresent(Autowired.class)) {
                Autowired autowired = field.getAnnotation(Autowired.class);
                String key = TextUtils.isEmpty(autowired.value()) ? field.getName() : autowired.value();
                // 获取key 值对应的 value
                Object obj = bundle.get(key);
                field.setAccessible(true);
                try {
                    /*
                    * 对于数组类型实现 Parcelable 接口的需要单独处理
                    * */
                    // 获取该字段的真正类型
                    Class<?> type = field.getType();
                    System.out.println("lgj type :" + type);
                    // 获取数组单个元素类型
                    Class<?> componentType = type.getComponentType();
                    // type 类型是数组,并且是 Parcelable 子类数组
                    if (type.isArray() && Parcelable.class.isAssignableFrom(componentType)){
                        Object[] objs = (Object[]) obj;
                        Object[] objects = Arrays.copyOf(objs, objs.length, (Class<? extends Object[]>) type);
                        obj = objects;
                    }
                    // 通过反射进行赋值运算
                    field.set(activity, obj);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}
相关标签: 享学Java基础