当前位置: 首页 > news >正文

java 通过Unsafe不使用构造器直接创建对象

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

这里有一个User没有无参构造

public class User {

    static {
        System.out.println("static {}");
    }

    {
        System.out.println("{}");
    }

    public User(String username, String password) {
        this.username = username;
        this.password = password;
    }

    private String username;

    private String password;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "username='" + username + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

以下是创建User的三种方法

1.直接new一个User

User user = new User("zhangsan","123456");

2.使用反射则是

Constructor<User> constructor = User.class.getConstructor(String.class, String.class);
User user = constructor.newInstance("zhangsan", "123456");

3.使用Unsafe

final Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
final Field theUnsafeField = unsafeClass.getDeclaredField("theUnsafe");
theUnsafeField.setAccessible(true);
final Object unsafe = theUnsafeField.get(null);
final Method allocateInstance = unsafeClass.getMethod("allocateInstance", Class.class);
User user = (User) allocateInstance.invoke(unsafe, User.class);

简单将Unsafe封装一个工具类

public final class UnsafeHelper {

    private UnsafeHelper() {
    }

    private static final Object unsafe;

    private static final Method allocateInstance;

    static {

        final Class<?> unsafeClass;

        final Field theUnsafeField;

        try {
            unsafeClass = Class.forName("sun.misc.Unsafe");
        } catch (ClassNotFoundException e) {
            throw new UnsupportedOperationException("can't find sun.misc.Unsafe. " + e.getMessage(), e);
        }

        try {
            theUnsafeField = unsafeClass.getDeclaredField("theUnsafe");
        } catch (NoSuchFieldException e) {
            throw new UnsupportedOperationException("can't find the field theUnsafe in sun.misc.Unsafe." + e.getMessage(), e);
        }
        theUnsafeField.setAccessible(true);

        try {
            unsafe = theUnsafeField.get(null);
        } catch (IllegalAccessException e) {
            throw new UnsupportedOperationException("get Unsafe instance failed: " + e.getMessage(), e);
        }

        try {
            allocateInstance = unsafeClass.getMethod("allocateInstance", Class.class);
        } catch (NoSuchMethodException e) {
            throw new UnsupportedOperationException("can't find the method allocateInstance in sun.misc.Unsafe : " + e.getMessage(),
                    e);
        }

    }

    public static <T> T newInstance(Class<?> clazz) {
        try {
            return (T) allocateInstance.invoke(unsafe, clazz);
        } catch (Exception e) {
            throw new UnsupportedOperationException("create instance for " + clazz + " failed. " + e.getMessage(), e);
        }
    }
}

测试用例:

    @Test(expected = InstantiationException.class)
    public void newInstanceByReflect1() throws IllegalAccessException,
            InstantiationException {
        try {
            User user = User.class.newInstance();
            Assert.assertNull(user.getUsername());
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }

    }


    @Test
    public void newInstanceByReflect2() throws NoSuchMethodException, IllegalAccessException,
            InvocationTargetException, InstantiationException {
        Constructor<User> constructor = User.class.getConstructor(String.class, String.class);
        User user = constructor.newInstance("zhangsan", "123456");
        System.out.println(user);
        Assert.assertEquals("zhangsan", user.getUsername());
    }


    @Test
    public void newInstanceByUnsafe() {
        User user = UnsafeHelper.newInstance(User.class);
        System.out.println(user);
        Assert.assertNull(user.getUsername());
    }

使用Gson提供的api来调用Unsafe

pom中添加依赖

<dependency>
	<groupId>com.google.code.gson</groupId>
	<artifactId>gson</artifactId>
	<version>2.8.5</version>
</dependency>

InstanceHelper

import com.google.gson.internal.ConstructorConstructor;
import com.google.gson.internal.ObjectConstructor;
import com.google.gson.reflect.TypeToken;

import java.lang.reflect.Type;
import java.util.HashMap;

/**
 * 无需构造器直接根据class创建实例
 *
 * @author Val Song
 * @date 2018/10/17
 * @since 1.0.0
 */
public final class InstanceHelper {

