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 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 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 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中添加依赖


	com.google.code.gson
	gson
	2.8.5

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 CONSTRUCTOR_CONSTRUCTOR_HOLDER =
            ThreadLocal.withInitial(() -> new ConstructorConstructor(new HashMap<>(0)));

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

你可能感兴趣的:(java 通过Unsafe不使用构造器直接创建对象)