反射(一)

一.类加载器
    当程序要使用某个类时,如果类还没有被加载到内存中,JVM则会通过类的加载器,类的连接,类初始化这三个步骤来完成类的加载,熟称:类加载或类初始化
    类的加载:将.class文件读入内存,并为该文件创建一个java.lang.Class对象,任何类被加载时,系统都会为之建立一个这样的对象
    类的连接:1.验证阶段->验证加载类内部结构是否正确,并协调与其它类的关联。
            2.准备阶段->分配内存空间,并设置默认值
            3.解析阶段->将类的二进制的符号引用替换成为直接引用
    类的初始化:主要是对变量进行初始化 步骤:若没加载类和连接,则加载连接,若父类没有加载,则加载连接,若类中有初始化语句,则执行这些语句
    初始化类的时机:创建类,调用类的方法,访问类的成员,用反射来强制创建某个类或接口对应的java.lang.Class对象,使用某个类的子类,java.exe运行某个类
    类加载器的机制:全盘负责->加载一个Class时,该Class所依赖和引用的其它Class也由该加载器载入,除非显示的说明用另一个加载器来完成
                 父类委托->加载一个Class时,先让父类试图加载该Class,父类无法完成时,才试图从自己的路径中加载
                 缓存机制->所有加载过的Class都会放在缓存区中,程序使用某一个Class对象时,先从缓存区中找Class,只有缓存中不存在Class
                          时,系统才会调用该类的二进制数据,生成Class对象,存到缓存区中


二.反射
   Java反射机制:在运行时去获取一个类的变量和方法信息,用得到的这些信息去创建该对象,调用方法的机制。
   1.获取Class类的对象:通过反射去使用一个类,首先要获取该类的字节码文件(xxx.class 由xxx.java编译出来的)去获得该类的Class对象
     使用类的class属性来获取该类对应的Class对象,
     调用对象的getClass()方法来获取所属类的Class对象
     使用Class类的静态方法:forName(String className),完整包名路径名

 

package twelve;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author KuKaFei.Hai
 * @date 2020/4/24 : 16:10
 * 反射得到类的对象,要使用类的相关成员变量,成员方法等,必须要分别对成员变量和成员方法进行获取,并不能像对象去调用
 * Class ->构造方法-->newInstance-->对象->getConstructor->使用构造方法,调用构造函数,创建对象
 * Class ->构造方法-->newInstance-->对象->getDeclaredField->使用获取成员变量的方法,调用成员变量
 * Class ->构造方法-->newInstance-->对象->getDeclaredMethods->使用获取成员方法,调用成员方法
 * <p>
 * 暴力反射
 * nullConst.setAccessible(true);
 */
public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        //类的.class属性来获得该类的Class对象
        Class<Student> stuClassA = Student.class;
        //调用对象的getClass()方法来获取所属类的Class对象
        Student stup = new Student();
        Class<? extends Student> stuClassB = stup.getClass();
        //使用Class类的静态方法:forName(String className),完整包名路径名
        Class<?> stuClassC = Class.forName("twelve.Student");
        //判断三种不通的方式所指向的是否是同一个Class文件
        boolean flag1 = stuClassA == stuClassB;
        boolean flag2 = stuClassA == stuClassC;
        boolean flag3 = stuClassB == stuClassC;
        System.out.println(flag1 && flag2 && flag3);
        System.out.println("-----------------------");
        //getConstructors() 只能获取公有的
        Constructor<?>[] constructors = stuClassC.getConstructors();
        for (Constructor<?> con : constructors) {
            System.out.println(con);
        }
        System.out.println("------------------------");
        // getDeclaredConstructors() 私有,公共的,全获取
        Constructor<?>[] declaredConstructors = stuClassC.getDeclaredConstructors();
        for (Constructor<?> con : declaredConstructors) {
            System.out.println(con);
        }
        //获取某个特定的构造函数
        Constructor<?> nullCon = stuClassC.getConstructor();
        //利用构造方法创建一个实例
        Object refStuA = nullCon.newInstance();
        System.out.println(refStuA);
        System.out.println("------------");
        Constructor<?> con3 = stuClassC.getConstructor(String.class, int.class, String.class);
        Object stuc = con3.newInstance("李某", 28, "江西九江");
        System.out.println(stuc);
        System.out.println("-------------");
        /**
         * 暴力反射 获得的私有方法等,不能直接调用,需要使用
         * setAccessible(true) 打开访问权限,才可以调用生成对象
         */
        //获得私有构造器
        Constructor<?> priveteCont = stuClassC.getDeclaredConstructor(String.class);
        //打开访问权限
        priveteCont.setAccessible(true);
        //私有构造器,获得对象
        Object priStu = priveteCont.newInstance("王某");
        System.out.println(priStu);
        System.out.println("-----------");
        /**
         * 反射获取成员变量
         *
         */
        //获取所有的成员变量
        Field[] decFiles = stuClassC.getDeclaredFields();
        for (Field f : decFiles) {
            System.out.println(f);
        }
        //获取单个成员变量
        Field name = stuClassC.getDeclaredField("name");
        Field age = stuClassC.getDeclaredField("age");
        Field addrss = stuClassC.getField("addrss");
        //获取构造器,生成对象,才对能获取的成员变量,赋值
        Constructor<?> nullConst = stuClassC.getConstructor();
        //生成实例
        Object nullObj = nullConst.newInstance();
        //暴力破解,访问私有属性
        //nullConst.setAccessible(true);
        // 获取到的成员对象,调用set()方法,给实例nullObj,赋值"xxxx"
        name.setAccessible(true);
        name.set(nullObj, "周某");
        age.set(nullObj, 48);
        addrss.set(nullObj, "江西九江");
        System.out.println(nullObj);
        System.out.println("------------------------");
        /**
         * 反射获取成员方法
         * Class ->构造方法-->newInstance-->对象->getDeclaredMethods->使用获取成员方法,调用成员方法
         */
        Method[] decMethods = stuClassC.getDeclaredMethods();
        //包括类中的所有成员方法和接口,继承来的所有的方法
        for(Method me :decMethods){
            System.out.println(me);
        }
        System.out.println("==========================================");
        //获取私有的成员方法
        Method studyPri = stuClassC.getDeclaredMethod("studyPri");
        //暴力破解访问权限
        studyPri.setAccessible(true);
        studyPri.invoke(nullObj);
        //获取公有无参方法
        Method studyA = stuClassC.getDeclaredMethod("studyA");
        Method studyB = stuClassC.getDeclaredMethod("studyB", String.class);
        studyA.invoke(nullObj);
        studyB.invoke(nullObj,"周某某");

    }

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值