目录
反射机制与什么用
Java可以通过反射操作字节码文件,通过反射机制可以操作代码片段。在java.long.refect包下。
反射机制相关的类
java.lang.refect.Class
代表字节码文件
java.lang.refect.Method
代表字节码中的方法字节码
java.lang.refect.Constructor
代表字节码中的构造方法字节码
java.lang.refect.Field
代表字节码中的属性字节码
如:
public class User{//Class
int no;//Field
public User(){//Constructor
}
public int getUser(){//Method
}
获取类的字节码三种方式
1 通过Class类的静态方法获取字节码
Class c1 = Class.forName("java.lang.String");//需要完整类名,带包名
//forName有异常需要处理
c代表着相应的字节码文件。
2 通过类的getClass()方法获取
String s = "abc";
Class c2 = s.getClass();
注意c1和c2指向同一个字节码文件,c1==c2,相同类型字节码在虚拟机方法区只有一份。
3 通过class属性获取
java任何类型都有class属性
Class c3 = int.class;
通过反射创建对象
Class c = Class.forName(str);
Object obj = c.newInstace();
//通过无参数构造方法构造对象,如果没有无参构造就会出错。
//forName会执行类的静态代码块
如果只想执行类的静态代码块,可以用Class.forName。
获取反射类中的各种属性方法
1 获取属性的名字
Class c = Class.forName(str);
Field[] fields = c.getFields();//只能获取公开属性的方法。
Field[] fields1 = c.getDeclaredFields();//能获取所有属性
String name = fields[0].getName();
2 获取属性的类型
Class c = Class.forName(str);
Field[] fields1 = c.getDeclaredFields();//能获取所有属性
Class type = fields1[0].getType();//获取类型
String fieldname = type.getName();//获取类型名字
3 获取属性的修饰符
Class c = Class.forName(str);
Field[] fields1 = c.getDeclaredFields();//能获取所有属性
int i = fields1[0].getModifiers();//注意返回的是int
String modifier = Modifier.toString(i);//获取修饰符名字
4 获取类中的方法和方法的参数
Method[] mm = c.getDeclaredMethods();//获取方法
s="";
for(Method m :mm){
s.append(Modifier.toString(m.getModifiers())+" ");//获取方法类型
s.append(m.getReturnType().getSimpleName()+" " );//获取方法返回值
s.append(m.getName());//获取方法名字
Class[] pp = m.getParameterTypes();//获取方法参数类型
for(Class p :pp){
s.append(p.getSimpleName());//获取方法参数类型的名字
s.append(",");
}
}
通过反射反编译出类
package homework;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
public class FieldTest {
public static void main(String[] args) throws Exception{
StringBuilder s = new StringBuilder();
Class c = Class.forName("java.lang.String");
Constructor con = c.getDeclaredConstructor();
Object obj = con.newInstance();
System.out.println(obj);
s.append(Modifier.toString(c.getModifiers())+" class "+c.getSimpleName()+"{\n");
Field[] ff = c.getDeclaredFields();
Method[] mm = c.getDeclaredMethods();
for( Field f : ff){
s.append("\t");
s.append(Modifier.toString(f.getModifiers())+" ");
s.append(f.getType().getSimpleName()+" ");
s.append(f.getName());
s.append(";\n");
}
for(Method m :mm){
s.append("\t");
s.append(Modifier.toString(m.getModifiers())+" ");
s.append(m.getReturnType().getSimpleName()+" " );
s.append(m.getName());
s.append("(");
Class[] pp = m.getParameterTypes();
for(Class p :pp){
s.append(p.getSimpleName());
s.append(",");
}
s.deleteCharAt(s.length()-1);
s.append("){}\n");
}
s.append("}");
System.out.println(s);
System.out.println();
System.out.println();
}
}
获取类路径的方法
获取类路径下类的路径的通用方法
//Thread.currentThread当前线程
//getContexClassLoader获取当前线程的类加载器对象
//getResource()获取资源,默认从类的根路径下
Thread.currentThread.getContexClassLoader.getResource(filename).getPath();
通过反射调用方法
Class user = Class.forName("User");
Object obj = user.newInstance();
Method m = user.getDeclaredMethod(String.class,int.class);//必须给出参数类型
Object retrunvalue = m.invoke("123",3);//必须给出参数
反射的作用
1 可以直接从配置文件中读取类名,进而实例化对象
在不改源代码的情况下,就可以创建任何对象,对扩展开放,对修改关闭。