为什么Java泛型类可以用对象参数实现泛型接口的方法?
以下是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{ 无效剂量(
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