ByteBuddy中是否有任何方法可以将TypeDescription.Generic转换为适当的java.lang.reflect.Type?

莱尔德·纳尔逊(Laird Nelson)

(ByteBuddy API的表面积非常巨大,这就是为什么我要问这个问题。)

我知道我可以选择aTypeDescription.Generic确定其“排序”,然后从那里手动进行相当费力的操作,但是通常我发现有一种方法可以为我完成这种繁琐的工作。

编辑:评论者要求“乏味”的食谱。在这里(退后一步;请注意,各种的各种实现Type或多或少都与您期望的一样):

 public static final Type toType(final TypeDefinition type) throws ReflectiveOperationException {
    final Type returnValue;
    if (type == null) {
      returnValue = null;
    } else {
      final TypeDescription.Generic genericType = type.asGenericType();
      switch (type.getSort()) {
      case GENERIC_ARRAY:
        returnValue = new DefaultGenericArrayType(toType(type.getComponentType()));
        break;
      case NON_GENERIC:
        returnValue = Class.forName(type.getTypeName(), false, Thread.currentThread().getContextClassLoader());
        break;
      case PARAMETERIZED:
        final TypeDefinition ownerType = genericType.getOwnerType();
        final TypeDefinition rawType = type.asErasure();
        final List<? extends TypeDefinition> actualTypeArguments = genericType.getTypeArguments();
        if (actualTypeArguments == null || actualTypeArguments.isEmpty()) {
          returnValue = new DefaultParameterizedType(toType(ownerType), toType(rawType));
        } else {
          final Type[] actualJavaTypeArguments = new Type[actualTypeArguments.size()];
          for (int i = 0; i < actualTypeArguments.size(); i++) {
            actualJavaTypeArguments[i] = toType(actualTypeArguments.get(i));
          }
          returnValue = new DefaultParameterizedType(toType(ownerType), toType(rawType), actualJavaTypeArguments);
        }
        break;
      case VARIABLE:
        final TypeVariableSource typeVariableSource = genericType.getTypeVariableSource();
        final GenericDeclaration gd;
        if (typeVariableSource instanceof TypeDefinition typeDefinition) {
          gd = Class.forName(typeDefinition.asErasure().getTypeName(), false, Thread.currentThread().getContextClassLoader());
        } else if (typeVariableSource instanceof MethodDescription.InDefinedShape methodDescription) {
          // Reflection time
          final String name = methodDescription.getName();
          final Class<?> cls = Class.forName(methodDescription.getDeclaringType().asErasure().getTypeName(), false, Thread.currentThread().getContextClassLoader());
          final List<? extends TypeDefinition> parameterTypes = methodDescription.getParameters().asTypeList();
          final Class<?>[] parameterClasses = new Class<?>[parameterTypes.size()];
          for (int i = 0; i < parameterTypes.size(); i++) {
            parameterClasses[i] = Class.forName(parameterTypes.get(i).asErasure().getName(), false, Thread.currentThread().getContextClassLoader());
          }
          if (MethodDescription.CONSTRUCTOR_INTERNAL_NAME.equals(name)) {
            assert TypeDescription.VOID.equals(methodDescription.getReturnType());
            gd = cls.getDeclaredConstructor(parameterClasses);
          } else {
            assert !MethodDescription.TYPE_INITIALIZER_INTERNAL_NAME.equals(name);
            gd = cls.getDeclaredMethod(name, parameterClasses);            
          }
        } else {
          throw new IllegalArgumentException("Unexpected type variable source: " + typeVariableSource);
        }
        final TypeVariable<?>[] typeVariables = gd.getTypeParameters();
        TypeVariable<?> temp = null;
        for (final TypeVariable<?> typeVariable : typeVariables) {
          if (typeVariable.getName().equals(genericType.getSymbol())) {
            temp = typeVariable;
            break;
          }
        }
        assert temp != null;
        returnValue = temp;
        break;
      case VARIABLE_SYMBOLIC:
        throw new IllegalArgumentException("Unexpected type: " + type);
      case WILDCARD:
        final List<? extends TypeDefinition> upperBounds = genericType.getUpperBounds();
        final List<? extends TypeDefinition> lowerBounds = genericType.getLowerBounds();
        if (lowerBounds == null || lowerBounds.isEmpty()) {
          if (upperBounds == null || upperBounds.isEmpty() || (upperBounds.size() == 1 && TypeDescription.Generic.OBJECT.equals(upperBounds.get(0)))) {
            returnValue = UnboundedWildcardType.INSTANCE;
          } else {
            // Upper bounded.
            final Type[] upperJavaBounds = new Type[upperBounds.size()];
            for (int i = 0; i < upperBounds.size(); i++) {
              upperJavaBounds[i] = toType(upperBounds.get(i)); // XXX recursive
            }
            returnValue = new UpperBoundedWildcardType(upperJavaBounds);
          }
        } else {
          assert upperBounds == null || upperBounds.isEmpty() || (upperBounds.size() == 1 && TypeDescription.Generic.OBJECT.equals(upperBounds.get(0))) : "Unexpected upper bounds: " + upperBounds + "; lower bounds: " + lowerBounds;
          // Lower bounded.
          assert lowerBounds.size() == 1 : "Unexpected size in lower bounds: " + lowerBounds;
          returnValue = new LowerBoundedWildcardType(toType(lowerBounds.get(0))); // XXX recursive
        }
        break;        
      default:
        throw new IllegalArgumentException("Unexpected type: " + type);
      }
    }
    return returnValue;
  }
拉斐尔·温特豪德

不可以,您只能将a转换Type为a,TypeDescription.Generic但是没有其他选择的方法。最简单的模拟方法可能是定义一个类,该类定义给定的字段Type,以加载该类并使用Java反射读取字段类型。

Byte Buddy无法将描述转换为a的原因Type是Byte Buddy抽象出了类加载器,并且类型变量可能与其声明源分离。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

Related 相关文章

热门标签

归档