Class中getConstructors()的泛型类型

And*_*nek 11 java generics reflection

在泛型类中,Class<T>该方法getConstructors()具有返回类型,而不是泛型类型参数T.其原因在于javadoc中的解释.

请注意,虽然此方法返回一个Constructor<T>对象数组(即此类中的构造函数数组),但此方法的返回类型Constructor<?>[]并非Constructor<T>[]如预期的那样.这个信息量较少的返回类型是必需的,因为从此方法返回后,可以修改数组以保存不同类的Constructor对象,这将违反类型保证Constructor<T>[].

我的一位同事和我试图理解这个解释.在我们的理解中,他们基本上说它是未知的泛型类型,因为一些调用者可以将其他Constructor对象放入该数组中.我们做对了吗?如果是这样,为什么有人会这样设计API.使用特定类型并信任程序员正确使用数组不是更好吗?对我们来说,这听起来有点像"我们正在制作更糟糕的API,因为程序员使用它可能会尝试一些愚蠢的东西".我们的谬误在哪里?

Mar*_*o13 3

Ashu Pachauri 在评论中提到的观点(即返回数组是为了向后兼容)当然是有效的。一般来说,数组和泛型不能很好地协同工作。(要获得证据,请查找与“通用数组”相关的所有 stackoverflow 问题...)

此外,还有一条规则是 API 应该易于使用难以滥用在这种情况下,这与最小惊讶原则有关:使用此方法获取构造函数的人可以对返回的数组执行完全合法的操作序列,并最终收到意外的ClassCastException. 因此,可以说返回数组这一事实Constructor<?>[]旨在实现“快速失败”行为。

一个说明性的例子:

import java.lang.reflect.Constructor;

public class GetConstructorsReturnType
{
    public static void main(String[] args) throws Exception
    {
        // This causes a warning, due to the cast, but imagine
        // this was possible
        Constructor<DerivedA> constructorsA[] =
            (Constructor<DerivedA>[])DerivedA.class.getConstructors();

        // The following lines are valid due to the subtype
        // relationship, but would not be valid if constructorsA
        // was declared as "Constructor<?>"
        Constructor<? extends Base> constructors[] = constructorsA;
        constructors[0] = DerivedB.class.getConstructor();

        // This causes a ClassCastException (and would also not
        // be possible constructorsA was declared as "Constructor<?>"
        DerivedA instance = constructorsA[0].newInstance();
    }
}
class Base
{
}
class DerivedA extends Base
{
    public DerivedA()
    {
    }
}
class DerivedB extends Base
{
    public DerivedB()
    {
    }
}
Run Code Online (Sandbox Code Playgroud)