2024-12-23
Android/Java
00

目录

Java 的反射机制
基本示例
常见的反射方法
调用示例
Java 注解
注解示例
Android 中的注解
MainActivity 示例
实现注解支持的工具类
Reference

Java 的反射机制

Java 反射机制允许你在运行时获取类的详细信息,并且调用对象的方法。它的主要作用包括:

  1. 判断任意对象所属的类;
  2. 动态构建类的对象;
  3. 获取类的成员变量和方法;
  4. 调用对象的方法;
  5. 生成动态代理。

基本示例

以下代码展示了如何使用反射获取类的所有属性:

java
package org.example; import java.lang.reflect.Field; import java.lang.reflect.Modifier; public class Main { public static void main(String[] args) { try { // 获取类 Class<?> c = Class.forName("java.lang.String"); // 获取所有属性 Field[] fields = c.getDeclaredFields(); StringBuffer sb = new StringBuffer(); sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() + " {\n"); // 遍历每个属性 for (Field field : fields) { sb.append("\t"); sb.append(Modifier.toString(field.getModifiers()) + " "); sb.append(field.getType().getSimpleName() + " "); sb.append(field.getName() + ";\n"); } sb.append("}\n"); System.out.println(sb); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }

运行后,你会看到 String 类的所有属性,例如:

text
public final class String { private final byte[] value; private final byte coder; private int hash; private boolean hashIsZero; private static final long serialVersionUID; static final boolean COMPACT_STRINGS; private static final ObjectStreamField[] serialPersistentFields; private static final char REPL; public static final Comparator CASE_INSENSITIVE_ORDER; static final byte LATIN1; static final byte UTF16; }

常见的反射方法

这些方法可以帮助你在运行时获取和操作类的信息:

java
getName():获得类的完整名字。 getFields():获得类的 public 类型的属性。 getDeclaredFields():获得类的所有属性。 getMethods():获得类的 public 类型的方法。 getDeclaredMethods():获得类的所有方法。 getMethod(String name, Class<?>... parameterTypes):获得特定的方法。 getConstructors():获得类的 public 类型的构造方法。 getConstructor(Class<?>... parameterTypes):获得特定的构造方法。 newInstance():通过类的无参构造方法创建一个新对象。

以下代码展示了如何动态调用方法:

java
// 获取方法 Method method = activityClass.getMethod("setContentView", int.class); // 调用方法 method.invoke(activity, layoutId);

调用示例

java
public Object invokeMethod(Object owner, String methodName, Object[] args) throws Exception { Class<?> ownerClass = owner.getClass(); Class<?>[] argsClass = new Class<?>[args.length]; for (int i = 0; i < args.length; i++) { argsClass[i] = args[i].getClass(); } Method method = ownerClass.getMethod(methodName, argsClass); return method.invoke(owner, args); } public Object invokeStaticMethod(String className, String methodName, Object[] args) throws Exception { Class<?> ownerClass = Class.forName(className); Class<?>[] argsClass = new Class<?>[args.length]; for (int i = 0; i < args.length; i++) { argsClass[i] = args[i].getClass(); } Method method = ownerClass.getMethod(methodName, argsClass); return method.invoke(null, args); }

Java中反射相关的类包括:

text
java.lang.Class: 代表类文件的对象 java.lang.reflect.Constructor: 代表构造方法 java.lang.reflect.Field: 代表成员变量 java.lang.reflect.Method: 代表成员方法 java.lang.reflect.Modifier: 判断方法类型 java.lang.annotation.Annotation: 代表注解

Java 注解

注解是Java的元数据,可以为代码提供信息。注解本身通过反射进行解释和处理。常见注解如 @Override 表示方法重写。

注解示例

java
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface MyAnnotation { String value(); }

元注解有如下类型:

java
@Retention(RetentionPolicy.SOURCE) // 编译时丢弃 @Retention(RetentionPolicy.CLASS) // 默认类型,编译时可用 @Retention(RetentionPolicy.RUNTIME) // 运行时可通过反射获取
java
@Target(ElementType.TYPE) // 作用于类 @Target(ElementType.FIELD) // 作用于字段 @Target(ElementType.METHOD) // 作用于方法 @Target(ElementType.PARAMETER) // 作用于参数 @Target(ElementType.CONSTRUCTOR) // 作用于构造方法 @Target(ElementType.ANNOTATION_TYPE) // 作用于注解 @Target(ElementType.PACKAGE) // 作用于包

Android 中的注解

在Android中,注解可以简化代码,尤其是视图绑定,如下所示:

MainActivity 示例

java
@ContentView(R.layout.activity_main) public class MainActivity extends AppCompatActivity { @ViewInject(R.id.button1) private Button button1; @ViewInject(R.id.button2) private Button button2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); AnnotateUtils.inject(this); button1.setText("Button 1"); button2.setText("Button 2"); } }

实现注解支持的工具类

java
@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface ContentView { int value(); } @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface ViewInject { int value(); } public class AnnotateUtils { public static void inject(Activity activity) { injectContentView(activity); injectViews(activity); } private static void injectContentView(Activity activity) { Class<? extends Activity> clazz = activity.getClass(); ContentView contentView = clazz.getAnnotation(ContentView.class); if (contentView != null) { try { Method method = clazz.getMethod("setContentView", int.class); method.invoke(activity, contentView.value()); } catch (Exception e) { e.printStackTrace(); } } } private static void injectViews(Activity activity) { Class<? extends Activity> clazz = activity.getClass(); Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { ViewInject viewInject = field.getAnnotation(ViewInject.class); if (viewInject != null) { try { field.setAccessible(true); field.set(activity, activity.findViewById(viewInject.value())); } catch (Exception e) { e.printStackTrace(); } } } } }

以上代码展示了如何通过注解简化视图绑定,从而减少冗余代码。这样可以使代码更简洁易读。

Reference

Android注解与反射机制

如果对你有用的话,可以打赏哦
打赏
ali pay
wechat pay

本文作者:Dong

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC。本作品采用《知识共享署名-非商业性使用 4.0 国际许可协议》进行许可。您可以在非商业用途下自由转载和修改,但必须注明出处并提供原作者链接。 许可协议。转载请注明出处!