反射:框架的灵魂设计
框架: 半成品软件。可以在框架的基础上进行软件的开发,简化编码。
反射:将类的各个组成部分封装为其他对象,这就是反射机制。
好处:
1.在程序的运行过程中去操作这些对象。
2.可以解耦,提高程序的可扩展性。
获取Class类对象的三方式:
Source 源代码阶段
Class.forName(“全类名”) 包名+类名:将字节码文件加载进内存,返回Class对象。
* 多用于配置文件,将类名定义在配置文件中。读取文件,加载类
Class类对象阶段
类名.Class : 通过类名的属性class获取
* 多用于参数的传递
RunTime 运行是阶段
对象.getClass(): getClass()方法在Object 类中定义着
*多用于对象的一个获取字节码的方式
结论 :
同一个字节码文件(.class)在一次程序的运行中,只会被加载一次
无论通过哪一种方式获取Class对象,都是同一个对象。
使用Class对象功能:
*获取功能:
1.获取成员变量们
Field[] getFields() :获取所有Public修饰的成员变量
Field getField(String name) :获取指定名称的public修饰的成员变量树
Field getDeclaredField(String name):获取指定的成员变量 不考虑修饰符
Field[] getDeclaredFields() 获取所有的成员变量 不考虑修饰符
2.获取构造方法们
Constructor getConstructor(类... parameterTypes)
返回一个 Constructor对象,该对象反映 Constructor对象表示的类的指定的公共 类函数。
Constructor[] getConstructors()
返回包含一个数组 Constructor对象反射由此表示的类的所有公共构造 类对象
Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
返回一个 Constructor对象,该对象反映 Constructor对象表示的类或接口的指定 类函数。
Constructor<?>[] getDeclaredConstructors()
返回一个反映 Constructor对象表示的类声明的所有 Constructor对象的数组 类 。
3.获取成员方法们
Method getMethod(String name, 类<?>... parameterTypes)
返回一个 方法对象,它反映此表示的类或接口的指定公共成员方法 类对象。
Method [] getMethods()
Method getDeclaredMethod(String name, 类... parameterTypes)
返回一个 方法对象,它反映此表示的类或接口的指定声明的方法 类对象。
Method [] getDeclaredMethods()
返回包含一个数组 方法对象反射的类或接口的所有声明的方法,通过此表示 类对象,包括公共,保护,默认(包)访问和私有方法,但不包括继承的方法。
4. 获取类名
String getName()
Field:成员变量
*1.设置值
void set(Object obj,Object value)
*2.获取值
get(Object obj)
*3.访问私有 忽略访问权限修饰符的安全检查
dField.setAccessible(true);//暴力反射
Constructor
*创建对象
T newInstance(Object... initargs)
如果空参构造方法,可以简化操作 Class对象的newInstance 方法
Method 方法对象
执行对象
Object invoke(Object obj,Object....args)
获取方法名称:
String getName //获取方法名
案例:
需求:写一个“框架”,不能改变该类的任意代码前提下,帮助我们创建任意类的对象,并且执行其中任意的方法,
实现:
1. 配置文件
2. 反射
步骤:
1. 将需要创建对象的全类名和需要执行的方法定义在配置文件中
2. 在程序中加载读取配置文件
3. 使用发射技术来加载类文件进内存
4. 创建对象,
5. 执行方法
Person.java
package edgedo.pojo;
public class Person {
private String name;
private int age;
public String a;
public String a2;
protected String b;
String c;
private String d;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = 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;
}
public void eat(){
System.out.println("eat eat eat eat ");
}
public void eat(String food){
System.out.println("eat eat eat eat "+food);
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
", a='" + a + '\'' +
", a2='" + a2 + '\'' +
", b='" + b + '\'' +
", c='" + c + '\'' +
", d='" + d + '\'' +
'}';
}
}
ReflectDemo.java
package edgedo.reflect;
import edgedo.pojo.Person;
public class ReflectDemo {
/**
* 获取Class类的三种方式
* *获取Class类对象的三方式:
1.Source 源代码阶段
Class.forName(“全类名”) 包名+类名:将字节码文件加载进内存,返回Class对象。
2. Class类对象阶段
类名.Class : 通过类名的属性class获取
3. RunTime 运行是阶段
对象.getClass(): getClass()方法在Object 类中定义着
*/
public static void main(String[] args) throws Exception {
//Class.forName.
Class cls = Class.forName("com.edgedo.pojo.Person");
System.out.println(cls);
//2.类名.Class
Class cls2 = Person.class;
System.out.println(cls2);
//3.对象通过getClass()
Person p = new Person();
Class cls3 = p.getClass();
System.out.println(cls3);
//==比较两个对象
System.out.println(cls==cls2);//true
System.out.println(cls==cls3);//true
System.out.println(cls2==cls3);//true
}
}
ReflectDemo2
package edgedo.reflect;
import edgedo.pojo.Person;
import java.lang.reflect.Field;
public class ReflectDemo2 {
/*1.获取成员变量们
Field[] getFields()
Field getField(String name)
Field getDeclaredField(String name)
Field[] getDeclaredFields()
*/
public static void main(String[] args) throws Exception {
//1.获取Person的Class对象
Class<Person> personClass = Person.class;
//Field[] getFields()
Field[] fields = personClass.getFields();
for(Field field:fields){
System.out.println(field);
}
System.out.println("111");
System.out.println("------");
// Field getField(String name)
Field a = personClass.getField("a");
// System.out.println(a);
//获取成员变量a的值
Person p = new Person();
a.set(p,"哈哈哈");//给哪一个对象传递什么数值
Object value = a.get(p);
System.out.println(value);
// Field[] getDeclaredFields() 获取所有的成员变量不考虑修饰符
Field[] declFiields = personClass.getDeclaredFields();
for(Field field:declFiields){
System.out.println(field);
}
// Field getDeclaredField(String name)
Field dField = personClass.getDeclaredField("d");
//访问私有 忽略访问权限修饰符的安全检查
dField.setAccessible(true);//暴力反射
Object dValue = dField.get(p);
System.out.println(dValue);
}
}
ReflectDemo3
package edgedo.reflect;
import edgedo.pojo.Person;
import java.lang.reflect.Constructor;
public class ReflectDemo3 {
/*
2.获取构造方法们
Constructor getConstructor(类... parameterTypes)
Constructor[] getConstructors()
Constructor<T> getDeclaredConstructor(类<?>... parameterTypes)
Constructor<?>[] getDeclaredConstructors()
3.获取成员方法们
Method getMethod(String name, 类<?>... parameterTypes)
Method [] getMethods()
Method getDeclaredMethod(String name, 类... parameterTypes)
Method [] getDeclaredMethods()
*/
public static void main(String[] args) throws Exception {
//1.获取Person的Class对象
Class<Person> personClass = Person.class;
//构造方法
Constructor constructor = personClass.getConstructor(String.class,int.class);
System.out.println(constructor);
//创建对象
Object person = constructor.newInstance("张三",16);
System.out.println(person);
System.out.println("----");
Constructor constructor1 = personClass.getConstructor();
Object person1 = constructor1.newInstance();
System.out.println(person1);
System.out.println("----");
//简化创造空参对象
Object o = personClass.newInstance();
System.out.println(o);
}
}
ReflectDemo4
package edgedo.reflect;
import edgedo.pojo.Person;
import java.lang.reflect.Method;
public class ReflectDemo4 {
/* 3.获取成员方法们
Method getMethod(String name, 类<?>... parameterTypes)
Method [] getMethods()
Method getDeclaredMethod(String name, 类... parameterTypes)
Method [] getDeclaredMethods()
*/
public static void main(String[] args) throws Exception {
//1.获取Person的Class对象
Class<Person> personClass = Person.class;
//获取指定名称的方法
Method eatMethod = personClass.getMethod("eat");
//创建对象
Person person =new Person();
//执行方法
eatMethod.invoke(person);
//获取有参的方法
Method eatMethod2 = personClass.getMethod("eat",String.class);
eatMethod2.invoke(person,"咖喱土豆");
//获取所有public修饰的方法
Method[] methods = personClass.getMethods();
for (Method method:methods){
System.out.println(method);
System.out.println("-----");
System.out.println(method.getName());
}
//获取类名
String className = personClass.getName();
System.out.println(className);
}
}
ReflectTest
package edgedo.reflect;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Properties;
public class ReflectTest {
public static void main(String[] args) throws Exception {
//可以创建任意类的对象 可以执行任意方法
/*前提:不能改变该类的任意代码
可以创建任意类的对象 可以执行任意方法*/
//1.加载配置文件
//1.1创建properties对象
Properties pro= new Properties();
//1.2 加载配置文件 转换为一个集合
//1.2.1 获取class目录下的配置文件的目录
ClassLoader classLoader = ReflectTest.class.getClassLoader();
InputStream inputStream = classLoader.getResourceAsStream("pro.properties");
pro.load(inputStream);
//2. 获取配置文件中定义的数据
String className = pro.getProperty("className");
String methodName = pro.getProperty("methodName");
//3.加载该类进内存
Class cls = Class.forName(className);
//4.创建对象
Object obj = cls.newInstance();
//5. 获取方法对象
Method method = cls.getMethod(methodName);
method.invoke(obj);
}
}