我搜索了其他类似的问题,但我认为它们没有涵盖这个问题.我有以下代码,这会导致编译错误:

// Example 1 (not working)
public interface I<T extends Number> {
    void method(Map<String, String> map, T value);
}

public abstract class A<T extends Number> implements I<T> {
    @Override
    public void method(Map<String, String> map, T value) {}
}

// Note that C doesn't know about the generic type
public class C extends A {
    // Error: name clash: method(Map<String,String>,Number) in C and
    // method(Map,Number) in A have the same erasure, yet neither overrides the other
    @Override
    public void method(Map<String, String> map, Number n) {}
}

我理解类型擦除,但当我"手动"输入擦除时,它可以工作,所以这段代码很好.

// Example 2 (working)
public interface I<T extends Number> {
    void method(Map map, T value);
}

public abstract class A<T extends Number> implements I<T> {
    @Override
    public void method(Map map, T value) {}
}

public class C extends A {
    // No error
    @Override
    public void method(Map map, Number n) {}
}

泛型T大概也不是问题,因为如果我删除Map参数,它就可以工作,所以这也没问题(而且无论如何,错误是关于Map而不是泛型类型,所以这并不奇怪):

// Example 3 (working)
public interface I<T extends Number> {
    void method(T value);
}

public abstract class A<T extends Number> implements I<T> {
    @Override
    public void method(T value) {}
}

public class C extends A {
    // No error
    @Override
    public void method(Number n) {}
}

但是删除type参数也可以修复它,所以我想问题也不是映射:

// Example 4 (working)
public interface I {
    void method(Map<String, String> map);
}

public abstract class A implements I {
    @Override
    public void method(Map<String, String> map) {}
}

public class C extends A {
    @Override
    public void method(Map<String, String> map) {}
}

这是一个小例子,但它突然出现是因为我试图在不需要更改C的情况下将泛型类型T添加到接口中,而C是在我不受控制的代码中实现的,所以不能用C以不兼容的方式更改I或A,但我希望能够在进行升级的类中使用泛型来使用泛型.不过,我认为这会起作用,并且使用现有类型添加带有约束的泛型将是一种向后兼容的更改,在大多数情况下确实如此,因为遵循示例3中形式的方法工作得很好.

无论如何,我不确定这里的错误到底是什么,因为示例3工作,任何关于一般形式无效的理论似乎都是不正确的,但是因为示例2工作,它也感觉这与类型擦除无关,但也许是泛型和类型擦除之间的一些有趣的交互,我不知道.

推荐答案

这并不理想,但您可以解决第一个示例中的问题,方法是将A一分为二,留下A个没有泛型定义,并添加一个处理泛型的新超类型:

// Rename A as SuperA
public class SuperA<T extends Number> implements I<T> {
    @Override
    public void method(Map<String, String> map, T value) {}
}
// Insert new A which hasn't got the generic A<T> but declares T as Number for C
public class A extends ASuper<Number> {
    @Override
    public void method(Map<String, String> map, Number value) {}
}

这样做的效果是为您说不能更改的类C提供正确的类型Number.

显然,这可能会对可能使用A的其他代码产生一些影响,因为A的定义与以前不太一样.

Java相关问答推荐

ActivityCompat.请求收件箱自动拒绝权限

找到允许的最大底片

Cucumber TestNG Assert失败,出现java. lang. Numbercycle异常

从技术上讲,OPC UA客户端是否可以通过转发代理将请求通过 tunel 发送到OPC UA服务器?

Java inline Double条件和值解装箱崩溃

通过合并Akka Streams中的多个慢源保持订购

FALSE:它应该在什么时候使用?

基于调车场算法的科学计算器

将java.util.Date转换为OffsetDateTime

JDK 21-为什么线程局部随机S nextInt不直接用Super.nextInt实现?

通过Spring Security公开Spring Boot执行器端点

使用Room Database删除Jetpack合成中的所有项目后,UI未重新合成

如何在Cosmos DB(Java SDK)中增加默认响应大小

Groovy/Java:匹配带引号的命令选项

如果List是一个抽象接口,那么Collectors.toList()如何处理流呢?

组合连接以从两个表返回数据

IntelliJ IDEA中的JavaFX应用程序无法在资源中找到CSS文件

在应用程序运行时更改LookAndFeel

如何使用WebEnvironment.RANDOM_PORT获得第二个随机端口?

在WHILE()循环初始化部分中声明和初始化变量的Java语法?