反射
- 官方说明
Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the Java virtual machine. This is a relatively advanced feature and should be used only by developers who have a strong grasp of the fundamentals of the language. With that caveat in mind, reflection is a powerful technique and can enable applications to perform operations which would otherwise be impossible.
- 百度翻译
反射通常由需要检查或修改在Java虚拟机中运行的应用程序运行时行为的程序使用。这是一个相对高级的特性,应该只由对语言基础有很强掌握的开发人员使用。记住这个警告,反射是一种强大的技术,并且能够使应用程序执行否则不可能执行的操作。
- 那么我们可以用反射做什么呢?
我们可以通过使用类的反射来获取私有属性或者动态生成一个类来实现类的各种方法。
用来测试的类
MainActivity
package com.gjn.testproject;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
test();
}
enum Sex {
man,
woman
}
interface InterFace {
void dos();
}
abstract static class BaseClz implements InterFace {
public Sex sex = Sex.man;
protected String base = "base";
private int n = 456;
@Override
public void dos() {
Log.e("-s-", "BaseClz dos");
}
}
static class Clz extends BaseClz {
private static final int NUM = 777;
public static String STR = "cccc";
public String str = "clz.";
private int num = 100;
private Clz(String str) {
this.str = str;
}
@Override
public void dos() {
Log.e("-s-", "Clz dos");
}
}
}
其中包括了一个枚举Sex一个接口两个内置类
Draw
package com.gjn.testproject.test;
public interface Draw {
void draw();
}
Shape
package com.gjn.testproject.test;
import android.util.Log;
public class Shape implements Draw {
public static final String SHAPE = "Shape";
private String shape;
private String x;
public int num;
public String s;
public Shape() {
shape = "null";
x = "?x?";
num = 777;
s = "wo shi s";
}
public Shape(String shape) {
this.shape = shape;
}
private Shape(String s, String xx){
shape = s;
x = xx;
}
private void xxx(){
draw();
Log.e("-s-", "xxx => " + x);
}
@Override
public void draw() {
Log.e("-s-", "draw " + shape);
}
public String getX() {
return x;
}
public void setX(String x) {
this.x = x;
}
}
这一个接口和一个类就是正常的类,那么我们就开始进行反射操作把!
Class
获取类(Class)
获取类(Class)的三种方法
Class.forName(String)
try {
Class c1 = Class.forName("com.gjn.testproject.MainActivity$BaseClz");
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
Object.getClass()
Clz clz = new Clz("1");
Class c2 = clz.getClass();
Class.class
(其中Class为类名)
Class c3 = Shape.class;
第一个方法是用途最大的。后面2种用途比较少。
java.lang.Class的常用方法说明
方法 | 说明 |
---|---|
getName() | 获取Class的全名,可以用来调用Class.forName(String) 生成类的 |
getSimpleName() | 获取Class的简称 |
getCanonicalName() | 获取Class的冠名 就是会将内部类的$ 改成. |
getModifiers() | 获取Class的修饰符 |
getSuperclass() | 获取Class的父类 |
getDeclaringClass() | 获取Class的声明类 |
getComponentType() | 获取Class的组件类型 |
getEnclosingClass() | 获取Class的关闭类 |
getInterfaces() | 获取Class的接口 |
getAnnotations() | 获取Class的全部注解(含继承) 可以用getAnnotation(Class annotationClass) 或者getAnnotation(Class<T> annotationClass) 获取某个注解 |
getDeclaredAnnotations() | 获取Class的全部注解(当前类不包括继承) |
getConstructors() | 获取Class的全部构造函数(含继承) 可以用getConstructor(Class<?>... parameterTypes) 获取某个构造函数 |
getDeclaredConstructors() | 获取Class的全部构造函数(当前类不包括继承) 可以用getDeclaredConstructor(Class<?>... parameterTypes) 获取某个构造函数 |
getMethods() | 获取Class的全部方法(含继承) 可以用getMethod(String name, Class<?>... parameterTypes) 获取某个方法 |
getDeclaredMethods() | 获取Class的全部方法(当前类不包括继承) 可以用getDeclaredMethod(String name, Class<?>... parameterTypes) 获取某个方法 |
getFields() | 获取Class的全部参数(含继承) 可以用getField(String name) 获取某个参数 |
getDeclaredFields() | 获取Class的全部参数(当前类不包括继承) 可以用getDeclaredField(String name) 获取某个参数 |
下面是开头测试test()
的所以代码
private void test() {
try {
Class c1 = Class.forName("com.gjn.testproject.MainActivity$BaseClz");
Clz clz = new Clz("1");
Class c2 = clz.getClass();
Class c3 = Shape.class;
print("c1------------------------------------------");
printClz(c1);
print("c2------------------------------------------");
printClz(c2);
print("c3------------------------------------------");
printClz(c3);
} catch (Exception e) {
e.printStackTrace();
}
}
private void printClz(Class c) {
print("名称 " + c.getName());
print("简称 " + c.getSimpleName());
print("冠名 " + c.getCanonicalName());
print("修饰符 " + Modifier.toString(c.getModifiers()));
print("父类 " + c.getSuperclass());
print("声明类 " + c.getDeclaringClass());
print("组件类型 " + c.getComponentType());
print("关闭类 " + c.getEnclosingClass());
for (Class clz : c.getInterfaces()) {
print("接口 " + clz);
}
for (Annotation annotation : c.getAnnotations()) {
print("注解(含继承) " + annotation);
}
for (Annotation annotation : c.getDeclaredAnnotations()) {
print("注解(当前) " + annotation);
}
for (Constructor constructor : c.getConstructors()) {
print("构造函数(含继承) " + constructor);
}
for (Constructor constructor : c.getDeclaredConstructors()) {
print("构造函数(当前) " + constructor);
}
for (Method method : c.getMethods()) {
print("方法(含继承) " + method);
}
for (Method method : c.getDeclaredMethods()) {
print("方法(当前) " + method);
}
for (Field field : c.getFields()) {
print("参数(含继承) " + field);
}
for (Field field : c.getDeclaredFields()) {
print("参数(当前) " + field);
}
}
private void print(String str) {
Log.e("-s-", str);
Log.e("-s-", "--------------------------------");
}
结果如下
11-12 14:37:57.544 22868-22868/com.gjn.testproject E/-s-: c1------------------------------------------
11-12 14:37:57.544 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.544 22868-22868/com.gjn.testproject E/-s-: 名称 com.gjn.testproject.MainActivity$BaseClz
11-12 14:37:57.544 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.544 22868-22868/com.gjn.testproject E/-s-: 简称 BaseClz
11-12 14:37:57.544 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.544 22868-22868/com.gjn.testproject E/-s-: 冠名 com.gjn.testproject.MainActivity.BaseClz
11-12 14:37:57.544 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.544 22868-22868/com.gjn.testproject E/-s-: 修饰符 abstract static
11-12 14:37:57.544 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.544 22868-22868/com.gjn.testproject E/-s-: 父类 class java.lang.Object
11-12 14:37:57.544 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.544 22868-22868/com.gjn.testproject E/-s-: 声明类 class com.gjn.testproject.MainActivity
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: 组件类型 null
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: 关闭类 class com.gjn.testproject.MainActivity
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: 接口 interface com.gjn.testproject.MainActivity$InterFace
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: 构造函数(当前) com.gjn.testproject.MainActivity$BaseClz()
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public void com.gjn.testproject.MainActivity$BaseClz.dos()
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public boolean java.lang.Object.equals(java.lang.Object)
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final java.lang.Class java.lang.Object.getClass()
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public int java.lang.Object.hashCode()
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final native void java.lang.Object.notify()
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final native void java.lang.Object.notifyAll()
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public java.lang.String java.lang.Object.toString()
11-12 14:37:57.545 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final native void java.lang.Object.wait() throws java.lang.InterruptedException
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final void java.lang.Object.wait(long) throws java.lang.InterruptedException
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final native void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: 方法(当前) public void com.gjn.testproject.MainActivity$BaseClz.dos()
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: 参数(含继承) public com.gjn.testproject.MainActivity$Sex com.gjn.testproject.MainActivity$BaseClz.sex
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: 参数(当前) protected java.lang.String com.gjn.testproject.MainActivity$BaseClz.base
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: 参数(当前) private int com.gjn.testproject.MainActivity$BaseClz.n
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: 参数(当前) public com.gjn.testproject.MainActivity$Sex com.gjn.testproject.MainActivity$BaseClz.sex
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: c2------------------------------------------
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: 名称 com.gjn.testproject.MainActivity$Clz
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: 简称 Clz
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: 冠名 com.gjn.testproject.MainActivity.Clz
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: 修饰符 static
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: 父类 class com.gjn.testproject.MainActivity$BaseClz
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.546 22868-22868/com.gjn.testproject E/-s-: 声明类 class com.gjn.testproject.MainActivity
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: 组件类型 null
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: 关闭类 class com.gjn.testproject.MainActivity
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: 构造函数(当前) private com.gjn.testproject.MainActivity$Clz(java.lang.String)
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: 构造函数(当前) com.gjn.testproject.MainActivity$Clz(java.lang.String,com.gjn.testproject.MainActivity$1)
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public void com.gjn.testproject.MainActivity$Clz.dos()
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public boolean java.lang.Object.equals(java.lang.Object)
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final java.lang.Class java.lang.Object.getClass()
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public int java.lang.Object.hashCode()
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final native void java.lang.Object.notify()
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final native void java.lang.Object.notifyAll()
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public java.lang.String java.lang.Object.toString()
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.547 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final native void java.lang.Object.wait() throws java.lang.InterruptedException
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final void java.lang.Object.wait(long) throws java.lang.InterruptedException
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final native void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: 方法(当前) public void com.gjn.testproject.MainActivity$Clz.dos()
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: 参数(含继承) public java.lang.String com.gjn.testproject.MainActivity$Clz.str
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: 参数(含继承) public static java.lang.String com.gjn.testproject.MainActivity$Clz.STR
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: 参数(含继承) public com.gjn.testproject.MainActivity$Sex com.gjn.testproject.MainActivity$BaseClz.sex
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: 参数(当前) private int com.gjn.testproject.MainActivity$Clz.num
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: 参数(当前) public java.lang.String com.gjn.testproject.MainActivity$Clz.str
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: 参数(当前) private static final int com.gjn.testproject.MainActivity$Clz.NUM
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: 参数(当前) public static java.lang.String com.gjn.testproject.MainActivity$Clz.STR
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: c3------------------------------------------
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: 名称 com.gjn.testproject.test.Shape
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.548 22868-22868/com.gjn.testproject E/-s-: 简称 Shape
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: 冠名 com.gjn.testproject.test.Shape
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: 修饰符 public
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: 父类 class java.lang.Object
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: 声明类 null
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: 组件类型 null
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: 关闭类 null
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: 接口 interface com.gjn.testproject.test.Draw
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: 构造函数(含继承) public com.gjn.testproject.test.Shape()
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: 构造函数(含继承) public com.gjn.testproject.test.Shape(java.lang.String)
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: 构造函数(当前) public com.gjn.testproject.test.Shape()
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: 构造函数(当前) public com.gjn.testproject.test.Shape(java.lang.String)
11-12 14:37:57.549 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.550 22868-22868/com.gjn.testproject E/-s-: 构造函数(当前) private com.gjn.testproject.test.Shape(java.lang.String,java.lang.String)
11-12 14:37:57.550 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.550 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public void com.gjn.testproject.test.Shape.draw()
11-12 14:37:57.550 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.550 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public boolean java.lang.Object.equals(java.lang.Object)
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final java.lang.Class java.lang.Object.getClass()
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public java.lang.String com.gjn.testproject.test.Shape.getX()
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public int java.lang.Object.hashCode()
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final native void java.lang.Object.notify()
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final native void java.lang.Object.notifyAll()
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public void com.gjn.testproject.test.Shape.setX(java.lang.String)
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public java.lang.String java.lang.Object.toString()
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final native void java.lang.Object.wait() throws java.lang.InterruptedException
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final void java.lang.Object.wait(long) throws java.lang.InterruptedException
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: 方法(含继承) public final native void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: 方法(当前) private void com.gjn.testproject.test.Shape.xxx()
11-12 14:37:57.551 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: 方法(当前) public void com.gjn.testproject.test.Shape.draw()
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: 方法(当前) public java.lang.String com.gjn.testproject.test.Shape.getX()
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: 方法(当前) public void com.gjn.testproject.test.Shape.setX(java.lang.String)
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: 参数(含继承) public int com.gjn.testproject.test.Shape.num
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: 参数(含继承) public java.lang.String com.gjn.testproject.test.Shape.s
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: 参数(含继承) public static final java.lang.String com.gjn.testproject.test.Shape.SHAPE
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: 参数(当前) public int com.gjn.testproject.test.Shape.num
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: 参数(当前) public java.lang.String com.gjn.testproject.test.Shape.s
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: 参数(当前) private java.lang.String com.gjn.testproject.test.Shape.shape
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: 参数(当前) private java.lang.String com.gjn.testproject.test.Shape.x
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: --------------------------------
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: 参数(当前) public static final java.lang.String com.gjn.testproject.test.Shape.SHAPE
11-12 14:37:57.552 22868-22868/com.gjn.testproject E/-s-: --------------------------------
Method
基本使用
正常我们都是获取一个类的方法然后调用就好了,所以大多我们都不考虑继承等方法。
Class.getDeclaredMethod(String name, Class<?>... parameterTypes)
(其中Class是类)Method.invoke(Object obj, Object... args)
(其中Method是方法)
可以调用getDeclaredMethod
获取对应的Method(方法)然后用invoke
来执行方法
注:如果想调用私有的方法需要调用setAccessible(boolean flag)
强制打开权限,但是这个方法不一定能够成功!
还是延用上面的代码继续写如下
try {
...//上面的c1 c2 c3 clz
BaseClz baseClz = new BaseClz() {
@Override
public void dos() {
super.dos();
}
};
Method m1 = c1.getDeclaredMethod("dos");
m1.invoke(baseClz);
Method m2 = c2.getDeclaredMethod("dos");
m2.invoke(clz);
Shape shape = new Shape("circle");
Method m3 = c3.getDeclaredMethod("draw");
m3.invoke(c3.newInstance());
m3.invoke(shape);
Method m4 = c3.getDeclaredMethod("xxx");
m4.setAccessible(true);
m4.invoke(c3.newInstance());
m4.invoke(shape);
Method m5 = c3.getDeclaredMethod("setX", String.class);
m5.invoke(shape, "new x");
Method m6 = c3.getDeclaredMethod("getX");
print("getX = " + m6.invoke(shape));
} catch (Exception e) {
e.printStackTrace();
}
结果如下
11-13 10:53:23.321 13278-13278/com.gjn.testproject E/-s-: BaseClz dos
11-13 10:53:23.321 13278-13278/com.gjn.testproject E/-s-: Clz dos
11-13 10:53:23.321 13278-13278/com.gjn.testproject E/-s-: draw null
11-13 10:53:23.321 13278-13278/com.gjn.testproject E/-s-: draw circle
11-13 10:53:23.321 13278-13278/com.gjn.testproject E/-s-: draw null
11-13 10:53:23.321 13278-13278/com.gjn.testproject E/-s-: xxx => ?x?
11-13 10:53:23.321 13278-13278/com.gjn.testproject E/-s-: draw circle
11-13 10:53:23.321 13278-13278/com.gjn.testproject E/-s-: xxx => null
11-13 10:53:23.321 13278-13278/com.gjn.testproject E/-s-: getX = new x
11-13 10:53:23.321 13278-13278/com.gjn.testproject E/-s-: --------------------------------
前面两个m1和m2就是直接调用dos方法 按照测试类可以直接得出结果。
然后是m3这边有两个 一个是直接用类生成的对象c3.newInstance()
还有一个是临时创建的对象Shape shape = new Shape("circle");
所以才有了两种结果
之后是m4我们可以看到去调用了私有的方法,就先取得权限在去调用方法
最后的m5 m6 就是对有参和有返回值的方法调用,其实和上面一样只不过上面的方法没有参数和返回值而已。
常见错误
- 泛型擦除导致的
NoSuchMethodException
当你反射泛型的时候要记住泛型最后都被编译成了Object!
例如
Class c4 = new MethodT<Integer>().getClass();
Method m7 = c4.getDeclaredMethod("t", Object.class);
print(m7.toGenericString());
Method m8 = c4.getDeclaredMethod("t", Integer.class);
print(m8.toGenericString());
结果如下
11-13 11:39:19.851 15595-15595/com.gjn.testproject E/-s-: public void com.gjn.testproject.MainActivity$MethodT.t(T)
11-13 11:39:19.851 15595-15595/com.gjn.testproject E/-s-: --------------------------------
11-13 11:39:19.851 15595-15595/com.gjn.testproject W/System.err: java.lang.NoSuchMethodException: t [class java.lang.Integer]
11-13 11:39:19.851 15595-15595/com.gjn.testproject W/System.err: at java.lang.Class.getConstructorOrMethod(Class.java:472)
11-13 11:39:19.851 15595-15595/com.gjn.testproject W/System.err: at java.lang.Class.getDeclaredMethod(Class.java:640)
11-13 11:39:19.851 15595-15595/com.gjn.testproject W/System.err: at com.gjn.testproject.MainActivity.test(MainActivity.java:189)
11-13 11:39:19.851 15595-15595/com.gjn.testproject W/System.err: at com.gjn.testproject.MainActivity.onCreate(MainActivity.java:95)
11-13 11:39:19.851 15595-15595/com.gjn.testproject W/System.err: at android.app.Activity.performCreate(Activity.java:5248)
11-13 11:39:19.851 15595-15595/com.gjn.testproject W/System.err: at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
11-13 11:39:19.851 15595-15595/com.gjn.testproject W/System.err: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2164)
11-13 11:39:19.851 15595-15595/com.gjn.testproject W/System.err: at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2249)
11-13 11:39:19.851 15595-15595/com.gjn.testproject W/System.err: at android.app.ActivityThread.access$800(ActivityThread.java:141)
11-13 11:39:19.851 15595-15595/com.gjn.testproject W/System.err: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1212)
11-13 11:39:19.851 15595-15595/com.gjn.testproject W/System.err: at android.os.Handler.dispatchMessage(Handler.java:102)
11-13 11:39:19.851 15595-15595/com.gjn.testproject W/System.err: at android.os.Looper.loop(Looper.java:136)
11-13 11:39:19.861 15595-15595/com.gjn.testproject W/System.err: at android.app.ActivityThread.main(ActivityThread.java:5113)
11-13 11:39:19.861 15595-15595/com.gjn.testproject W/System.err: at java.lang.reflect.Method.invokeNative(Native Method)
11-13 11:39:19.861 15595-15595/com.gjn.testproject W/System.err: at java.lang.reflect.Method.invoke(Method.java:515)
11-13 11:39:19.861 15595-15595/com.gjn.testproject W/System.err: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
11-13 11:39:19.861 15595-15595/com.gjn.testproject W/System.err: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:609)
11-13 11:39:19.861 15595-15595/com.gjn.testproject W/System.err: at dalvik.system.NativeStart.main(Native Method)
- 访问不可见方法导致的
IllegalAccessException
就是上面说的m4调用私用方法之前一定要先取得权限!setAccessible(true)
- 反射调用方法时传入错误参数导致的
IllegalArgumentException
如果参数传多了或者少了会报这个错误!例如无参方法写了参数或者有参方法没写参数。
Field
基本使用
和方法一样我们大部分都只需要取当前类的值,所以我们调用getDeclaredField
获取成员变量
Class.getDeclaredField(String name)
(其中Class是类)Field.set(Object obj, Object value)
(其中Field是成员变量)Field.get(Object obj)
(其中Field是成员变量)
例如如下
Field f1 = c3.getDeclaredField("num");
print("num = " + f1.get(shape));
f1.set(shape, 7);
print("num = " + f1.get(shape));
Field f2 = c3.getDeclaredField("x");
f2.setAccessible(true);
print("x = " + f2.get(shape));
f2.set(shape, "shape");
print("x = " + f2.get(shape));
结果
11-13 17:08:15.222 29046-29046/com.gjn.testproject E/-s-: num = 0
11-13 17:08:15.222 29046-29046/com.gjn.testproject E/-s-: --------------------------------
11-13 17:08:15.222 29046-29046/com.gjn.testproject E/-s-: num = 7
11-13 17:08:15.222 29046-29046/com.gjn.testproject E/-s-: --------------------------------
11-13 17:08:15.223 29046-29046/com.gjn.testproject E/-s-: x = new x
11-13 17:08:15.223 29046-29046/com.gjn.testproject E/-s-: --------------------------------
11-13 17:08:15.223 29046-29046/com.gjn.testproject E/-s-: x = shape
11-13 17:08:15.223 29046-29046/com.gjn.testproject E/-s-: --------------------------------
11-13 17:08:15.223 29046-29046/com.gjn.testproject E/-s-: draw circle
11-13 17:08:15.223 29046-29046/com.gjn.testproject E/-s-: xxx => shape
调用私有的方法要注意也要setAccessible(true)
获取权限
常见错误
- 无法转换类型导致的
IllegalArgumentException
- 反射非 public 的变量导致的
NoSuchFieldException
- 修改 final类型的变量导致的
IllegalAccessException
总结
反射是会消耗资源的对运算也有性能开销,因为在反射时这样的操作需要引发许多额外操作,比如验证访问权限等。
最好在比较特殊的情况使用,例如注解生成一系列的功能的时候。
而且编译java代码的时候编译器是会对代码进行优化的,好比你写了String xx= "xxxxx"
跟在后面又写了xx="123"
那么代码优化的时候会直接取后一个过滤掉多余的代码,但是使用反射成员变量的Field.set
就没有这些优化了。
还有一个要注意的就是,反射修改某些私有的成员变量的时候可能会导致部分变了部分没变这类情况,所以要对反射的代码逻辑很理解在使用比较好!
资料
深入理解 Java 反射:Class (反射的入口)
深入理解 Java 反射:Method (成员方法)
深入理解 Java 反射:Field (成员变量)