反射可以让我们在运行时获取类的属性,方法,构造方法、父类、接口等信息,通过反射还可以让我们在运行期实例化对象、调用方法、即使方法或属性是私有的的也可以通过反射的形式调用。
所有为什么第三方库基本都会使用到反射,正是因为反射这种 “看透 Class” 的能力。
反射相关的类、方法
要看透一个类,首先要获取这个类的对象,其它信息都是通过这个对象获取的,下面的所有的示例具体操作代码请参考 【个人学习项目DroidStudy】,我在这个工程下新建一个 ReflectionActivity,包的路径为 com.sun.study.ui.activity.ReflectionActivity,通过反射相关的类、方法让我看透这个类。
1、获取对象的三种方式:
第一种、知道一个类,直接获取 Class 对象
Class<?> cls1 = ReflectionActivity.class;
第二种、如果已经得到了某个对象,可以通过这个对象获取 Class 对象
ReflectionActivity activity = new ReflectionActivity();
Class<?> cls2 = activity.getClass();
第三种、如果你在编译期获取不到目标类型,但是你知道它的完整类路径,那么你可以通过如下的形式来获取 Class 对象,这样获取可能会抛出异常 ClassNotFoundException。
try {
Class<?> cls3 = Class.forName(“com.sun.study.ui.activity.ReflectionActivity”);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
2、反射的相关方法和示例
列出反射的相关方法
getName():获得类的完整名字。
newInstance():通过类的不带参数的构造方法创建这个类的一个对象。
getFields():获得类的public类型的属性。
getDeclaredFields():获得类的所有属性。
getMethods():获得类的public类型的方法。
getDeclaredMethods():获得类的所有方法。
getMethod(String name, Class[] parameterTypes):获得类的特定方法。
getModifiers()和Modifier.toString():获得属修饰符,例如private,public,static等
getReturnType():获得方法的返回类型
getParameterTypes():获得方法的参数类型
getConstructors():获得类的public类型的构造方法。
getConstructor(Class[] parameterTypes):获得类的特定构造方法。
getSuperclass():获取某类的父类
getInterfaces():获取某类实现的接口
示例一:获得类的所有方法(Method)信息
private void getMethodsInfo() { Class cls = ReflectionActivity.class; Method[] methods = cls.getDeclaredMethods(); if (methods == null) return; StringBuilder sb = new StringBuilder(); for (Method method:methods) { sb.append(Modifier.toString(method.getModifiers())).append(" “); sb.append(method.getReturnType()).append(” “); sb.append(method.getName()).append(”(“); Class[] parameters = method.getParameterTypes(); if (parameters != null) { for (int i=0; i<parameters.length; i++) { Class paramCls = parameters[i]; sb.append(paramCls.getSimpleName()); if (i < parameters.length - 1) sb.append(”, “); } } sb.append(”)\n\n"); } tvInfo.setText(sb.toString()); }
运行结果如下图:
reflection_icon1.png
示例一:获得类的所有属性(Field)信息,并修改类型Int属性i的值
private void modifyFieldValue() { Class cls = ReflectionActivity.class; Field[] fields = cls.getDeclaredFields(); if (fields == null) return; StringBuilder sb = new StringBuilder(); sb.append(“获得类的所有属性信息:\n\n”); for (Field field:fields) { sb.append(Modifier.toString(field.getModifiers())).append(" “); sb.append(field.getType().getSimpleName()).append(” “); sb.append(field.getName()).append(”;“); sb.append(”\n\n"); } try { sb.append(“属性i的默认值:i = “); Field f = cls.getDeclaredField(“i”); sb.append(f.getInt(“i”)).append(”\n\n”); f.set(“i”, 100); sb.append(“属性i修改后的值:i = “); sb.append(f.getInt(“i”)).append(”\n\n”); } catch (Exception e) { e.printStackTrace(); } tvInfo.setText(sb.toString()); toolbar.setSubtitle(“修改类型Int属性i的值”); }
运行结果如下图:
reflection_icon2.png
更多示例请参考 【个人学习项目DroidStudy】
反射的相关内容先记录到这,接下来看看注解相关概念与使用。
● 注解(Annotation)
注解的概念
注解(Annotation),也叫元数据。一种代码级别的说明。它是JDK 1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明,注释。
注解的作用
1、标记作用,用于告诉编译器一些信息让编译器能够实现基本的编译检查,如@Override、Deprecated,看下它俩的源码
@Target(ElementType.METHOD) @Retention(RetentionPolicy.SOURCE) public @interface Override { } @Documented @Retention(RetentionPolicy.RUNTIME) public @interface Deprecated { }
2、编译时动态处理,动态生成代码,如Butter Knife、Dagger 2
3、运行时动态处理,获得注解信息,如Retrofit
注解的分类
注解的分类有两种分法:
第一种分法
1、基本内置注解,是指Java自带的几个Annotation,如@Override、Deprecated、@SuppressWarnings等
2、元注解(meta-annotation),是指负责注解其他注解的注解,JDK 1.5及以后版本定义了4个标准的元注解类型,如下:
1、@Target
2、@Retention
3、@Documented
4、@Inherited
3、自定义注解,根据需要可以自定义注解,自定义注解需要用到上面的meta-annotation
第二种分法,根据作用域分类
1、源码时注解(RetentionPolicy.SOURCE)
2、编译时注解(RetentionPolicy.CLASS)
3、运行时注解(RetentionPolicy.RUNTIME)
注解相关知识点
1、元注解相关信息
@Target:指Annotation所修饰的对象范围,通过ElementType取值有8种,如下
TYPE:类、接口(包括注解类型)或枚举
FIELD:属性
METHOD:方法
PARAMETER:参数
CONSTRUCTOR:构造函数
LOCAL_VARIABLE:局部变量
ANNOTATION_TYPE:注解类型
PACKAGE:包
@Retention:指Annotation被保留的时间长短,通过RetentionPolicy取值有3种,如下:
SOURCE:在源文件中有效(即源文件保留)
CLASS:在class文件中有效(即class保留)
RUNTIME:在运行时有效(即运行时保留)
@Documented:是一个标记注解,用于描述其它类型的注解应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。
@Inherited:也是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的
2、注解定义格式
public @interface 注解名 { 定义体 }
3、注解参数可支持的数据类型:
8种基本数据类型 int、float、boolean、byte、double、char、long、short String、Class、enum、Annotation 以上所有类型的数组
4、⚠注意:自定义注解如果只有一个参数成员,最好把定义体参数名称设为"value",如@Target
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此我收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
外链图片转存中…(img-FavRuMld-1715863155386)]
[外链图片转存中…(img-mruAFxqc-1715863155387)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!