这里有一个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());
}