前两篇博客中很多地方都是用到了ResolvableType获取类型信息,这篇就来详细看看它。
ResolvableType封装了Java的Type,提供了getSuperType()方法访问父类型,getInterfaces()反回实现的接口,getGeneric()获取泛型参数,resolve()转化为Class对象。那么什么事Java的Type呢,可以看出Type有四个子接口,一个子类。每种类型代表啥意思可以参考这篇文章《Java Type详解》。下面看看ResolvableType具体实现。
ResolvableType的构造函数都是私有的,提供了四类实例化对象的静态方法:
- forField(Field):获取指定字段的类型
- forMethodParameter(Method, int):获取指定方法的指定形参的类型
- forMethodReturnType(Method):获取指定方法的返回值的类型
- forClass(Class):直接封装指定的类型
每个方法最终都会调用同一个构造方法
static ResolvableType forType(
@Nullable Type type, @Nullable TypeProvider typeProvider, @Nullable VariableResolver variableResolver);
先来看看forField()方法:
public static ResolvableType forField(Field field) {
Assert.notNull(field, "Field must not be null");
return forType(null, new FieldTypeProvider(field), null);
}
首先将field封装成FieldTypeProvider,然后调用上述都会使用的forType()方法。FieldTypeProvider实现了TypeProvider接口,该接口有两个方法,对于FieldTypeProvider就是返回字段的类型,该对象表示此Field对象表示的字段的声明的类型,如果Type是参数化类型,则返回的Type对象必须准确反映源代码中使用的实际类型参数对象和该字段本身的Field对象。
interface TypeProvider extends Serializable {
@Nullable
Type getType();
@Nullable
default Object getSource() {
return null;
}
}
static class FieldTypeProvider implements TypeProvider {
private final String fieldName;
private final Class<?> declaringClass;
private transient Field field;
public FieldTypeProvider(Field field) {
this.fieldName = field.getName();
this.declaringClass = field.getDeclaringClass();
this.field = field;
}
@Override
public Type getType() {
return this.field.getGenericType();
}
@Override
public Object getSource() {
return this.field;
}
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
inputStream.defaultReadObject();
try {
this.field = this.declaringClass.getDeclaredField(this.fieldName);
}
catch (Throwable ex) {
throw new IllegalStateException("Could not find original class structure", ex);
}
}
}
下面看一下都会用到的forType()方法。
static ResolvableType forType(
@Nullable Type type, @Nullable TypeProvider typeProvider, @Nullable VariableResolver variableResolver) {
if (type == null && typeProvider != null) {
type = SerializableTypeWrapper.forTypeProvider(typeProvider);
}
if (type == null) {
return NONE;
}
// For simple Class references, build the wrapper right away -
// no expensive resolution necessary, so not worth caching...
if (type instanceof Class) {
return new ResolvableType(type, typeProvider, variableResolver, (ResolvableType) null);
}
// Purge empty entries on access since we don't have a clean-up thread or the like.
cache.purgeUnreferencedEntries();
// Check the cache - we may have a ResolvableType which has been resolved before...
ResolvableType resultType = new ResolvableType(type, typeProvider, variableResolver);
ResolvableType cachedType = cache.get(resultType);
if (cachedType == null) {
cachedType = new ResolvableType(type, typeProvider, variableResolver, resultType.hash);
cache.put(cachedType, cachedType);
}
resultType.resolved = cachedType.resolved;
return resultType;
}
上面代码获取type时没有简单的调用typeProvider.getType(),而是使用SerializableTypeWrapper.forTypeProvider(typeProvider)包装了一个代理类,这么做的目的是为了type可以做做序列化并且缓存。
static Type forTypeProvider(final TypeProvider provider) {
Assert.notNull(provider, "Provider must not be null");
Type providedType = provider.getType();
if (providedType == null) {
return null;
}
if (providedType instanceof Serializable) {
return providedType;
}
Type cached = cache.get(providedType);
if (cached != null) {
return cached;
}
for (Class<?> type : SUPPORTED_SERIALIZABLE_TYPES) {
if (type.isAssignableFrom(providedType.getClass())) {
ClassLoader classLoader = provider.getClass().getClassLoader();
Class<?>[] interfaces = new Class<?>[] {type, SerializableTypeProxy.class, Serializable.class};
InvocationHandler handler = new TypeProxyInvocationHandler(provider);
cached = (Type) Proxy.newProxyInstance(classLoader, interfaces, handler);
cache.put(providedType, cached);
return cached;
}
}
throw new IllegalArgumentException("Unsupported Type class: " + providedType.getClass().getName());
}
TypeProxyInvocationHandler。
public Object invoke(Object proxy, Method method, @Nullable Object[] args) throws Throwable {
if (method.getName().equals("equals") && args != null) {
Object other = args[0];
// Unwrap proxies for speed
if (other instanceof Type) {
other = unwrap((Type) other);
}
return ObjectUtils.nullSafeEquals(this.provider.getType(), other);
}
else if (method.getName().equals("hashCode")) {
return ObjectUtils.nullSafeHashCode(this.provider.getType());
}
else if (method.getName().equals("getTypeProvider")) {
return this.provider;
}
if (Type.class == method.getReturnType() && args == null) {
return forTypeProvider(new MethodInvokeTypeProvider(this.provider, method, -1));
}
else if (Type[].class == method.getReturnType() && args == null) {
Type[] result = new Type[((Type[]) method.invoke(this.provider.getType())).length];
for (int i = 0; i < result.length; i++) {
result[i] = forTypeProvider(new MethodInvokeTypeProvider(this.provider, method, i));
}
return result;
}
try {
return method.invoke(this.provider.getType(), args);
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
}
在结合ResolvableType的getType()方法看一下,如果type是代理对象则先调用getTypeProvider()方法得到TypeProvider在调用getType()方法获取到Type。
public Type getType() {
return SerializableTypeWrapper.unwrap(this.type);
}
public static <T extends Type> T unwrap(T type) {
Type unwrapped = type;
while (unwrapped instanceof SerializableTypeProxy) {
unwrapped = ((SerializableTypeProxy) type).getTypeProvider().getType();
}
return (unwrapped != null ? (T) unwrapped : type);
}
获取type先通过构造函数实例化一个resultType,这个resultType的resolved暂时是null。间接的通过使用相同的Type和TypeProvider作为参数使用另一构造函数实例化一个临时的对象,因为这个构造函数可以生成resolved,再将resolved赋值给 resultType。那为啥不直接使用后者实例化对象呢,因为后者需要一个hashcode,而前者可以生成hashcode。
生成hashCode。
private int calculateHashCode() {
int hashCode = ObjectUtils.nullSafeHashCode(this.type);
if (this.typeProvider != null) {
hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.typeProvider.getType());
}
if (this.variableResolver != null) {
hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.variableResolver.getSource());
}
if (this.componentType != null) {
hashCode = 31 * hashCode + ObjectUtils.nullSafeHashCode(this.componentType);
}
return hashCode;
}
生成resolved。
private Class<?> resolveClass() {
if (this.type == EmptyType.INSTANCE) {
return null;
}
if (this.type instanceof Class) {
return (Class<?>) this.type;
}
if (this.type instanceof GenericArrayType) {
Class<?> resolvedComponent = getComponentType().resolve();
return (resolvedComponent != null ? Array.newInstance(resolvedComponent, 0).getClass() : null);
}
return resolveType().resolve();
}
ResolvableType resolveType() {
if (this.type instanceof ParameterizedType) {
return forType(((ParameterizedType) this.type).getRawType(), this.variableResolver);
}
if (this.type instanceof WildcardType) {
Type resolved = resolveBounds(((WildcardType) this.type).getUpperBounds());
if (resolved == null) {
resolved = resolveBounds(((WildcardType) this.type).getLowerBounds());
}
return forType(resolved, this.variableResolver);
}
if (this.type instanceof TypeVariable) {
TypeVariable<?> variable = (TypeVariable<?>) this.type;
// Try default variable resolution
if (this.variableResolver != null) {
ResolvableType resolved = this.variableResolver.resolveVariable(variable);
if (resolved != null) {
return resolved;
}
}
// Fallback to bounds
return forType(resolveBounds(variable.getBounds()), this.variableResolver);
}
return NONE;
}
resolveClass()方法的目的就是将type转换成相关的Class对象,因为只有满足type instanceof Class才返回,否则继续调用forType()递归上面的代码。
ResolvableType还有一个as方法,功能是沿着继承链向上查找参数指定的ResolvableType。
public ResolvableType as(Class<?> type) {
if (this == NONE) {
return NONE;
}
if (ObjectUtils.nullSafeEquals(resolve(), type)) {
return this;
}
for (ResolvableType interfaceType : getInterfaces()) {
ResolvableType interfaceAsType = interfaceType.as(type);
if (interfaceAsType != NONE) {
return interfaceAsType;
}
}
return getSuperType().as(type);
}
下面看看文章开头提及的getSuperType()方法。
public ResolvableType getSuperType() {
Class<?> resolved = resolve();
if (resolved == null || resolved.getGenericSuperclass() == null) {
return NONE;
}
ResolvableType superType = this.superType;
if (superType == null) {
superType = forType(SerializableTypeWrapper.forGenericSuperclass(resolved), asVariableResolver());
this.superType = superType;
}
return superType;
}
SerializableTypeWrapper.forGenericSuperclass(resolved)方法返回当前Class对象父类的可序列化的Type对象,asVariableResolver返回一个DefaultVariableResolver对象,它的resolveVariable()方法用于将TypeVariable转化成 ResolvableType对象,这个类会在isAssignableFrom()方法用到。
private class DefaultVariableResolver implements VariableResolver {
@Override
@Nullable
public ResolvableType resolveVariable(TypeVariable<?> variable) {
return ResolvableType.this.resolveVariable(variable);
}
@Override
public Object getSource() {
return ResolvableType.this;
}
}
Java 面试宝典是大明哥全力打造的 Java 精品面试题,它是一份靠谱、强大、详细、经典的 Java 后端面试宝典。它不仅仅只是一道道面试题,而是一套完整的 Java 知识体系,一套你 Java 知识点的扫盲贴。
它的内容包括:
- 大厂真题:Java 面试宝典里面的题目都是最近几年的高频的大厂面试真题。
- 原创内容:Java 面试宝典内容全部都是大明哥原创,内容全面且通俗易懂,回答部分可以直接作为面试回答内容。
- 持续更新:一次购买,永久有效。大明哥会持续更新 3+ 年,累计更新 1000+,宝典会不断迭代更新,保证最新、最全面。
- 覆盖全面:本宝典累计更新 1000+,从 Java 入门到 Java 架构的高频面试题,实现 360° 全覆盖。
- 不止面试:内容包含面试题解析、内容详解、知识扩展,它不仅仅只是一份面试题,更是一套完整的 Java 知识体系。
- 宝典详情:https://www.yuque.com/chenssy/sike-java/xvlo920axlp7sf4k
- 宝典总览:https://www.yuque.com/chenssy/sike-java/yogsehzntzgp4ly1
- 宝典进展:https://www.yuque.com/chenssy/sike-java/en9ned7loo47z5aw
目前 Java 面试宝典累计更新 400+ 道,总字数 42w+。大明哥还在持续更新中,下图是大明哥在 2024-12 月份的更新情况:
想了解详情的小伙伴,扫描下面二维码加大明哥微信【daming091】咨询
同时,大明哥也整理一套目前市面最常见的热点面试题。微信搜[大明哥聊 Java]或扫描下方二维码关注大明哥的原创公众号[大明哥聊 Java] ,回复【面试题】 即可免费领取。