IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> android 注解和反射 (入门以及使用) -> 正文阅读

[移动开发]android 注解和反射 (入门以及使用)

先来看一看今天的效果:

代码效果:


效果不重要,重要的是代码:

注解

官方解释:

从JDK5开始,Java增加对元数据的支持,也就是注解,注解与注释是有一定区别的,可以把注解理解为代码里的特殊标记,这些标记可以在编译,类加载,运行时被读取,并执行相应的处理。通过注解开发人员可以在不改变原有代码和逻辑的情况下在源代码中嵌入补充信息。

百度百科

定义一个注解:

public @interface SZJ{
}

元注解:

元注解是用来标示当前注解是干什么用的,什么时候用,常用的有2个

@Target

  • ElementType.ANNOTATION_TYPE 应用于注解类型。
  • ElementType.CONSTRUCTOR 应用于构造函数。
  • ElementType.FIELD 应用于字段或属性。
  • ElementType.LOCAL_VARIABLE 应用于局部变量。
  • ElementType.METHOD 应用于方法级注解。
  • ElementType.PACKAGE 可以应用于包声明。
  • ElementType.PARAMETER 可以应用于方法的参数。
  • ElementType.TYPE 可以应用于类的任何元素。

@Retention

  • RetentionPolicy.SOURCE 仅用于源码级别,会被编译器忽略[编译成class后,会被class丢弃该注解]
  • RetentionPolicy.CLASS 在编译器由编译器保留,JVM会忽略
  • RetentionPolicy.RUNTIME 由JVM保留,运行时可以使用

CLASS包含了SOURCE,RUNTIME包含SOURCE、CLASS。

SOURCE<CLASS<RUNTIME

举例:
在这里插入图片描述
@Retention注解解释:

RetentionPolicy.SOURCE 仅用于源码级别,会被编译器忽略[编译成class后,会被class丢弃该注解]

在这里插入图片描述
这个注解太偏源码,用到的地方比较少

RetentionPolicy.CLASS 在编译器由编译器保留,JVM会忽略

在这里插入图片描述
这个注解一般是APT技术用到的比较多,像一些ARouter,EventBus,Butterknifer等等框架都是用的这个注解.

反射

定义:

反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和
方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。是Java被视为动态语言的关键。

百度百科

使用场景:

不知道某个类是什么类,用来干什么的,就可以通过反射机制直接调用到他内部的属性,以及方法

反射与Class:

反射始于Class,Class是一个类,封装了当前对象所对应的类的信息。一个类中有属性,方法,构造器等,比如说有一个Person类,一个Book类,这些都是不同的类,现在需要一个类,用来描述类,这就是Class,它应该有类名,属性,方法,构造器等。Class是用来描述类的类。

获得Class对象:

  • 类名获取: 类名.class
  • 对象名获取: 对象名.getClass()
  • 全类名获取: Class.forName(“全类名”)

代码展示:

public void test() {
        System.out.println("我是方法哦");

        //类名获取
        Class<?> intCls = int.class;
        Class<?> strCls = String.class;

          //对象名获取
        UserBean userBean = new UserBean();
        Class<? extends UserBean> userBeanCls = userBean.getClass();

        //全类名获取
        try {
            Class<?> userBeanCls2 = Class.forName("com.example.annotation.bean.UserBean");

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

反射的🌰:

 public void test() {
        System.out.println("我是方法哦");

        //TODO 对象名获取 class
        UserBean userBean = new UserBean();
        Log.i("szjUserBean",userBean.toString());
        try {
            Class<? extends UserBean> userBeanCls = userBean.getClass();
            Field nameField = userBeanCls.getDeclaredField("name");
            //允许访问 private
            nameField.setAccessible(true);
            //修改状态
            nameField.set(userBean,"SZJ");
            Log.i("szjUserBean",userBean.toString());


            //TODO 全类名获取 class
            Class<?> userBeanCls2 = Class.forName("com.example.annotation.bean.UserBean");
            Field nameField2 = userBeanCls2.getDeclaredField("name");
            nameField2.setAccessible(true);
            //修改状态
            nameField2.set(userBean,"我是SZJ");
            Log.i("szjUserBean",userBean.toString());


            //TODO 反射调用方法
            Method test = userBeanCls.getMethod("test",String.class,int.class);
            String userTestRt = (String) test.invoke(userBean, "张三1", 22);
            Log.i("szjUserBean",userTestRt);


            Method test2 = userBeanCls.getDeclaredMethod("test2",String.class,int.class);
            //允许访问private
            test2.setAccessible(true);
            String userTestRt2 = (String) test2.invoke(userBean, "张三2", 33);
            Log.i("szjUserBean2",userTestRt2);

        } catch (Exception e) {
            e.printStackTrace();
            Log.i("szjError", e.toString());
        }
    }

效果图:

在这里插入图片描述

  • getDeclaredField(String) 获得自己的成员属性[不包括父类,包括private]
  • getFields(String) 获得自己+父类的成员属性[不包括private]
  • Field[] = getDeclaredFields() 获取到所有的属性
  • getMethod(参数名,参数.class) 获得方法[不包括父类,包括private]
  • getDeclaredMethod(参数名,参数.class) 获得自己+父类的成员方法[不包括private]
  • Method[] = getDeclaredMethods() 获取所有的方法
  • Field.setAccessible(boolean) 是否允许访问private属性

反射获取到注解:

  • Field.isAnnotationPresent(Class) 属性上是否有该注解
  • Field.getAnnotation(Class) 获取到属性上注解
  • Annotation[] = Method.getAnnotations() 获取到方法上的所有注解
  • Annotation.annotationType() 获取到方法上注解的注解类型

注解配合反射实现效果

定义注解:

//运行时存在
@Retention(RetentionPolicy.RUNTIME)
//作用来属性上
@Target(ElementType.FIELD)
public @interface szjFind {

   //IdRes: 用来区分传入 int 类型 是否是id
   @IdRes int value();
}

通过反射和注解给控件赋值:

//TODO findViewById
    public void initFind(Activity activity) {
        //获取 Class
        Class<? extends Activity> cls = activity.getClass();

        //getFields 获得自己+父类的成员 不包括 private
        //getDeclaredFields 获得自己的成员(不包括父类,包括 private)

        //获得此类所有的属性
        Field[] fields = cls.getDeclaredFields();
        //遍历这个类中的所有属性
        for (Field field : fields) {
            //判断属性是否被 szjFind 注解
            if (field.isAnnotationPresent(szjFind.class)) {
                //获得注解的实例
                szjFind szjFind = field.getAnnotation(szjFind.class);

                assert szjFind != null;
                //获取 id
                int id = szjFind.value();
                //找到 Id
                View view = activity.findViewById(id);

                //允许操作 private 属性
                field.setAccessible(true);

                try {
                    //反射设置属性的值
                    field.set(activity, view);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
        }
    }

在Activity中注册:

szjAnnotationUtil.getInstance().initFind(this);

代码总览图:

因为高度重复,其余代码请下载demo观看

注意:在实际开发项目中不建议采用这种方式,因为反射非常耗时,本篇只是以[获取控件ID/onClick/Intent]他来举例!

完整代码

原创不易,您的点赞就是对我最大的支持!

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-17 15:30:31  更:2021-08-17 15:31:59 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:07:50-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码