静态泛型方法

2022-09-01 13:09:44

您能解释一下为什么以下工作吗?

public class GenericsTest<T> {

    public void doSomething(T v1, T v2) {

    }

    public static <T> void doSomethingStatic(T v1, T v2) {

    }

    public static <T> void doSomethingStaticList(List<T> v1, List<T> v2)
    {

    }

    public static void main(String[] args) {
        GenericsTest<String> gt = new GenericsTest<>();

        // OK
        gt.doSomething("abc", "abc");

        // Not OK
        gt.doSomething(1, "abc");

        // OK
        doSomethingStatic(1, 2);

        // Still OK
        doSomethingStatic(1, "abc");

        // So why is this not OK?
        List<String> list1=new LinkedList<>();
        List<Integer> list2=new LinkedList<>();
        doSomethingStaticList(list1,list2);
    }
}

T v1, T v2应该是相同的类型,但我仍然能够传递不同的类型(整数和字符串)。doSomethingStatic

如果默认采用通用超类,为什么不能与不同的类型一起使用?doSomethingStatic()doSomethingStaticList()


答案 1

在非静态情况下,定义为 创建 的实例时。因此,传递一个将给出编译错误。如果你这样做,它也会失败。TStringGenericsTestintgt.doSomething(1, 2)

在静态情况下,您不需要手动定义,它是从参数派生的。它将是两个类的第一个公共超类 - 在本例中是 。您可能希望使用有界通配符,例如 或。TObject<T extends Number><T extends CharSequence>

请注意,您在这里有两个不同的:T

  • GenericsTest<T>
  • public static <T> void doSomethingStatic(T v1, T v2)

泛型参数的声明是每当您编写 .在这种情况下,您可以使用不同的字母以避免混淆。<T>


答案 2

这之所以有效,是因为在静态方法中是他自己的类型参数,而不是在成员方法中使用的参数。重命名它以澄清:TT

public static class GenericsTest<T> {

    public void doSomething(T v1, T v2) {

    }

    public static <V> void doSomethingStatic(V v1, V v2) {

    }
//...

因此,如果您的实例类型参数值是,则这是一个错误。在类型参数的静态值不同的情况下:doSomething(...)StringdoSomethingStatic(...)

GenericsTest.doSomethingStatic(1, "abc"); //ok
GenericsTest.<Object>doSomethingStatic(1, "abc"); //ok
GenericsTest.<String>doSomethingStatic(1, "abc"); //not ok
new GenericsTest<String>().doSomething(1, "abc"); //not ok

推荐