java的反射机制笔记
首先了解什么是反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的
所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。
JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为
动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
通过以上的信息,我们可以猜测下,我们平时所做的应用所接的第三方的sdk,经常会让我们在自己的报名下放置相关的java类,可以添加自己的逻辑,这边应该也是用到了反射的机制,下面一起探索吧^_^,看看反射机制的作用。
这边有篇写的关于import语句的文章,写的不错
http://zhaohe162.blog.163.com/blog/static/3821679720101120104444895/
1.相关操作定义
方法名 | 含义 |
getDeclaredFields() | 获取类包含的全部变量,返回Field[] |
getDeclaredFields(String name) | 获取传入制定的的变量名的变量Field |
getDeclaredMethods() | 获取当前类的所有方法method[] |
getDeclaredMethod(String name ) | 获取当前的name的方法 |
getDeclaredMethod(String name ,class[] …) | 获取当前的name和参数class的方法 |
getReturnType() | 获取方法的返回值类型 |
getParameterTypes() | 获取方法的出入参数 |
getDeclaredConstructors() | 获取当前类的构造方法 |
getDeclaredConstructor(class[],…) | 获取带参数的构造方法 |
getSuperclass() | 获取父类 |
getInterfaces() | 获取当前类实现的接口 |
2.实现获取类的相关变量
先定义一个非常简单的Utils类
public class Utils {
public static String a = "a";
private String b = "b";
protected boolean c = false;
public String getA(){
Log.i("lz","lz do getA =" + a);
return a;
}
public static String getAS(){
Log.i("lz","lz do getAS =" + a);
return a;
}
private String getB(){
Log.i("lz","lz do getB =" + b);
return b;
}
public boolean getC(){
Log.i("lz","lz do getC =" + c);
return c;
}
public void printA(){
Log.i("lz","lz do printA a=" + a);
}
public void printAB(int a){
Log.i("lz","lz do printA a=" + a);
}
}
获取Utils类中的所有变量
//get all fields by class
public static StringBuffer getAllFields(){
StringBuffer sb = new StringBuffer();
try {
//第一种
// Class c = Class.forName("类的目录.Utils");
//第二种
Class c = l.loadClass("类的目录.Utils");
Object o = c.newInstance();
Field d[] = c.getDeclaredFields();
sb.append(Modifier.toString(c.getModifiers()) + " class " + c.getSimpleName() + "\n");
for (Field f:d) {
f.getName();
sb.append("\t");//空格
sb.append(Modifier.toString(f.getModifiers())+" ");//获得属性的修饰符,例如public,static等等
sb.append(f.getType().getSimpleName() + " ");//属性的类型的名字
sb.append(f.getName()+";\n");//属性的名字+回车
}
Log.i("lz","lz do info class=" + sb);
return sb;
} catch (ClassNotFoundException e) {
e.printStackTrace();
Log.i("lz","lz do class 11111111111111111");
} catch (InstantiationException e) {
e.printStackTrace();
Log.i("lz","lz do class 22222222222222222");
} catch (IllegalAccessException e) {
Log.i("lz","lz do class 333333333333333333");
e.printStackTrace();
}
return sb;
}
获取制定名字的变量并且赋值
//set reflect field by give field name
public static String getFieldByName(String name){
Class c = null;
try {
c = l.loadClass("累的目录.Utils");
Object o = c.newInstance();
Field f = c.getDeclaredField(name);
//打破封装
f.setAccessible(true); //使用反射机制可以打破封装性,导致了java对象的属性不安全。
f.set(o,"set do");//设置name的变量的值是set do字符串
return ((Utils)o).getA();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return "";
}
获取所有的方法
public static String getAllMethods(){
Class c = null;
StringBuffer sb = new StringBuffer();
try {
c = l.loadClass("类的目录.Utils");
Method m[] = c.getDeclaredMethods();
for (Method me:m) {
sb.append(Modifier.toString(me.getModifiers()) + " " + me.getName()
+ " " + me.getReturnType() + "\n");
for (Class cl:me.getParameterTypes()) {
sb.append("\t" + cl.getName() + "\n");
}
}
return sb.toString();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return "";
}
public static void doMethodByGiveParams(String methName,Class params[],@android.support.annotation.Nullable Object args[]){
Class c = null;
try {
c = l.loadClass("类的目录.Utils");
Method m = c.getMethod(methName,params);
//出入参数,执行指定的方法,如果有返回值,返回o,方法无参数,args不传 //m.invoke(c)
Object o = m.invoke(c,args);
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
细心的朋友可能已经注意到加载类的两个不同的方法,下面讲述Class.forname 和ClassLoader.loadClass的区别,稍后敬上... ...