java如何不通过构造函数创建对象(Unsafe)
作者:子♂衿
java中不通过构造函数创建对象
(也有说不创建对象直接执行成员方法)
这里就不和你们扯什么通过 反序列化、clone等方法了 个人觉得都是在胡扯。
如何不执行构造函数创建对象?
先来带大家认识一个类 sun.misc.Unsafe
该类主要提供一些直接访问系统内存资源等等(学过C语言的应该知道和C语言中的指针一样),但是由于此类能够直接操作内存,这无疑也增加了程序的安全风险。所以技术不是那么好的千万不要在应用中直接使用哟。
从上图可以看出 java是不允许直接创建该类对象的,但是我们可以看到第一个红框哪里明显有个Unsafe类的对象,该类是单例的。 那么怎么获取该类的实例呢?
注意:本版较低的jdk可能没有这个方法
有一个getUnsafe()方法,但是很不幸,该方法是提供给jdk内部使用的。我们直接调用该方法会抛异常的。
具体原理就是该类会判断当前调用这个方法的类是不是由Bootstrap类加载器加载的。
那么如何获取这个Unsafe实例呢?
有两种方法
- 一、让我们使用了Unsafe对象的类通过Bootstrap加载
- 二、熟悉反射的同学就会心头一冷笑,这还不简单吗?是的,我们可以直接通过反射获取
这里只讲通过反射获取的方式
获取Unsafe对象
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); Unsafe unsafe = (Unsafe) theUnsafe.get(null);
java基础好的同学,这段代码应再熟悉不过了
不执行构造函数创建对象?
Unsafe类中有一个 sun.misc.Unsafe#allocateInstance
方法, 接收一个Class<?> 类型对象,然后返回该类的一个对象
我们准备一个测试类
class Test{ private String name; public Test(){ System.out.println("test construct"); } }
该类构造方法私有,然后构造方法中打印了一句话,也就是,只要你创建一个新的对象就会打印这句话。
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); Unsafe unsafe = (Unsafe) theUnsafe.get(null); Test test = (Test) unsafe.allocateInstance(Test.class);
测试代码
上面这段代码是没有任何输出的,也就是没有执行构造方法,但是却返回了一个对象
因此也听有人说 压根就没有创建对象, 这我也不好说有没有创建对象,因为对于底层具体怎么实现的我也不造,但是我更倾向于是没有执行构造方法创建对象这种说法吧。
总结以及注意事项
通过这篇文章我们知道原来java中也提供了直接操作内存的类,而且该类还能不执行构造方法就返回一个对象,不过因此也有注意,Unsafe类是直接操作内存的,所以他所分配的内存jvm的垃圾收集器是无法释放的。该类操作的内存和C语言中一样,要手动释放。
关于该类的更多使用方式可到网上找相关的资料
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。