起初对反射的理解是毫无概念,回看《Java核心技术》,书中明确指出了反射的各种用法以及使用事项。
先上两个代码:
public class Person {
public String name ;
//定义一个私有属性
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +"name='" + name + '\'' +", age=" + age +
'}';
}
public Person() {
}
public Person(String name,int age) {
this.name = name;
this.age =age;
}
//定义一个私有构造
private Person(String name) {
this.name = name;
}
public void eat(){
System.out.println("rice");
}
//定义私有方法
private String study(String str){
System.out.println("I am reading "+ str);
return str;
}
}
使用反射的运用;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Reflection {
@Test
public void test1(){
Person p1 = new Person("Mousn",24);
p1.name = "Emousn";
p1.setAge(22);
System.out.println(p1.toString());
p1.eat();
}
@Test
public void test2() throws Exception {
Class clazz = Person.class;
Constructor constructor = clazz.getConstructor(String.class, int.class);
Object obj = constructor.newInstance("Tom", 24);
Person p2 = (Person) obj;
System.out.println(p2);
// 调用属性
Field name = clazz.getDeclaredField("name");
name.set(p2,"Tomer");
System.out.println(p2);
// 调用方法
Method method = clazz.getDeclaredMethod("eat");
method.invoke(p2);
// 调用私有构造
Constructor constructor1 = clazz.getDeclaredConstructor(String.class);
// 开启限制
constructor1.setAccessible(true);
Object obj1 = constructor1.newInstance("Jerry");
Person p3 = (Person) obj1;
System.out.println(p3);
// 调用私有属性
Field age = clazz.getDeclaredField("age");
age.setAccessible(true);
age.set(p3,12);
System.out.println(p3);
// 获取所有属性、修饰符
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
int modifiers = field.getModifiers();
if( Modifier.isPrivate(modifiers)) {
System.out.println(field + " private");
}else if(Modifier.isPublic(modifiers)){
System.out.println(field + " public");
}else if(Modifier.isProtected(modifiers)){
System.out.println(field + " Protected");
}else {
System.out.println(field + " final");
}
}
// 调用私有方法
Method study = clazz.getDeclaredMethod("study", String.class);
study.setAccessible(true);
String st = (String)study.invoke(p3, "book");
System.out.println(st);
// 获取所有的方法
Method[] methods = clazz.getDeclaredMethods();
for (Method method1 : methods) {
System.out.println(method1.toString());
}
}
// 思考: 反射机制与面向对象中的封装性有冲突?怎么看待这两种技术?
}
输出结果
Person{name='Tom', age=24}
Person{name='Tomer', age=24}
rice
Person{name='Jerry', age=0}
Person{name='Jerry', age=12}
public java.lang.String com.example.demo.Person.name public
private int com.example.demo.Person.age private
I am reading book
book
public java.lang.String com.example.demo.Person.toString()
public java.lang.String com.example.demo.Person.getName()
public void com.example.demo.Person.setName(java.lang.String)
public void com.example.demo.Person.setAge(int)
public void com.example.demo.Person.eat()
private java.lang.String com.example.demo.Person.study(java.lang.String)
public int com.example.demo.Person.getAge()
那些类可以有Class对象? 外部类,内部类(成员内部类、静态内部类)、局部内部类、匿名内部类 接口、数组、枚举类、void类、注解类、基本数据类型 获得Class实例的四种方式:
// 获取Class实例的方式
/**
Class的实例对应一个运行时类;
运行时类会在内存中停留,此时Class会拥有地址值,通过不同方式获得的Class实例的地址值一样(同一个运行时类)
*/
@Test
public void test3() throws Exception {
// 方式一:调用运行时属性.class
Class<Person> personClass1 = Person.class;
// 方式二:通过运行时类的对象
Person person = new Person();
Class personClass2 = person.getClass();
// 方式三:调用Class的静态方法 :forName(String classpath) (常用)
Class personClass3 = Class.forName("com.example.demo.Person");
// 方式四:使用类的加载器ClassLoader
ClassLoader classLoader = Reflection.class.getClassLoader();
Class personClass4 = classLoader.loadClass("com.example.demo.Person");
Class personClass4 = classLoader.loadClass("com.example.demo.Person");
System.out.println(personClass1);//class com.example.demo.Person
System.out.println(personClass2);//class com.example.demo.Person
System.out.println(personClass3);//class com.example.demo.Person
System.out.println(personClass4);//class com.example.demo.Person
}
检查类的结构:
