一、简介
Java反射就是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;并且能改变它的属性。
Java 是一门面向对象的语言。每一个类都可以看成一个对象,是 java.lang.Class 类的对象。
二、Class类
Class是一个类,封装了当前对象所对应的类的信息。对于每个类而言,JRE 都为其保留一个不变的 Class 类型的对象。
获取Class对象的三种方式:
1、第一种方式 getClass()
Test test = new Test();
Class ts = test.getClass();
2、第二种方式 .class
Class ts = Test.class;
3、第三种方式 通过类的全名获取
try{
Class ts = Class.forName("com.cpf.Test");
System.out.println(ts.getName());
}catch(Exception e){
}
Class ts = Test.class;
开发过程中一般选中第三种方式。
三、方法介绍
//获得类的完整名字。
getName():
//获得类的public类型的属性。包括父类中的字段。
getFields():
//获得类的所有属性。包括public、private和proteced。 但是不包括父类的申明字段。
getDeclaredFields():
所有公用(public)方法包括其从父类继承的公用方法,当然也包括它所实现接口的方法。
getMethods():
//获得类的所有方法。包括public、private、proteced和接口实现的方法,但不包括父类继承的方法
getDeclaredMethods():
//获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
getMethod(String name, Class[] parameterTypes):
//获得类的public类型的构造方法。包括父类中的构造方法。
getConstructors():
//获得类的所有构造方法,包括public、private、proteced。但不包括父类继承的方法。
getDeclaredConstructors():
//获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
getConstructor(Class[] parameterTypes):
//通过类的不带参数的构造方法创建这个类的一个对象。
Object newInstance():
//返回类加载器
ClassLoader getClassLoader():
//返回当前Class对象的接口
Class<?>[] getInterfaces()
四、通过反射获取类的构造方法、方法以及属性
1、获取构造方法
//加载Class对象
Class clazz = Class.forName(”com.cpf.Test”);
//获取所有公有构造方法
System.out.println(”**********************所有公有构造方法*********************************”);
Constructor[] conArray = clazz.getConstructors();
//获取所有构造方法
System.out.println(”************所有的构造方法(包括:私有、受保护、默认、公有)***************”);
conArray = clazz.getDeclaredConstructors();
//获取单个无参公有构造方法
System.out.println(”*****************获取公有、无参的构造方法*******************************”);
Constructor con = clazz.getConstructor(null); //因为是无参的构造方法所以类型是一个null,不写也可以
//获取单个有参构造方法
System.out.println(”******************获取带参的私有构造方法*******************************”);
con = clazz.getDeclaredConstructor(String.class);
2、创建实例对象
创建实例对象有两种方式
<1> 直接使用Class.newInstance()
//加载Class对象
Class clazz = Class.forName(”com.cpf.Test”);
//创建实例对象
Object obj = clazz.newInstance();
这种方式只适用于类中包含有公有的无参构造方法
<2> 使用构造方法的newInstance()
//加载Class对象
Class clazz = Class.forName(”com.cpf.Test”);
//调用单个有参私有构造方法
Constructor con = clazz.getDeclaredConstructor(String.class);
//如果构造方法是私有的,那么就需要设置setAccessible方法true
con.setAccessible(true);//暴力访问(忽略掉访问修饰符)
//创建实例对象
Object obj = con.newInstance(’男’);
这种方式既可以用于私有也可以用于公有构造方法,同样的可以用于有参,也可以用于无参
3、获取成员变量并调用
//加载Class对象
Class clazz = Class.forName(”com.cpf.Test”);
//创建实例对象
Object obj = clazz.newInstance();
<1> getFields() 获取所有公有属性(包括接口实现和父类继承的)
Field[] fields = clzz.getFields();
//赋值
field.set(obj,"Apple");
//取值
field.get(obj);
<2> getField("") 根据变量名获取公有的属性(包括接口实现和父类继承的)
Field field = clzz.getField("age");
field.set(obj,"12");
System.out.println(field.get(obj));
<3> getDeclaredFields() 获取所有变量public、private、proteced(包括接口实现,但不包括父类继承的)
Field[] fields = clzz.getDeclaredFields();
for(Field field : fields){
//输出所有的属性名
System.out.println(field.getName());
}
<4> getDeclaredField("")根据变量名获取属性
Field field = clzz.getDeclaredField("email");
//如果属性是private的,就必须加
field.setAccessible(true);
field.set(obj,"12");
System.out.println(field.get(obj));
3、获取方法并调用
//加载Class对象
Class clazz = Class.forName(”com.cpf.Test”);
//创建实例对象
Object obj = clazz.newInstance();
<1> getMethods() 获取所有公有方法(包括接口实现和父类继承的)
Method[] methods = clzz.getMethods();
for(Method method : methods){
//方法名
System.out.println("name==" + method.getName());
//返回值类型
System.out.println("retrunType==" + method.getReturnType());
}
<2> getMethod("") 根据方法名获取公有的方法(包括接口实现和父类继承的)
//有参
Method method = clzz.getMethod("getAge",String.class);
method.invoke(obj, "Apple");
//无参
Method method1 = clzz.getMethod("getAge");
String age = (String)method1.invoke(obj);
System.out.println(age);
<3> getDeclaredMethods() 获取所有方法public、private、proteced包括接口实现,但不包括父类继承的)
Method[] methods = clzz.getDeclaredMethods();
for(Method method : methods){
System.out.println("name==" + method.getName());
System.out.println("retrunType==" + method.getReturnType());
}
<4> getDeclaredMethod("")根据方法名获取方法
//获取私有有参方法
Method method = clzz.getDeclaredMethod("getName",String.class);
//调用私有方法必须要设置
method.setAccessible(true);
//调用私有有参方法
method.invoke(obj, "Apple");
//获取私有无参方法
Method method1 = clzz.getDeclaredMethod("getName");
method1.setAccessible(true);
String age = (String)method1.invoke(obj);
System.out.println(age);
//获取公有有参方法
Method method2 = clzz.getDeclaredMethod("getAge",String.class);
//调用方法
method2.invoke(obj, "Apple");
在动态代理实现原理中就可以看到反射的使用。