只要元素类型和维度一样返回的就是同一个class对象
类加载主要经历三个阶段
- 加载:把.class文件加载到内存中,生成一个Class对象。
- 链接:先检查代码是否符合规范确保没有安全方面的问题,然后开始为静态变量开辟内存空间,这些空间都在方法区中进行分配,把常量池中的符号指向引用地址。
- 初始化: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(); } }
测试结果:
结论:关闭了权限检测之后执行方法会比不关更快,普通方式调用是最快的。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)