为什么Java泛型类可以用对象参数实现泛型接口的方法?

为什么Java泛型类可以用对象参数实现泛型接口的方法?,java,generics,interface,Java,Generics,Interface,以下是Java代码: public interface myInterface<T> { void doSomething(T yes); } private static class myInterfaceImpl<T> implements myInterface<T>{ @Override public void doSomething(Object yes) { } } 公共接口myInterface{ 无效剂量(

以下是Java代码:

public interface myInterface<T> {
    void doSomething(T yes);
}

private static class myInterfaceImpl<T> implements myInterface<T>{
    @Override
    public void doSomething(Object yes) {

    }
}
公共接口myInterface{
无效剂量(T是);
}
私有静态类myInterfaceImpl实现myInterface{
@凌驾
公共无效剂量测定(对象是){
}
}
即使我认为该类没有从接口重写该方法,它还是可以编译。通过类型推断,我假设类型参数T始终等于Object,因为类从接口实现方法,在接口中将Object明确声明为参数。重写方法中带有(T yes)的版本也可以工作,但这对我来说是显而易见的。你能告诉我为什么我举的例子就是这样吗

谢谢。

我可能已经找到了:

在类型擦除过程中,如果类型参数有界,Java编译器将擦除所有类型参数,并用其第一个界替换每个类型参数;如果类型参数无界,则用对象替换每个类型参数

考虑以下表示单链表中节点的泛型类:

public class Node<T> {

    private T data;
    private Node<T> next;

    public Node(T data, Node<T> next) {
        this.data = data;
        this.next = next;
    }

    public T getData() { return data; }
    // ...
}
在以下示例中,泛型节点类使用有界类型参数:

public class Node<T extends Comparable<T>> {

    private T data;
    private Node<T> next;

    public Node(T data, Node<T> next) {
        this.data = data;
        this.next = next;
    }

    public T getData() { return data; }
    // ...
}
谢谢@Oleksandr。我可能已经找到了:

在类型擦除过程中,如果类型参数有界,Java编译器将擦除所有类型参数,并用其第一个界替换每个类型参数;如果类型参数无界,则用对象替换每个类型参数

考虑以下表示单链表中节点的泛型类:

public class Node<T> {

    private T data;
    private Node<T> next;

    public Node(T data, Node<T> next) {
        this.data = data;
        this.next = next;
    }

    public T getData() { return data; }
    // ...
}
在以下示例中,泛型节点类使用有界类型参数:

public class Node<T extends Comparable<T>> {

    private T data;
    private Node<T> next;

    public Node(T data, Node<T> next) {
        this.data = data;
        this.next = next;
    }

    public T getData() { return data; }
    // ...
}

谢谢@Oleksandr。

所以你偶然发现了协方差和逆变。 假设你有:

IMyInterface<T> {
  void foo(T o);
}
IMyInterface{
void foo(to);
}
你实现了吗

class A implements IMyInterface<Integer> {
  void foo(Integer o) { ... }
}
A类实现IMI接口{
void foo(整数o){…}
}
您也可以编写以下内容之一:

class A implements IMyInterface<Integer> {
  void foo(Number o) { ... }
}

class A implements IMyInterface<Integer> {
  void foo(Object o) { ... }
}
A类实现IMI接口{
void foo(数字o){…}
}
类实现IMyInterface{
void foo(对象o){…}
}
因为类型T的参数o保证为整数 ->o也保证是数字或对象 ->因为整数扩展数字扩展对象

所以你在削弱这种类型!
这就是你的代码所做的。

所以你偶然发现了协方差和逆变。 假设你有:

IMyInterface<T> {
  void foo(T o);
}
IMyInterface{
void foo(to);
}
你实现了吗

class A implements IMyInterface<Integer> {
  void foo(Integer o) { ... }
}
A类实现IMI接口{
void foo(整数o){…}
}
您也可以编写以下内容之一:

class A implements IMyInterface<Integer> {
  void foo(Number o) { ... }
}

class A implements IMyInterface<Integer> {
  void foo(Object o) { ... }
}
A类实现IMI接口{
void foo(数字o){…}
}
类实现IMyInterface{
void foo(对象o){…}
}
因为类型T的参数o保证为整数 ->o也保证是数字或对象 ->因为整数扩展数字扩展对象

所以你在削弱这种类型!
这就是您的代码所做的。

这就是类型擦除(Java在JDK 1.5中引入泛型时用于向后兼容的机制)使事情变得有点不直观的地方

通常人们会期望重写方法的签名必须完全匹配。事实并非如此。虽然完全匹配签名肯定会覆盖该方法,但签名的擦除也会覆盖该方法。报告指出:

在类C中声明或由类C继承的实例方法mC重写了在类A中声明的另一个方法mA,如果以下所有条件均为真:

--剪断

mC的签名是mA签名的子签名(§8.4.2)

并指出:

方法m1的签名是方法m2签名的子签名,如果:

  • m2与m1具有相同的签名,或

  • m1的签名与m2签名的删除(§4.6)相同

由于对
T
的擦除是
对象
,因此允许使用接受
对象
的方法重写(此处实现)该方法。如果在界面中的
T
上设置了上限,则不能再使用
Object
覆盖该方法;这一定是上界,即擦除

// Example of erasure with upper bound
interface myInterface<T extends Number> {
    void doSomething(T yes);
}

class myInterfaceImpl<T extends Number> implements myInterface<T>{
    @Override
    public void doSomething(Number yes) {

    }
}

这就是类型擦除(Java在JDK1.5中引入泛型时用于向后兼容的机制)让事情变得有点不直观的地方

通常人们会期望重写方法的签名必须完全匹配。事实并非如此。虽然完全匹配签名肯定会覆盖该方法,但签名的擦除也会覆盖该方法。报告指出:

在类C中声明或由类C继承的实例方法mC重写了在类A中声明的另一个方法mA,如果以下所有条件均为真:

--剪断

mC的签名是mA签名的子签名(§8.4.2)

并指出:

方法m1的签名是方法m2签名的子签名,如果:

  • m2与m1具有相同的签名,或

  • m1的签名与m2签名的删除(§4.6)相同

由于对
T
的擦除是
对象
,因此允许使用接受
对象
的方法重写(此处实现)该方法。如果在界面中的
T
上设置了上限,则不能再使用
Object
覆盖该方法;这一定是上界,即擦除

// Example of erasure with upper bound
interface myInterface<T extends Number> {
    void doSomething(T yes);
}

class myInterfaceImpl<T extends Number> implements myInterface<T>{
    @Override
    public void doSomething(Number yes) {

    }
}

我认为类没有从接口重写方法--为什么你这么认为?我认为类没有从接口重写方法--为什么你这么认为?这是完美的解释。谢谢你能肯定这个矛盾吗?通常允许覆盖接受supert