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

这里有一个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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值