反射
框架设计的灵魂
反射:将类的各个组成部分封装为其他对象,这就是反射机制
好处:1、可以在程序运行过程中,操作这些对象
2、可以解耦合,提高程序的可扩展性
大致意思:把一个类.class经过类加载器处理,把其中的成员变量,构造方法,成员方法,都存在一个数组中
形成一个Class类对象;
获取Class类的方式
1、Class.forName(“全类名”):将字节码文件加载进内存,返回Class对象
*多用于配置文件,将类名定义在配置文件中
2、类名.class:通过类名的属性class获取
*多用于参数的传递
3、对象.getClass:getClass()方法在Object类中定义着
*多用于对象获取字节码的方式
public class Persion {
private String name;
private int age;
public String a;
protected String b;
String c;
private String d;
public Persion(String name, int age) {
this.name = name;
this.age = age;
}
public Persion() {
}
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;
}
public void eat(){
System.out.println("吃的方法");
}
public void eat(String name){
System.out.println("吃了"+name);
}
@Override
public String toString() {
return "Persion{" +
"name='" + name + '\'' +
", age=" + age +
", a='" + a + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
", d='" + d + '\'' +
'}';
}
}
public class Mytest {
@Test
public void test01() throws ClassNotFoundException {
Class<?> aClass = Class.forName("com.zww.domain.Persion");
System.out.println(aClass);
Class<Persion> persionClass = Persion.class;
System.out.println(persionClass);
Persion persion = new Persion();
Class<? extends Persion> aClass1 = persion.getClass();
System.out.println(aClass1);
// 注意三个值最后运行出来的结果是一样的,*.class在一次程序运行过程中,只会被加载一次
}
}
使用Class对象功能
获取功能:
1、获取成员变量
Field getField(String name)
返回一个 Field对象,它反映此表示的类或接口的指定公共成员字段 类对象。
Field[] getFields()
返回包含一个数组 Field对象反射由此表示的类或接口的所有可访问的公共字段 类对象。
Field getDeclaredField(String name)
返回一个 Field对象,它反映此表示的类或接口的指定已声明字段 类对象。
Field[] getDeclaredFields()
返回的数组 Field对象反映此表示的类或接口声明的所有字段 类对象。
2、获取构造方法
Constructor<T> getConstructor(类<?>... parameterTypes)
返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的公共 类函数。
Constructor<?>[] getConstructors()
返回包含一个数组 Constructor对象反射由此表示的类的所有公共构造 类对象。
Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定 类函数。
Constructor<?>[] getDeclaredConstructors()
返回一个反映 Constructor对象表示的类声明的所有 Constructor对象的数组 类 。
3、获取成员方法
方法 getMethod(String name, 类<?>... parameterTypes)
返回一个 方法对象,它反映此表示的类或接口的指定公共成员方法 类对象。
方法[] getMethods()
返回包含一个数组 方法对象反射由此表示的类或接口的所有公共方法 类对象,包括那些由类或接口和那些从超类和超接口继承的声明。
方法 getDeclaredMethod(String name, 类<?>... parameterTypes)
返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 类对象。
方法[] getDeclaredMethods()
返回包含一个数组 方法对象反射的类或接口的所有声明的方法,通过此表示 类对象,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法。
4、获取类的名字
getName()
所有的测试类的情况
public class Mytest {
@Test
public void test01() throws ClassNotFoundException {
Class<?> aClass = Class.forName("com.zww.domain.Persion");
System.out.println(aClass);
Class<Persion> persionClass = Persion.class;
System.out.println(persionClass);
Persion persion = new Persion();
Class<? extends Persion> aClass1 = persion.getClass();
System.out.println(aClass1);
// 注意三个值最后运行出来的结果是一样的,*.class在一次程序运行过程中,只会被加载一次
}
/**
* 获取成员变量的
* @throws NoSuchFieldException
* @throws IllegalAccessException
*/
@Test
public void test02() throws NoSuchFieldException, IllegalAccessException {
// 0、获取person的Class对象
Class<Persion> persionClass = Persion.class;
// 1-获取成员变量
// 1-1: Field[] getFields() , 获取所有public修饰的
Field[] fields = persionClass.getFields();
for (Field field:fields ) {
System.out.println(field);
}
System.out.println("----------");
// 1-2: Field getField(String name)
// 获取成员变量之后,可以来进行get和set操作
Field a = persionClass.getField("a");
Persion p = new Persion();
// 设置a的值
a.set(p,"张三");
System.out.println(p); // 获取出来就是张三
System.out.println("----------");
// 1-3:Field getDeclaredField(String name)
Field declaredField = persionClass.getDeclaredField("d");
declaredField.setAccessible(true); // 暴力反射
System.out.println("这里是get处理p的="+declaredField.get(p));
// 1-4:Field[] getDeclaredFields() 获取所有的成员变量
Field[] declaredFields = persionClass.getDeclaredFields();
for (Field field1: declaredFields) {
System.out.println(field1);
}
}
/**
* 获取构造方法的测试类
*/
@Test
public void test03() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
// Constructor<T> getConstructor(类<?>... parameterTypes),构造方法用来创建对象的时候使用
Class<Persion> persionClass = Persion.class;
Constructor<Persion> constructor = persionClass.getConstructor(String.class, int.class);
System.out.println(constructor);
// 创建对象,采用使用构造器的方式
Persion persion = constructor.newInstance("张三", 12);
System.out.println(persion);
System.out.println("----------------------");
// 空参构造器演示
Constructor constructor1 = persionClass.getConstructor();
System.out.println("空参演示"+constructor1);
// Constructor<?>[] getConstructors()
// Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
// Constructor<?>[] getDeclaredConstructors()
}
/**
* 获取成员方法,也是分属性的
*/
@Test
public void test04() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
// 1-使用空参的方法
Class<Persion> persionClass = Persion.class;
// 获取指定的方法名
Method eat = persionClass.getMethod("eat");
Persion persion = new Persion();
// 执行方法
eat.invoke(persion);
// 2-有参数的方法
Method eat1 = persionClass.getMethod("eat", String.class);
eat1.invoke(persion, "苹果"); // 输出吃了苹果
// 3-获取所有的方法
Method[] methods = persionClass.getMethods();
for (Method method:methods){
System.out.println(method);
System.out.println(method.getName());
}
//获取类名
String name = persionClass.getName();
System.out.println("获取的类名"+name);
}
}