Java 泛型 - 使用泛型函数扩展泛型类

标签 java generics

我有一个像这样的简单程序:

package test;

public class TestGenericsInheritance {

    public static void main(String[] args) {}

    public static abstract class A<Q>{

        public void foo2(Q obj){}
        public abstract <T> void foo(T obj);
    }

    public static class C extends A<Object>{

        @Override
        public <T> void foo(T obj) {}
    }

    public static class B extends A{

        @Override
        public <T> void foo(T obj) {}
    }
}

如您所见,它什么都不做。在 java 1.6 和 1.7 上编译此程序文件时出现以下错误:

/D:/Projects/.../test/TestGenericsInheritance.java:[24,19] test.TestGenericsInheritance.B is not abstract and do es not override abstract method foo(java.lang.Object) in test.TestGenericsInheritance.A /D:/Projects/.../test/TestGenericsInheritance.java:[27,25] name clash: foo(T) in test.TestGenericsInheritance .B and foo(T) in test.TestGenericsInheritance.A have the same erasure, yet neither overrides the other /D:/Projects/.../test/TestGenericsInheritance.java:[26,9] method does not override or implement a method from a supertype

C 类和 B 类在语义上是相同的,但是 B 类不将方法 foo 识别为 A#foo 的实现。为了使此代码兼容,我必须在类 B 中使用以下签名实现方法 A#foo:

public void foo(Object obj) 

我的问题是,为什么我的程序无法编译?泛型 Q 和 T 是完全独立的,那么为什么只有在为继承类 A 显式指定泛型 Q 时才可以实现泛型函数 A#foo?

谢谢

最佳答案

B扩展原始类型 A .因为您使用原始类型,所以所有通用信息都将被删除,而不仅仅是您未能指定的类型变量(参见 Section 4.6 of the Java Language Specification )。这意味着 A有一个方法 void foo(Object obj) ,而 A<SomeType>有一个方法 <T> void foo(T obj) .

如果您重写一个方法,它必须具有相同的签名(可选地在对被重写的方法进行类型删除之后)——有趣的是,重写的方法可能具有不同的、更具体的返回类型。您的两种方法的签名不同(您需要在覆盖方法中进行类型删除),因此您的示例无法编译。

按原样实现类型删除的原因是向后兼容。这个想法是新代码只使用泛型,只有旧代码会使用原始类型。因此,目标不是让原始类型最方便(因为无论如何新代码都不应该使用它们),而是让原始类型最兼容。

例如考虑类 ArrayList ,它是在 Java 2 中引入的(远早于泛型)。它有一个方法 public Object[] toArray(Object[] a) .在 Java 5 中引入了泛型,此方法的签名可以更改为 public <T> T[] toArray(T[] a) (其中 T 不是元素类型)毫无困难:由于类型删除的实现方式,对于使用(或子类化)ArrayList 的旧代码而不是 ArrayList<SomeType>方法签名保持不变。

关于Java 泛型 - 使用泛型函数扩展泛型类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38146919/

相关文章:

java - Spring MVC 请求映射 - 完整请求 URI

java - 通过外部 AsyncTask 将项目添加到 Activity 中的 ListView

java - 放心 - 将响应 JSON 反序列化为 List<POJO>

JavaFX - TextArea 的掩码文本

java - 是真假关键字吗?

java - 在tomcat中记录所有请求和响应数据

function - F# 泛型/函数重载语法

swift - 为什么我们在这里需要一个泛型?协议(protocol)还不够吗?

java - 如何摆脱这个泛型警告?

TypeScript 函数,返回与输入相同类型的值