曾经碰到一件怪事:Spring可以把构造函数为私有的对象实例也给创建出来,当时没去研究为何。直到今天突然想起,查了一下,找到此文:[url]http://yh-private.iteye.com/blog/183345[/url] ,于是给转了过来,javaeye没有直接转载的功能,真有些不方便啊。
1.私有构造函数的调用:
主要的类:java.lang.reflect.Constructor
首先要拿到构造方法,具体如下:
Class clazz = Class.forName("Bean");
Constructor[] cons = clazz.getDeclaredConstructors();
这样拿到的cons数组保存着所有的这个类的构造函数,包括私有的和公有的。
迭代并调用con.toGenericString()可以拿到每个构造方法的全限定名(带修饰符,带参数)。
如果要拿单个构造方法,可以调用getDeclaredConstructor(Class args);来拿,只要参数匹配了就可以得到,如果没有参数,则传null即可。
然后需要调用Constructor的方法setAccessible设置为true,表示允许使用私有构造函数。这个方法是父类 AccessibleObject的方法,这个类的自类有Constructor, Field, Method分别代表构造函数,成员变量,和成员方法。也就是说使用这个方法,可以访问类的所有的方法、变量、构造函数。
最后,使用Constructor的newInstance方法就可以把对象创建出来了:
Bean bean = (Bean)con.newInstance(Object args);
没有参数的构造函数可以传null进去。
2.调用私有的方法:
主要的类:java.lang.reflect.Method
首先还是要拿到那个私有的方法,可以调用
Method[] ms = clazz.getDeclaredMethods();来拿到所有的方法的集合。
也可以拿某个单独的方法:getDeclaredMethod(String name, Class... parameterTypes)匹配名字和参数的方法会被拿到,方法若没有参数传null.
同样可以调用toGenericString()看全限定名。
然后同样需要调用setAccessible(true)来设置可以方法私有方法。
最后,就可以使用method.invoke(bean, Object args);来调用这个方法。两个参数分别是对象,和这个方法的参数。
3.调用私有成员变量,也叫字段。
主要类:java.lang.reflect.Field
首先还是要拿到要使用的字段:
还是两种,拿全部:Field[] fs = clazz.getDeclaredFields();
拿某个:clazz.getDeclaredField(String fieldName);
老步骤:setAccessible(true)
最后, f.get(obj) ,就能拿到传入对象的私有变量。
1.私有构造函数的调用:
主要的类:java.lang.reflect.Constructor
首先要拿到构造方法,具体如下:
Class clazz = Class.forName("Bean");
Constructor[] cons = clazz.getDeclaredConstructors();
这样拿到的cons数组保存着所有的这个类的构造函数,包括私有的和公有的。
迭代并调用con.toGenericString()可以拿到每个构造方法的全限定名(带修饰符,带参数)。
如果要拿单个构造方法,可以调用getDeclaredConstructor(Class args);来拿,只要参数匹配了就可以得到,如果没有参数,则传null即可。
然后需要调用Constructor的方法setAccessible设置为true,表示允许使用私有构造函数。这个方法是父类 AccessibleObject的方法,这个类的自类有Constructor, Field, Method分别代表构造函数,成员变量,和成员方法。也就是说使用这个方法,可以访问类的所有的方法、变量、构造函数。
最后,使用Constructor的newInstance方法就可以把对象创建出来了:
Bean bean = (Bean)con.newInstance(Object args);
没有参数的构造函数可以传null进去。
2.调用私有的方法:
主要的类:java.lang.reflect.Method
首先还是要拿到那个私有的方法,可以调用
Method[] ms = clazz.getDeclaredMethods();来拿到所有的方法的集合。
也可以拿某个单独的方法:getDeclaredMethod(String name, Class... parameterTypes)匹配名字和参数的方法会被拿到,方法若没有参数传null.
同样可以调用toGenericString()看全限定名。
然后同样需要调用setAccessible(true)来设置可以方法私有方法。
最后,就可以使用method.invoke(bean, Object args);来调用这个方法。两个参数分别是对象,和这个方法的参数。
3.调用私有成员变量,也叫字段。
主要类:java.lang.reflect.Field
首先还是要拿到要使用的字段:
还是两种,拿全部:Field[] fs = clazz.getDeclaredFields();
拿某个:clazz.getDeclaredField(String fieldName);
老步骤:setAccessible(true)
最后, f.get(obj) ,就能拿到传入对象的私有变量。
MyBean.java :
package cn.yzj.entities;
public class MyBean
{
private String name;
private Integer age;
private MyBean()
{
this.name ="ABC";
}
private MyBean(String name,Integer age)
{
this.name = name;
this.age = age;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
private void printName()
{
System.out.println(this.name);
}
}
package cn.yzj;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import cn.yzj.entities.MyBean;
public class Test1
{
public static void main(String[] args) throws ClassNotFoundException,
IllegalArgumentException, InstantiationException,
IllegalAccessException, InvocationTargetException,
SecurityException, NoSuchMethodException
{
Class clazz = Class.forName("cn.yzj.entities.MyBean");
// 获得私有成员变量并返回.
// getField(clazz);
// 调用私有方法
// getMethod(clazz);
// 用私有构造方法构造对象并返回.
// getConstrutor(clazz);
}
//用私有构造方法构建实例的方法
private static MyBean getConstrutor(Class clazz)
throws NoSuchMethodException, InstantiationException,
IllegalAccessException, InvocationTargetException
{
// 拿所有的构造方法.
/*
* Constructor[] cons = clazz.getDeclaredConstructors(); for(Constructor
* con : cons) { System.out.println(con.toGenericString()); }
*/
// 1.拿无参数的构造方法.
Constructor con = clazz.getDeclaredConstructor(null);
// 2.设置可以访问.
con.setAccessible(true);
// 3.创建实例
MyBean myBean = (MyBean) con.newInstance(null);
return myBean;
}
private static Object getField(Class clazz) throws NoSuchMethodException,
InstantiationException, IllegalAccessException,
InvocationTargetException
{
MyBean myBean = getConstrutor(clazz);
Field[] fs = clazz.getDeclaredFields();
for (Field f : fs)
{
System.out.println(f.toGenericString());
}
fs[0].setAccessible(true);
return fs[0].get(myBean);
}
private static void getMethod(Class clazz) throws NoSuchMethodException,
InstantiationException, IllegalAccessException,
InvocationTargetException
{
MyBean myBean = getConstrutor(clazz);
Method[] ms = clazz.getDeclaredMethods();
for (Method m : ms)
{
System.out.println(m.toGenericString());
}
ms[0].setAccessible(true);
ms[0].invoke(myBean, null);
}
}