小贾漫谈——Java反射
一、Class的API
二、测试使用的JavaBean
class Admin{ //字段 public String userName; public String pwd; private int age; //构造方法 public Admin(){ System.out.println("无参构造器啦。。。。。"); } public Admin(String userName,String pwd){ System.out.println("我的用户名:"+userName+" 密码:"+pwd); } private Admin(int age){ System.out.println("我的保密年龄:"+age); } //方法 private void setAge(int age){ this.age=age; } public int getAge(int age){ return age; } }
三、测试
1、获取构造器并创建实例
通过getConstructors()方法获取所有的public构造器
@Test //获取所有public的构造器 public void getAllPublicConstrutor() { //1、先找到被调用构造器所在类的字节码 Class clazz=Admin.class; //2、获取所有的public构造器 Constructor[] cons=clazz.getConstructors(); for (Constructor constructor : cons) { System.out.println(constructor); } }
/** * 测试结果: * public Admin() public Admin(java.lang.String,java.lang.String) */
通过getDeclaredConstructors()获取所有的构造器
@Test //通过getDeclaredConstructors()获取所有的构造器 public void getAllConstrutor(){ Class clazz=Admin.class; Constructor[] cons=clazz.getDeclaredConstructors(); for (Constructor constructor : cons) { System.out.println(constructor); } } /** * 测试结果: * public Admin() public Admin(java.lang.String,java.lang.String) private Admin(int) */
获取指定的public构造器,并创建实例
@Test //获取指定的public构造器,并创建实例 public void ConstructorPublicInvoke() throws Exception{ //1、先找到被调用构造器所在类的字节码 Class clazz=Admin.class; //2、找到被调用指定的构造器,传入构造器参数的字节码 Constructor construtor=clazz.getConstructor(String.class,String.class); //3、执行构造器 创建对象 construtor.newInstance("Jack","123456"); } /** * 测试结果: * 我的用户名:Jack 密码:123456 */
获取指定的private构造器,并创建实例
@Test //获取指定的private构造器,并创建实例 public void ConstructorInvoke() throws Exception { //1、先找到被调用构造器所在类的字节码 Class clazz=Admin.class; //2、找到被调用指定的构造器,传入构造器参数的字节码 Constructor construtor=clazz.getDeclaredConstructor(int.class); //3、在调用构造器之前,设置改构造器可以被访问 construtor.setAccessible(true); //4、执行构造器 创建对象 construtor.newInstance(13); } /** * 测试结果: * 我的保密年龄:13 */
2、获取方法并调用方法
获取所有的public方法,以及父类的方法
@Test //获取所有的public方法,以及父类的方法 public void getPublicMethod(){ Class clazz=Admin.class; Method[] methods=clazz.getMethods(); for (Method method : methods) { System.out.println(method); } } /** 测试结果: * public int Admin.getAge(int) public final void java.lang.Object.wait() throws java.lang.InterruptedException public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException public native int java.lang.Object.hashCode() public final native java.lang.Class java.lang.Object.getClass() public boolean java.lang.Object.equals(java.lang.Object) public java.lang.String java.lang.Object.toString() public final native void java.lang.Object.notify() public final native void java.lang.Object.notifyAll() */
获取所有的方法,不包括父类的。
@Test //获取所有的方法,不包括父类的。 public void getAllMethod(){ Class clazz=Admin.class; Method[] methods=clazz.getDeclaredMethods(); for (Method method : methods) { System.out.println(method); } } /** * 测试结果: * private void Admin.setAge(int) public int Admin.getAge(int) */
调用public方法,并执行
@Test //调用public方法,并执行 public void getPublicMethodInvoke() throws Exception{ //1、先找到被调用构造器所在类的字节码 Class clazz=Admin.class; //2、根据方法名,获取方法 Method method=clazz.getMethod("getAge", int.class); //3、调用方法 method.invoke(clazz.newInstance(), 23); } /** * 测试结果: * 无参构造器啦。。。。。 public方法===我的年龄是23 * */
调用私有方法并执行
@Test //调用私有方法并执行 public void getMethodInvoke() throws Exception{ //1、先找到被调用构造器所在类的字节码 Class clazz=Admin.class; //2、根据方法名,获取方法 Method method=clazz.getDeclaredMethod("setAge", int.class); //3、设置私有方法为可调用 method.setAccessible(true); //4、调用方法 method.invoke(clazz.newInstance(), 23); } /** * 测试结果: * 无参构造器啦。。。。。 私有方法====我的年龄是23 */
3、设置字段和获取字段
设置和获取public的字段
@Test //获取public的字段 public void setGetPublicFileds() throws Exception{ //1、先找到被调用构造器所在类的字节码 Class clazz=Admin.class; //2、根据字段名获取字段 Field field=clazz.getField("userName"); //3、创建实例 Admin admin=(Admin) clazz.newInstance(); //4、设置值 field.set(admin, "Jack"); String userName= (String) field.get(admin); System.out.println(userName); } /** * 测试结果: * 无参构造器啦。。。。。 Jack */
设置和获取
@Test //设置和获取private字段 public void setGetFileds() throws Exception{ //1、先找到被调用构造器所在类的字节码 Class clazz=Admin.class; //2、根据字段名获取字段 Field field=clazz.getDeclaredField("age"); //3、创建实例 Admin admin=(Admin) clazz.newInstance(); //4、设置字段为可见 field.setAccessible(true); //5、设置值 field.set(admin, 15); //6、获取值 Integer age= (Integer) field.get(admin); System.out.println(age); } /** * 测试结果: * 无参构造器啦。。。。。 15 */
4、获取参数泛型信息
import java.lang.reflect.Field; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Map; class Gene{ public Map<String,Object> map; } public class GenericType { public static void main(String[] args) throws Exception { Class clazz=Gene.class; Field field=clazz.getField("map"); //获取带泛型的类型 Type type=field.getGenericType(); System.out.println(type); //java.util.Map<java.lang.String, java.lang.Object> ParameterizedType paraType=(ParameterizedType) type; Type[] types=paraType.getActualTypeArguments(); System.out.println(types[0]);//String System.out.println(types[1]);//Object /** * 输出结果: * class java.lang.String class java.lang.Object */ } }
1、java.lang.reflect.Type;
所有已知子接口:GenericArrayType, ParameterizedType, TypeVariable<D>, WildcardType
所有已经实现的类:Class
2、ParameterizedType 表示参数化类型,如 Collection<String>。
getActualTypeArguments():返回表示此类型实际类型参数的 Type 对象的数组。