反射
反射相关API
- java.lang.Class:类
- java.lang.reflect.Method:方法
- java.lang.reflect.Field:成员变量
- java.lang.reflect.Constructor:构造方法
首先创建Person类用来测试反射
public class Person extends Animal implements Move, Study {
private String msg;
public int age;
public Person(){
System.out.println("这是一个公共无参构造方法");
}
public Person(String msg){
this.msg = msg;
System.out.println("这是一个公共带参构造方法");
}
private Person(String msg, int age){
this.msg = msg;
this.age = age;
System.out.println("这是一个私有带参构造方法");
}
public void showMsg(){
System.out.println("这是一个公共无参方法");
}
public void showMy(String str, int i){
System.out.println("这是一个公共有参方法");
}
private void show(String str){
System.out.println("这是一个私有有参方法");
}
@Override
public void toMove() {
System.out.println("Move接口的toMove方法");
}
@Override
public void studyMath() {
System.out.println("Study接口的studyMath方法");
}
}
Animal.java
public class Animal {
public void run(){
System.out.println("这是Animal类的run方法");
}
}
Study.java
public interface Study {
void studyMath();
}
Move.java
public interface Move {
void toMove();
}
Class 类
- 对于每一个类而言JRE都为其保留了一个不变的Class类型的对象,一个Class对象包含了指定莫各类的所有有关信息。
- Class本身也是一个类
- Class对象只能由系统建立对象
- 一个类在JVM中只能有一个Class实例
- 一个Class对象对应的是一个加载到JVM中的.class文件
- 每个类的实例优惠记得自己是由哪个Class实例生成的
- 通过Class可以完整的得到一个类中的完整结构
使用getClass方法获取类
Person p = new Person();
//使用getClass获取到的对象中包含了Person累的所有信息
System.out.println(p.getClass());
运行结果
Class类中的常用方法
方法名 | 描述 |
---|---|
forName(String name) | 根据类的全类名(包名+类名)获取Class对象 |
newInstance() | 创建目标类对象 |
getName() | 获取全类名 |
getSuperclass() | 获取父类的Class对象 |
getInterfoces() | 获取所有实现的接口 |
getClassLoader() | 获取类的类加载器 |
getConstructors() | 获取所有构造器 |
getDeclaredFields() | 获取所有的属性 |
getMethods() | 获取对应的方法 |
实例化Class类对象
已知具体的类,通过类的class属性获取,该方法最安全可靠,程序性能最高
Class c = Person.class;
已知某个类的实例,调用该实例的getClass方法获取
Class c = person.getClass();
已知一个类的全类名,且该类在类路径下,可通过Class类的静态方法forName获取,可能抛出ClassNotFoundException
Class c = Class.forName("com.java.test.reflect.Person");
使用类加载器获取,需知类的全类名
ClassLoader cl = this.getClass().getClassLoader();
Class c = cl.loadClass("com.java.test.reflect.Person");
获取指定类的父类
示例代码
try {
Class c = Class.forName("com.java.test.reflect.Person");
Class sc = c.getSuperclass();
System.out.println(sc.getName());
} catch (Exception e) {
e.printStackTrace();
}
运行结果
获取指定类的接口类
示例代码
Class c = Class.forName("com.java.test.reflect.Person");
Class[] cs = c.getInterfaces();
for (Class clazz : cs){
System.out.println(clazz.getName());
}
运行结果
获取指定类的构造方法
获取公共构造方法
Class c = Class.forName("com.java.test.reflect.Person");
Constructor[] constructors = c.getConstructors();
for (Constructor constructor:constructors){
//获取方法名
System.out.println(constructor.getName());
//获取权限修饰符,1为public,2为private
System.out.println(constructor.getModifiers());
//获取参数的Class
Class[] parameterTypes = constructor.getParameterTypes();
for (Class clazz :parameterTypes){
System.out.println(clazz.getName());
}
System.out.println("-----------------");
}
运行结果
获取所有构造方法
Constructor[] constructors = c.getDeclaredConstructors();
运行结果
使用反射创建对象
使用class创建
Object obj = c.newInstance();
- 此方法在jdk9中被弃用
- 使用以下方法代替
无参构造方法调用
Class c = Class.forName("com.java.test.reflect.Person");
Person p = (Person) c.getConstructor().newInstance();
p.run();
运行结果
有参构造方法调用
Class c = Class.forName("com.java.test.reflect.Person");
Person p = (Person)
c.getConstructor(String.class).newInstance("test");
p.run();
运行结果
破除封装调用私有构造方法
Class c = Class.forName("com.java.test.reflect.Person");
Constructor constructor = c.getDeclaredConstructor(String.class, int.class);
//解除封装
constructor.setAccessible(true);
Person p = (Person) constructor.newInstance("test", 11);
p.run();
运行结果
反射获取类的方法
获取公有方法
public Method[] getMethods()
获取所有方法
public Method[] getDeclaredMethods()
Method类的方法
//取得返回值
public Class<?> getReturnType()
//取得所有参数
public Class<?>[] getParameterTypes()
//取得修饰符
public int getModifiers
示例代码
Class c = Class.forName("com.java.test.reflect.Person");
Method[] methods = c.getDeclaredMethods();
for (Method m : methods){
System.out.println("方法名:"+m.getName());
System.out.println("修饰符:"+m.getModifiers());
System.out.println("返回类型:"+m.getReturnType());
Class[] paraClass = m.getParameterTypes();
for (Class pc : paraClass){
System.out.println("参数类型:"+pc.getName());
}
System.out.println("-------------------");
}
运行结果
方法名:showMsg
修饰符:1
返回类型:void
-------------------
方法名:showMy
修饰符:1
返回类型:void
参数类型:java.lang.String
参数类型:int
-------------------
方法名:studyMath
修饰符:1
返回类型:void
-------------------
方法名:show
修饰符:2
返回类型:void
参数类型:java.lang.String
-------------------
方法名:toMove
修饰符:1
返回类型:void
-------------------
通过反射获取类的属性和包
获取公共Field
public Field[] getFields();
获取所有Field
public Field[] getDeclaredFields();
Field类的方法
//以整数形式返回Field的修饰符
public int getModifiers();
//得到Field的属性类型
public Class<?> getType();
//返回Field的名称
public String getName();
示例代码
Class c = Class.forName("com.java.test.reflect.Person");
Field[] fields = c.getDeclaredFields();
for (Field f : fields){
System.out.println(f.getName());
System.out.println(f.getModifiers());
System.out.println(f.getType().getName());
System.out.println("-----------------");
}
运行结果
msg
2
java.lang.String
-----------------
age
1
int
-----------------
反射调用指定方法
调用方法示例
Class c = Class.forName("com.java.test.reflect.Person");
//获取构造方法
Constructor constructor = c.getConstructor();
//使用构造方法创建对象
Object obj = constructor.newInstance();
/**
* 获取指定方法
* string:方法名
* 参数类型
*/
Method method = c.getMethod("showMy", String.class, int.class);
/**
* 运行方法
* obj:创建的指定类的对象
* 传入方法的参数
*/
method.invoke(obj, "test", 1);
运行结果
这是一个公共无参构造方法
这是一个公共有参方法
Process finished with exit code 0
调用私有方法
method.setAccessible(true);//解除私有封装
反射获取修改类的属性
示例代码
Class c = Class.forName("com.java.test.reflect.Person");
Constructor constructor = c.getConstructor();
Object obj = constructor.newInstance();
Field field = c.getField("age");
field.set(obj, 10);
System.out.println(field.get(obj));
运行结果
这是一个公共无参构造方法
10
Process finished with exit code 0
调用私有属性
field.setAccessible(true);//解除私有封装