Java反射

 

  

 

 

Method和Field,Constructor对象都有setAccessible()方法

setAccessible作用是启动和禁用访问安全检查的开关

Class类常用方法

 

反射机制是java实现动态语言的关键,也就是通过反射实现类动态加载。

1.静态加载:编译时加载相关的类,如果没有则报错,依赖性太强
2.动态加载:运行时加载需要的类,如果运行时不用该类,则不报错,降低了依赖性

 

JVM在该阶段的主要目的是将字节码从不同的数据源(可能是class文件、也可能是jar包,甚至网络)转化为二进制字节流加载到内存中,并生成一个代表该类的
java.Iang.Class对象

连接阶段-验证
1.目的是为了确保 Class文件的字节流中包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。
2.包括:文件格式验证(是否以魔数oxcafebabe开头)、元数据验证、字节码验证和符号引用验证[举例说明]
3.可以考虑使用-Xverify:none参数来关闭大部分的类验证措施,缩短虚拟机类加载的时间。

连接阶段-准备
1. JVM 会在该阶段对静态变量,分配内存并默认初始化(对应数据类型的默认初始值,如O、OL、null、false 等)。这些变量所使用的内存都将在方法区中进行分配.

Initialization(初始化)
1.到初始化阶段,才真正开始执行类中定义的 Java程序代码,此阶段是执行<clinit>()方法的过程。
2. <clinit>()方法是由编译器按语句在源文件中出现的顺序,依次自动收集类中的所有静态变量的赋值动作和静态代码块中的语句,并进行合并。
3.虚拟机会保证一个类的<clinit>()方法在多线程环境中被正确地加锁、同步,如果多个线程同时去初始化一个类,那么只会有一个线程去执行这个类的<clinit>()方法,其他线程都需要阻塞等待,直到活动线程执行<clinit>()方法完毕

 

 

上述实例代码:

复制代码
public class fs {
    public static void main(String[] args) throws IOException, ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException, NoSuchFieldException {
        //使用Properties类,可以读写配置文件
        //不使用new Cat创建一个对象
        Properties properties = new Properties();
        properties.load(new FileInputStream("src\\re.properties"));
        String classpath = properties.get("classpath").toString();
        String method = properties.get("method").toString();
        //不能实现,classpath,method是String类型
        //使用反射机制解决
        //返回一个class类型对象
        Class<?> cls = Class.forName(classpath);
        Object o = cls.newInstance();
        Method method1 = cls.getMethod(method);
        //方法.invoke(对象); 调用类的方法
        method1.invoke(o);
        //得到属性字段(只能的得到公用的属性)
        Field name = cls.getField("name");
        //传统方法 对象.成员变量,反射机制  成员变量对象.get(对象);
        System.out.println(name.get(o));
        //Constructor代表构造方法,Constructor对象表示构造起
        Constructor<?> constructor = cls.getConstructor();
        System.out.println(constructor);
        //得到一个有参构造器
        Constructor<?> constructor1 = cls.getConstructor(String.class);
        System.out.println(constructor1);

        //类的常用方法
        //得到是哪一个类
        System.out.println(cls);//class jd.Cat
        //得到包名
        System.out.println(cls.getPackage().getName());
        //得到全类名
        System.out.println(cls.getName());
        //通过cls创建一个对象实例
        Object o1 = cls.newInstance();
        Cat cat = (Cat)o1;
        System.out.println(cat.name);
        System.out.println(cat);
        //得到类的属性
        Field name1 = cls.getField("name");
        System.out.println(name1.get(cat));
        //给属性赋值
        name.set(cat,"狗");
        System.out.println(name1.get(cat));
        //得到所有的所属性
        Field[] fields = cls.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }

        //获取Class类的方法
        //编译阶段
        Class<?> cls2 = Class.forName(classpath);
        System.out.println(cls2);
        //加载阶段
        Class<Cat> cls3 = Cat.class;
        System.out.println(cls3);
        //运行阶段
        Cat cat1 = new Cat();
        Class<? extends Cat> cls4 = cat1.getClass();
        System.out.println(cls4);
        //类加载器
        ClassLoader classLoader = cat.getClass().getClassLoader();
        Class<?> cls5 = classLoader.loadClass(classpath);
        System.out.println(cls5);

        //cls cls1 cls2 cls3是同一个类
        //获得私有的属性
        Field[] declaredFields = cls.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField.getName());
        }

        //反射爆破创建实例
        //如果无参构造器创建实例
        Object o2 = cls.newInstance();
        System.out.println(o2);
        //通过public的有参构造器创建实例
        Constructor<?> constructor2 = cls.getConstructor(String.class);
        Object mqs = constructor2.newInstance("mqs");
        System.out.println(mqs);
        //通过非public有参构造器创建实例
        Constructor<?> declaredConstructor = cls.getDeclaredConstructor(String.class, int.class);
        declaredConstructor.setAccessible(true);
        Object mqs1 = declaredConstructor.newInstance("mq", 23);
        System.out.println(mqs1);

        //通过反射访问类中的成员
        Object o3 = cls.newInstance();
        System.out.println(o3.getClass());//运行类型
        Field name2 = cls.getField("name");
        name2.set(o3,"mm");
        System.out.println(name2.get(o3));
        //还有其他方法略

        //通过反射访问方法(方法同样也可以爆破)
        Object o4 = cls.newInstance();//是一个cat对象
        Method hi = cls.getMethod("hi");
        Method hi1 = cls.getDeclaredMethod("hi");
        hi.invoke(o4);
        //反射访问私有方法
        Method hi2 = cls.getDeclaredMethod("say",String.class);
        hi2.setAccessible(true);
        Object kl = hi2.invoke(o4, "kl");
        System.out.println(kl);
    }
}
复制代码
复制代码
public class Cat {
    public String name = "猫";
    public int age = 12;
    public String  nature = "好";
    private int lon = 20;

    public void hi(){
        System.out.println("hi"+name);
    }

    public static String say(String name){
        return name+"说";
    }

    public Cat(){

    }

    public Cat(String name) {
        this.name = name;
    }


    private Cat(String name, int age) {
        this.name = name;
        this.age = age;
    }


    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
复制代码
posted @   贝勒爷ma  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!
点击右上角即可分享
微信分享提示