這裏有一個User沒有無參構造java
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的三種方法api
1.直接new一個Useride
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封裝一個工具類this
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); } } }
測試用例:google
@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來調用Unsafecode
pom中添加依賴xml
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.5</version> </dependency>
InstanceHelperget
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()); }