Java中的反射机制
上文我们讲了类文件是如何加载到JVM内存中(类加载过程),这些加载到JVM 的类不仅JVM 能调用它,我们也能通过编程的方式对着写Class对象进行操作,这就要通过反射机制来实现了。
Java中反射主要是通过java.reflect包中的对象来实现的,下面详细介绍下一些常见的反射使用方法。
1.如何获取一个类对象
方式一.通过类的getClass()方法
/**
* 方式一.通过类的getClass()方法
* 都已经得到对象了,反射显得多余
**/
public Class getClassMethod1(){
ManDemo md = new ManDemo();
return md.getClass();
}
方式二.通过类的.class 获取
/**
* 方式二.通过类的.class 获取
* 强依赖,需要引入相关类
**/
public Class getClassMethod2(){
return ManDemo.class;
}
方式三.通过 Class.forName("") 获取
/**
* 方式三.通过 Class.forName("") 获取
* 灵活 首要选择
* 这里需要注意,通过类的全路径名获取Class对象会抛出一个异常,如果根据类路径找不到这个类那么就会抛出这个异常。
**/
public Class getClassMethod3(){
Class c = null;
try {
c = Class.forName("try1.ManDemo");
c.getName();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
return c;
}
方式四.通过类装载器 ClassLoader获取
public Class getClassMethod4(){
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class c = null;
try{
c = loader.loadClass("try1.ManDemo");
}catch (Exception e){
e.printStackTrace();
}
return c;
}
其中方式三灵活,是一般进行反射操作的首要选择。
2.如何获取构造方法
/**
* 获取构造方法
**/
public void getConstructors(){
Class c = getClassMethod3();
//获取所有构造方法
System.out.println("----------获取所有public构造方法-----------");
Constructor[] constructors = c.getConstructors();
for (Constructor cc:constructors) {
System.out.println(cc);
}
System.out.println("----------获取所有声明过的构造方法-----------");
Constructor[] constructors2 = c.getDeclaredConstructors();
for (Constructor cc:constructors2) {
System.out.println(cc);
}
try {
System.out.println("----------获取类中指定参数类型的public构造方法-----------");
System.out.println( c.getConstructor(String.class,Integer.class));
System.out.println( c.getConstructor(Integer.class,String.class));
System.out.println( c.getConstructor());
System.out.println("----------获取类中指定参数类型的所有构造方法-----------");
System.out.println( c.getDeclaredConstructor(String.class));
System.out.println( c.getDeclaredConstructor(Integer.class,String.class));
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
}
1.class.getConstructors():获取类中所有public构造方法
2.class.getDeclaredConstructors():获取类中所有声明过的构造方法
3.class.getConstructor(Class<?>… parameterTypes):获取类中指定参数类型的public构造方法
4.class.getDeclaredConstructor(Class<?>… parameterTypes):获取类中指定参数类型的所有构造方法
3.获取类中属性
/**
* 获取类中属性
**/
public void getFields(){
Class c = getClassMethod3();
System.out.println("----------1.获取所有共有字段------------");
Field[] fields = c.getFields();
for (Field f: fields) {
System.out.println(f);
}
System.out.println("----------2.获取所有声明过的字段------------");
Field[] fields1 = c.getDeclaredFields();
for (Field f: fields1) {
System.out.println(f);
}
System.out.println("----------3.获取共有字段并使用-----------");
try {
//获得指定的共有字段
Field field = c.getField("sex");
//获取一个公有构造方法,并实例化
Object obj = c.getConstructor().newInstance();
//为属性设置值
field.set(obj,true);
ManDemo man = (ManDemo)obj;
System.out.println(man.sex);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("----------4.获取私有字段并使用-----------");
try {
Field nameField = c.getDeclaredField("name");
Object obj2 = c.getConstructor().newInstance();
//设置暴力反射 允许修改私有字段 否则修改私有字段会产生异常
nameField.setAccessible(true);
nameField.set(obj2,"王舞");
ManDemo man = (ManDemo)obj2;
System.out.println(man.getName());
} catch (Exception e) {
e.printStackTrace();
}
}
1.class.getFields() :获取所有public字段
2.class.getDeclaredFields() :获取所有声明过的字段
3.class.getField(String name) :获取指定名字的public字段
4.class.getDeclaredField(String name) :获取私有字段并使用
获取字段后使用,方法见上文的实例代码
4.获取类中方法
/**
* 获取类中方法
**/
public void geMethods(){
Class c = getClassMethod3();
System.out.println("----------1.获取所有共有方法------------");
Method[] methods = c.getMethods();
for (Method m:methods) {
System.out.println(m);
}
System.out.println("----------2.获取所有方法------------");
Method[] methods1 = c.getDeclaredMethods();
for (Method m:methods1) {
System.out.println(m);
}
try {
Object obj = c.getConstructor().newInstance();
System.out.println("----------3.获取特定的方法并使用(不带参)------------");
Method m = c.getMethod("sleep");
Method m0 = c.getMethod("sleep",Integer.class); //带参
m.invoke(obj);
System.out.println("----------4.获取特定的方法并使用(不带参、私有)------------");
Method m1 = c.getDeclaredMethod("think");
//设置暴力反射 允许修改私有字段 否则调用私有方法会产生异常
m1.setAccessible(true);
m1.invoke(obj);
System.out.println("----------5.获取特定的方法并使用(带参)------------");
Method m2 = c.getDeclaredMethod("eat1",String.class);
m2.invoke(obj,"杨梅");
c.getDeclaredMethod("drunk",String.class,Integer.class).invoke(obj,"橙汁",3);
} catch (Exception e) {
e.printStackTrace();
}
}
1.class.getMethods():获取类中所有public方法
2.class.getDeclaredMethods():获取类中所有方法
3.class.getMethod(String name, Class<?>… parameterTypes):获取特定的public方法并使用(只传name代表方法不带参)
4.class.getDeclaredMethod(String name, Class<?>… parameterTypes):获取特定的方法并使用(只传name代表方法不带参)