反射机制概述
动态语言,类运行的时候借助反射取得任何类的内部信息,并能直接操作任意对象的属性和方法
理解Class类并获取Class实例
Class aClass = Class.forName(classPath);//根据给的路径下的类找到反射对象
Class<Person> personClass = Person.class;//根据类名找到它的反射对象
Person P =new Person(22);//根据类的对象找到反射对象
Class aClass1 = P.getClass();
类的加载与ClassLoader的理解
- 类的加载过程:
程序经过jvavac以后,会生成一个或多个字节码文件(.class结尾),接着我们使用java.exe命令对字节码文件进行解释运行。将一些字节码文件加载到内存中。此过程就称为类的加载。加载到内存中的类,我们就称为运行时的类,这些运行时的类,就作为class的一个实例。反射原理
Class clazz =Person.class;将内存中的类转为对象,运行时对象。万事万物皆对象. - 换句话说一个Class的实例对应一个运行时类
- 加载到内存中运行时类,会缓冲一定时间。再此时间之内,我们可以通过不同的方式来获取此运行时类。(问题当加载到内存运行的类 声明周期后 获取的反射还能使用吗)
- 任何加载到内存的结构基本都可以反射(接口、枚举、基本类、数组、注解、void)都可以 点class !!补充数组只要类型和维度一个都是同一个class ==ture;
类的加载 - 将类加载到内存中 (java.exe命令)
- 将类链接(获取类的属性默认0)
- 类的初始化(获取类的属性赋值,和方法)
类的加载器
负责类的加载(将javac生成字节码文件加载到内存中)
只加载一份Class运行时对象
我们通过4个方法获取的就是同一个已经存在的对象。
加载器分为1.引导类加载器(专门用来加载核心类库,获取不到)2.扩展类加载器(加载目录为jie\lib\ext下的jar包) 3.系统类加载器(加载自己导入的包)4.自定义类加载器(使用系统类加载器加载)
JAR包是由字节码文件打包生成的,由扩展类加载器加载。字节码文件就是由java编译器生成的,一个类对应一个字节码文件,
@Test
public void Method() throws IOException {
java.lang.ClassLoader classLoader = Person.class.getClassLoader();
System.out.println(classLoader);
java.lang.ClassLoader parent = classLoader.getParent();获取上一级
System.out.println(parent);
java.lang.ClassLoader parent1 = classLoader.getParent();
System.out.println(parent1);
重点Properties:用来读取配置文件。
@Test
public void metho() throws IOException {
Properties properties =new Properties();
properties.load(new FileInputStream("src\\load.property"));
String property = properties.getProperty("user");
String password = properties.getProperty("password");
System.out.println(property+""+password);
}
}
常见运行时类的对象
@Test
public void method() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException {
//方式一
Class<Person> personClass = Person.class;
Person person = personClass.getConstructor(String.class,int.class).newInstance("json",20);;
//方式二
Class aClass = Class.forName("REFLECT.Person");
Constructor C= aClass.getDeclaredConstructor(String.class);
C.setAccessible(true);
Person a = (Person) C.newInstance("kevin");
System.out.println(a);
// 方式三
Person ff =new Person("kevin",22);
Class aClass1 = ff.getClass();
aClass1.getConstructor().newInstance();
}
}
**写个测试体会反射
问题:什么时候用到反射
当我们到程序运行时都不知道需要什么样的类时,使用反射(动态运行时)
如web和后台的交互
**
package REFLECT;
import org.junit.Test;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Random;
/**
* @Author kevin
* @Description
* @Create 2021-04-03-11:29
* @Modify
*/
public class Createrefobj {
@Test
public void Method() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
for (int i = 0; i <100 ; i++) {
int num =new Random().nextInt(3);
switch (num){
case 1:
System.out.println(getInstance("java.util.Date").toString());
break;
case 2:
System.out.println(getInstance("java.lang.Object").toString());
break;
case 3:
System.out.println(getInstance("src\\REFLECT\\Person").toString());
break;
}
}
}
public Object getInstance(String Classpath) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
return Class.forName(Classpath).getConstructor().newInstance();
}
}
获取运行时类的完整结构(getConstruct/getdeclaredConstruct,getinstance,getFiled,getMethod)
package REFLECT;
import org.junit.Test;
import java.lang.reflect.*;
/**
* @Author kevin
* @Description
* @Create 2021-04-03-12:30
* @Modify
*/
public class GetRunnerEntireObs {
@Test
public void method() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, InstantiationException, ClassNotFoundException {
//获取类中的所有public属性以及获取所有类中的属性
Class<Person> personClass = Person.class;
Field[] fields = personClass.getFields();
// Field[] fields = personClass.getDeclaredFields();
// for (Field f : fields
// ) {
//获取权限修饰符
// int modifiers = f.getModifiers();
// System.out.println(Modifier.toString(modifiers));
//获取数据类型
// Class type = f.getType();
// System.out.println(type);
//获取变量名字
// String name = f.getName();
// System.out.println(name);
//通过反射获取对象方法
// Person person = personClass.getConstructor().newInstance();
//找到具体的方法
// Method nation = personClass.getDeclaredMethod("nation", String.class);
// nation.setAccessible(true);
// Object chian = nation.invoke(person, "Chian");
// System.out.println(chian);
//调用指定的构造器
//1.找到具体的构造器
// Constructor declaredConstructors = personClass.getDeclaredConstructor(String.class);
// declaredConstructors.setAccessible(true);
// Object o = declaredConstructors.newInstance("kevin");
// System.out.println(o);
}
}
调用运行时类的指定结构
每日练习
package REFLECT;
import org.junit.Test;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Properties;
/**
* @Author kevin
* @Description
*
*
*
* 1.写出获取Class实例的三种常见方式
* 2.谈谈对Class类的理解
* 3.创建Class对应运行时类的对象和通用方法,代码实现。以及这样操作,需要对应运行类构造器方面满足的要求。
* 4.在工程或module的src有名字为jdbc.properties的配置文件,文件内容为:name=tom,热河在程序中通过代码获取tom这个变量 值。代码实现
* 5.如何调用方法show()
* @Create 2021-04-03-15:42
* @Modify
*/
public class EverydayPractice {
@Test
public void Method() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException, IOException {
// 获取Class类的三种方式
Class<Person> personClass = Person.class;
Person P =new Person();
Class aClass = Class.forName("P");
Class aClass1 = P.getClass();
// 谈谈对class类的理解
// 反射是基于运行中的字节码文件诞生的技术,类在被加载器加载到内存中的字节码文件可以被反射。使用CLass类来获取类的反射
// 获取指定构造器
Constructor<Person> declaredConstructor = personClass.getDeclaredConstructor(String.class);
declaredConstructor.setAccessible(true);
// 获取指定方法
Person person = declaredConstructor.newInstance("kevin");
Method nation = personClass.getDeclaredMethod("nation", String.class);
nation.setAccessible(true);
Object china = nation.invoke(person, "china");
System.out.println(china);
// 获取指定属性
Field number = personClass.getDeclaredField("number");
number.setAccessible(true);
number.set(person,123456798);
System.out.println(person);
// propertie获取
Properties PC =new Properties();
Class aClass = PC.getClass();
PC.load(new FileInputStream("src\\REFLECT\\jdbc.propertie"));
String name1 = PC.getProperty("name");
System.out.println(name1);
}
}
反射的应用动态代理(使用Proxy方法)
使用一个代理类完成所有被代理类的任务,使用此方法可以动态的应对运行中可能出现的各种不确定的选择,根据选择给出需要的内容。
package Dynamic;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Author kevin
* @Description
* @Create 2021-04-04-10:12
* @Modify
*/
public class ProxyTest {
private static Object man;
public static Object GetInstance(Object o) {
//3.这个获取的参数实例化给第一步
MyInvocationHandler myInvocationHandler =new MyInvocationHandler();
//1.这里获取需要打理类的反射对象
Object o1 = Proxy.newProxyInstance(o.getClass().getClassLoader(), o.getClass().getInterfaces(), myInvocationHandler);
//6.把对象绑定给MyInvocationHandler,调用方法的时候MyInvocationHandler就知道调用什么方法了
myInvocationHandler.bind(o);
return o1;
}
}
//2.这个方法固定的,用来获取第一步需要的一个参数
class MyInvocationHandler implements InvocationHandler {
//5.这里给个参数获取对象
private Object object ;
public void bind(Object o){
this.object =o ;
}
//4.这里要实现获取的对象调用方法的时候是调用这个方法,但需要一个参数obj来确定是那个对象的方法。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return method.invoke(object,args);
}
}
class Superman implements man{
public void brief(){
System.out.println("代理");
System.out.println("I can fly");
}
public void eat(String food){
System.out.println("代理");
System.out.println("I need"+food);
}
public void sleep(){
System.out.println("i dont need sleep ");
}
}
interface man{
void brief();
void eat(String food);
}
class Normalman implements man{
@Override
public void brief() {
System.out.println("i belive myself");
}
@Override
public void eat(String food) {
System.out.println("i eat"+food);
}
public void sleep(){
System.out.println("i need sleep");
}
}
package Dynamic;
/**
* @Author kevin
* @Description
* @Create 2021-04-04-10:40
* @Modify
*/
public class USER {
public static void main(String[] args) {
Normalman normalman =new Normalman();
Superman superman =new Superman();
man m =(man)ProxyTest.GetInstance(normalman);
m.brief();
}
}