Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/391.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何获取形式方法参数类型的参数?_Java_Reflection_Guava_Type Erasure - Fatal编程技术网

Java 如何获取形式方法参数类型的参数?

Java 如何获取形式方法参数类型的参数?,java,reflection,guava,type-erasure,Java,Reflection,Guava,Type Erasure,我有一些方法只包含一个类型为Event的参数,需要提取Something或其原始类型。看起来像 void method1(Event<MyEnum1> event) {} <E extends Enum<E>> method2(Event<E> event) {} <K, V> method3(Event<Map<K, V>> event) {} 对于method1,使用(ParameterizedTyp

我有一些方法只包含一个类型为
Event
的参数,需要提取
Something
或其原始类型。看起来像

 void method1(Event<MyEnum1> event) {}
 <E extends Enum<E>> method2(Event<E> event) {}
 <K, V> method3(Event<Map<K, V>> event) {}
对于
method1
,使用
(ParameterizedType)方法很容易。getGenericParameterTypes()
。对于
方法2
,我可以使用番石榴

TypeToken.of(method.getDeclaringClass())
    .method(method)
    .getTypeParameters()[0]
    .getBounds()
要获取
类型

TypeToken.of(method.getDeclaringClass())
    .method(method)
    .getParameters()
    .get(0)
获取
参数
。我想,我需要使用
类型
解析
参数
,但我被困在这里了


我不太关心
方法3
,尽管知道一个通用方法会很好。我不关心实际参数的类型(我知道会被擦除)。

您不需要
TypeToken
java.lang.reflect
提供您所需的一切

你需要考虑多个病例。我将假设提供的任何方法的第一个参数始终是
Event
类型(或者实际上是参数化类型)

您将需要处理的5个子类型。从示例中,您需要检查类型参数是具体类型(
MyEnum
)、类型变量(
E
Enum
为界)还是参数化类型(
Map

此外,还有
WildcardType
,您可以像处理类型变量一样处理它并提取边界。最后,您必须使用
genericaraytype
Event
Event
)处理泛型数组类型。我忽略了这些,但它只是对其他类型重新应用相同的规则

我假设,对于类型变量的情况,边界可能是其他类型变量,因此我们需要重复出现,直到找到具体的边界

// get raw type argument of first parameter
public static Class<?> getRawTypeArgument(Method method) {
    Parameter parameter = method.getParameters()[0];
    Type type = parameter.getParameterizedType();
    /// assume it's parameterized
    ParameterizedType parameterizedType = (ParameterizedType) type;
    // assume there's one type argument
    Type typeArgument = parameterizedType.getActualTypeArguments()[0];
    if (typeArgument instanceof TypeVariable<?>) {
        TypeVariable<?> typeVariableArgument = (TypeVariable<?>) typeArgument;
        return recursivelyExtractBound(typeVariableArgument);
    } else if (typeArgument instanceof Class<?>) {
        return (Class<?>) typeArgument;
    } else if (typeArgument instanceof ParameterizedType) {
        ParameterizedType parameterizedTypeArgument = (ParameterizedType) typeArgument;
        return (Class<?>) parameterizedTypeArgument.getRawType();
    } 
    throw new AssertionError("Consider wildcard and generic type");
}

private static Class<?> recursivelyExtractBound(TypeVariable<?> typeVariable) {
    // assume first
    Type bound = typeVariable.getBounds()[0];
    if (bound instanceof Class<?>) {
        return (Class<?>) bound;
    } else if (bound instanceof TypeVariable<?>) {
        TypeVariable<?> nested = (TypeVariable<?>) bound;
        return recursivelyExtractBound(nested);
    } else if (bound instanceof ParameterizedType) {
        ParameterizedType parameterizedTypeArgument = (ParameterizedType) bound;
        return (Class<?>) parameterizedTypeArgument.getRawType();
    }
    throw new AssertionError("Are there others?");
}

这真是太棒了!但是,我只需将
IllegalStateException
更改为
AssertionError
。因为是你作为程序员断言没有其他可覆盖的案例。另外,最重要的是被调用对象的状态,这里被调用的方法是静态的。静态和状态通常不能很好地结合;)@OlivierGrégoire是的。@OlivierGrégoire我不确定这个变化。如果存在,我更喜欢断言RuntimeException。
AssertionError
可能会滑倒抛出捕捉并导致问题。。。或许不是;番石榴的人也用它。@maaartinus程序员不仅陈述了一些东西,而且强烈地这样做了。结果证明是假的。我不认为这是一个例外,而是一个错误!甚至Josh Bloch也在这样的场景中使用了它(有效Java,第二版,第4、7项和其他几个项目,包括20项,它们与这个答案的场景非常相似)。如果有人知道我失败的原因,可能会很有趣。正如公认的答案所示,这其实很简单。我的问题是,我发现
typeArgument
typevariableempl
,在Eclipse中打开它,发现它是私有的,没有实现任何接口(这是不可能的,因为它是
类型,但我错过了它)。相关的类是
sun.reflect.generics.reflectiveObjects.TypeVariableImpl
(sources.jar中缺少),而不是我所看到的那个类。
// get raw type argument of first parameter
public static Class<?> getRawTypeArgument(Method method) {
    Parameter parameter = method.getParameters()[0];
    Type type = parameter.getParameterizedType();
    /// assume it's parameterized
    ParameterizedType parameterizedType = (ParameterizedType) type;
    // assume there's one type argument
    Type typeArgument = parameterizedType.getActualTypeArguments()[0];
    if (typeArgument instanceof TypeVariable<?>) {
        TypeVariable<?> typeVariableArgument = (TypeVariable<?>) typeArgument;
        return recursivelyExtractBound(typeVariableArgument);
    } else if (typeArgument instanceof Class<?>) {
        return (Class<?>) typeArgument;
    } else if (typeArgument instanceof ParameterizedType) {
        ParameterizedType parameterizedTypeArgument = (ParameterizedType) typeArgument;
        return (Class<?>) parameterizedTypeArgument.getRawType();
    } 
    throw new AssertionError("Consider wildcard and generic type");
}

private static Class<?> recursivelyExtractBound(TypeVariable<?> typeVariable) {
    // assume first
    Type bound = typeVariable.getBounds()[0];
    if (bound instanceof Class<?>) {
        return (Class<?>) bound;
    } else if (bound instanceof TypeVariable<?>) {
        TypeVariable<?> nested = (TypeVariable<?>) bound;
        return recursivelyExtractBound(nested);
    } else if (bound instanceof ParameterizedType) {
        ParameterizedType parameterizedTypeArgument = (ParameterizedType) bound;
        return (Class<?>) parameterizedTypeArgument.getRawType();
    }
    throw new AssertionError("Are there others?");
}
public static void main(String[] args) throws Exception {
    Class<?> clazz = Example.class;
    for (Method method : clazz.getDeclaredMethods()) {
        if (!method.getName().startsWith("method")) {
            continue;
        }
        System.out.println("Method '" + method + "' -> " + getRawTypeArgument(method));
    }
}
Method 'java.lang.Object com.example.Example.method3(com.example.root.Event)' -> interface java.util.Map
Method 'java.lang.Object com.example.Example.method2(com.example.root.Event)' -> class java.lang.Enum
Method 'void com.example.Example.method1(com.example.Event)' -> class com.example.MyEnum1