反射机制

反射机制概述

动态语言,类运行的时候借助反射取得任何类的内部信息,并能直接操作任意对象的属性和方法

理解Class类并获取Class实例

Class aClass = Class.forName(classPath);//根据给的路径下的类找到反射对象
        Class<Person> personClass = Person.class;//根据类名找到它的反射对象
        Person P =new Person(22);//根据类的对象找到反射对象
        Class aClass1 = P.getClass();   

类的加载与ClassLoader的理解

  1. 类的加载过程:
    程序经过jvavac以后,会生成一个或多个字节码文件(.class结尾),接着我们使用java.exe命令对字节码文件进行解释运行。将一些字节码文件加载到内存中。此过程就称为类的加载。加载到内存中的类,我们就称为运行时的类,这些运行时的类,就作为class的一个实例。反射原理
    Class clazz =Person.class;将内存中的类转为对象,运行时对象。万事万物皆对象.
  2. 换句话说一个Class的实例对应一个运行时类
  3. 加载到内存中运行时类,会缓冲一定时间。再此时间之内,我们可以通过不同的方式来获取此运行时类。(问题当加载到内存运行的类 声明周期后 获取的反射还能使用吗)
  4. 任何加载到内存的结构基本都可以反射(接口、枚举、基本类、数组、注解、void)都可以 点class !!补充数组只要类型和维度一个都是同一个class ==ture;
    类的加载
  5. 将类加载到内存中 (java.exe命令)
  6. 将类链接(获取类的属性默认0)
  7. 类的初始化(获取类的属性赋值,和方法)
    类的加载器
    负责类的加载(将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();
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值