Added a cache for no-args constructors to avoid expensive reflection everytime an object needs to be instantiated.
This commit is contained in:
parent
861e047a62
commit
6d3e0e92a5
@ -16,6 +16,7 @@
|
||||
|
||||
package com.google.gson;
|
||||
|
||||
import com.google.gson.internal.LruCache;
|
||||
import com.google.gson.internal.Types;
|
||||
import com.google.gson.internal.UnsafeAllocator;
|
||||
|
||||
@ -36,7 +37,22 @@ import java.lang.reflect.Type;
|
||||
final class MappedObjectConstructor implements ObjectConstructor {
|
||||
private static final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create();
|
||||
|
||||
private static final LruCache<Class<?>, Constructor<?>> noArgsConstructorsCache =
|
||||
new LruCache<Class<?>, Constructor<?>>(500);
|
||||
private final ParameterizedTypeHandlerMap<InstanceCreator<?>> instanceCreatorMap;
|
||||
/**
|
||||
* We need a special null value to indicate that the class does not have a no-args constructor.
|
||||
* This helps avoid using reflection over and over again for such classes. For convenience, we
|
||||
* use the no-args constructor of this class itself since this class would never be
|
||||
* deserialized using Gson.
|
||||
*/
|
||||
private static final Constructor<MappedObjectConstructor> NULL_VALUE =
|
||||
getNoArgsConstructorUsingReflection(MappedObjectConstructor.class);
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private MappedObjectConstructor() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
public MappedObjectConstructor(
|
||||
ParameterizedTypeHandlerMap<InstanceCreator<?>> instanceCreators) {
|
||||
@ -71,13 +87,27 @@ final class MappedObjectConstructor implements ObjectConstructor {
|
||||
}
|
||||
|
||||
private <T> Constructor<T> getNoArgsConstructor(Class<T> clazz) {
|
||||
try {
|
||||
Constructor<T> declaredConstructor = clazz.getDeclaredConstructor();
|
||||
declaredConstructor.setAccessible(true);
|
||||
return declaredConstructor;
|
||||
} catch (Exception e) {
|
||||
@SuppressWarnings("unchecked")
|
||||
Constructor<T> constructor = (Constructor<T>)noArgsConstructorsCache.getElement(clazz);
|
||||
if (constructor == NULL_VALUE) {
|
||||
return null;
|
||||
}
|
||||
if (constructor == null) {
|
||||
constructor = getNoArgsConstructorUsingReflection(clazz);
|
||||
noArgsConstructorsCache.addElement(clazz, constructor);
|
||||
}
|
||||
return constructor == NULL_VALUE ? null : constructor;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T> Constructor<T> getNoArgsConstructorUsingReflection(Class<T> clazz) {
|
||||
try {
|
||||
Constructor<T> constructor = clazz.getDeclaredConstructor();
|
||||
constructor.setAccessible(true);
|
||||
return constructor;
|
||||
} catch (Exception e) {
|
||||
return (Constructor<T>) NULL_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
Loading…
Reference in New Issue
Block a user