    private InstanceHelper() {
    }

    private static ThreadLocal<ConstructorConstructor> CONSTRUCTOR_CONSTRUCTOR_HOLDER =
            ThreadLocal.withInitial(() -> new ConstructorConstructor(new HashMap<>(0)));

    /**
     * 不需要构造器创建实例,底层通过Unsafe实现
     *
     * @param type
     * @param <T>
     * @return
     */
    public static <T> T newInstance(Type type) {
        TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(type);
        ObjectConstructor<T> objectConstructor = CONSTRUCTOR_CONSTRUCTOR_HOLDER.get().get(typeToken);
        return objectConstructor.construct();
    }

}

InstanceHelper测试用例

@Test
public void newInstanceByGson() {
	User user = InstanceHelper.newInstance(User.class);
	System.out.println(user);
	Assert.assertNull(user.getUsername());
}

转载于:https://my.oschina.net/valsong/blog/2248616

相关文章:

  • jenkins配置用户角色权限,根据不同权限显示视图、Job
  • JVM虚拟机(五):JDK8内存模型—消失的PermGen
  • Java8 new Time Api
  • Ansible常用模块详解
  • 学以致用二十三-----shell脚本里调用脚本
  • 创建新用户,及用新用户名和密码登录--------------DCL
  • Docker Compose 简介
  • 算法-插入排序
  • HAWQ配置之客户端访问
  • 自动化测试Jest及其应用
  • 前端h5框架总结
  • Linux基础命令---sudo
  • Algs4-1.1.11编写一段代码,打印出一个二维布尔数组的内容
  • [Google Guava] 2.1-不可变集合
  • I/O复用模型详解(网络总结)
  • 深入了解以太坊
  • CentOS7简单部署NFS
  • fetch 从初识到应用
  • HashMap剖析之内部结构
  • HTTP中的ETag在移动客户端的应用
  • Java应用性能调优
  • MySQL数据库运维之数据恢复
  • 简单基于spring的redis配置(单机和集群模式)
  • 实战:基于Spring Boot快速开发RESTful风格API接口
  • 一些关于Rust在2019年的思考
  • 好程序员大数据教程Hadoop全分布安装(非HA)
  • #HarmonyOS:基础语法
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • %3cscript放入php,跟bWAPP学WEB安全(PHP代码)--XSS跨站脚本攻击
  • (26)4.7 字符函数和字符串函数
  • (C#)if (this == null)?你在逗我,this 怎么可能为 null!用 IL 编译和反编译看穿一切
  • (day 2)JavaScript学习笔记(基础之变量、常量和注释)
  • (二)构建dubbo分布式平台-平台功能导图
  • (附源码)计算机毕业设计SSM疫情下的学生出入管理系统
  • (十六)串口UART
  • (中等) HDU 4370 0 or 1,建模+Dijkstra。
  • (转)Spring4.2.5+Hibernate4.3.11+Struts1.3.8集成方案一
  • (转)VC++中ondraw在什么时候调用的
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • .FileZilla的使用和主动模式被动模式介绍
  • .net mvc 获取url中controller和action
  • .net Signalr 使用笔记
  • .NET 中 GetProcess 相关方法的性能
  • ::
  • @data注解_SpringBoot 使用WebSocket打造在线聊天室(基于注解)
  • @vue/cli脚手架
  • [C++基础]-入门知识
  • [c语言]小课堂 day2
  • [HDU]2161Primes
  • [LeetCode] Minimum Path Sum
  • [Python] Ubuntu12.04LTS
  • [Rust] 使用vscode实现HelloWorld程序并进行debug
  • [Spring]一文明白IOC容器和思想
  • [SWPUCTF 2021 新生赛]crypto8
  • [yolov9]使用python部署yolov9的onnx模型