Java基础之反射很重要

Java基础之反射很重要,第1张

Java基础之反射很重要 获取对象的方法



只要元素类型和维度一样返回的就是同一个class对象

加载的内存分析

类加载主要经历三个阶段

  1. 加载:把.class文件加载到内存中,生成一个Class对象。
  2. 链接:先检查代码是否符合规范确保没有安全方面的问题,然后开始为静态变量开辟内存空间,这些空间都在方法区中进行分配,把常量池中的符号指向引用地址。
  3. 初始化:clinit方法把所有静态变量的赋值 *** 作和静态代码合在一起执行一遍完成初始化。
什么时候会发生类的初始化 主动引用:会发生类的初始化

虚拟机启动时会先加载main方法所在的类
new一个类对象会发生类的初始化
调用类的静态成员和静态方法(final不算在内)
反射
当初始化一个类时,会先初始化他的父类。

被动引用:不会发生类的初始化

通过子类引用父类的静态变量不会导致子类初始化
定义这个类的数组不会触发该类的初始化
引用常量不会触发该类的初始化(常量在链接阶段就存入常量池了)

类加载器

类缓存:一个类一旦被加载,会缓存一段时间。垃圾回收机制可以回收这些Class对象

引导类加载器:用C++编写的,是JVM自带的加载器。负责Java平台核心库(rt.jar),该加载器无法直接获取。
扩展类加载器:负责加载扩展库jre/lib/ext目录或指定目录下的jar包。
系统类加载器:最常用的加载器,我们自己写的类就是通过这个加载器加载的。

动态创建对象执行方法

import pojo.User;

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

public class Test02 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
//        获取Class对象
        Class c1 = Class.forName("pojo.User");
//        通过Class对象的newInstance()方法构造一个对象
//        其实质是调用了这个对象的无参构造
//        如果这个对象没有无参构造那么这个方法会报错
        User user1 = (User)c1.newInstance();
        System.out.println(user1);
//      如果这个对象没有无参构造
//        可以使用反射获取他的有参构造器
        Constructor constructor = c1.getDeclaredConstructor(String.class, String.class);
        User zjq = (User)constructor.newInstance( "zjq", "123");
        System.out.println(zjq);
//        也可以通过Class对象获得他的方法 如果该方法是私有的,我们可以通过.setAccessible() 方法把他设置为true
        Method setName = c1.getDeclaredMethod("setName", String.class);
        setName.setAccessible(true);
//        原本私有的方法下载可以使用了
        setName.invoke(zjq, "梁朝伟");
        System.out.println(zjq);
//        成功获得一张改名卡
//        小张已经不是小张了


    }
}

性能分析对比
import pojo.User;

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

//测试三种方式执行代码的效率
public class Test03 {
    //普通方法
    public static void test1(){
        User user = new User();
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            user.getName();
        }
        long end = System.currentTimeMillis();
        System.out.println(end-start);
    }
//    调用反射执行方法
    public static void test2() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c = user.getClass();
        Method getName = c.getDeclaredMethod("getName", null);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
           getName.invoke(user,null);
        }
        long end = System.currentTimeMillis();
        System.out.println(end-start);
    }
//    关闭检测权限执行方法
    public static void test3() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        User user = new User();
        Class c = user.getClass();
        Method getName = c.getDeclaredMethod("getName", null);
        getName.setAccessible(true);
        long start = System.currentTimeMillis();
        for (int i = 0; i < 10000000; i++) {
            getName.invoke(user,null);
        }
        long end = System.currentTimeMillis();
        System.out.println(end-start);
    }

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
        test1();
        test2();
        test3();
    }
}

测试结果:
结论:关闭了权限检测之后执行方法会比不关更快,普通方式调用是最快的。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5672995.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-16
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存