为什么这个泛型方法的重写适用于 1.6,但不适用于 1.7?

发布于 2024-12-05 16:18:07 字数 2018 浏览 0 评论 0原文

给定以下类,它重写 AbstractListModel 中的 getListeners 方法:

import java.util.EventListener;
import javax.swing.AbstractListModel;

public class GenericBug extends AbstractListModel {

/**
 * This is the method of interest
     * This is the exact same method signature that is present in the base class
 */
@Override
public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
    // do something useful here...
    return super.getListeners(listenerType);
}

// Not important here
@Override
public int getSize() {
    return 0;
}
@Override
public Object getElementAt(int index) {
    return null;
}
}

该类使用 Oracle 1.6 JDK 可以正常编译。使用 Oracle 1.7 JDK 尝试完全相同的类,我收到编译错误,指出存在名称冲突,但该方法没有被覆盖(但它是!!)

这是我使用 JDK7 时收到的错误:

% /usr/java/jdk1.7.0/bin/javac GenericBug.java
GenericBug.java:10: error: name clash: <T#1>getListeners(Class<T#1>) in GenericBug and <T#2>getListeners(Class<T#2>) in AbstractListModel have the same erasure, yet neither overrides the other
        public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
                                             ^
  where T#1,T#2 are type-variables:
    T#1 extends EventListener declared in method <T#1>getListeners(Class<T#1>)
    T#2 extends EventListener declared in method <T#2>getListeners(Class<T#2>)
GenericBug.java:12: error: incompatible types
                return super.getListeners(listenerType);
                                         ^
  required: T[]
  found:    EventListener[]
  where T is a type-variable:
    T extends EventListener declared in method <T>getListeners(Class<T>)
GenericBug.java:9: error: method does not override or implement a method from a supertype
        @Override
        ^
Note: GenericBug.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
3 errors

有人可以解释吗对我来说发生了什么事?这是 JDK1.7 中的编译器错误,还是我遗漏了什么?

Given the following class, which overrides the getListeners method from AbstractListModel:

import java.util.EventListener;
import javax.swing.AbstractListModel;

public class GenericBug extends AbstractListModel {

/**
 * This is the method of interest
     * This is the exact same method signature that is present in the base class
 */
@Override
public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
    // do something useful here...
    return super.getListeners(listenerType);
}

// Not important here
@Override
public int getSize() {
    return 0;
}
@Override
public Object getElementAt(int index) {
    return null;
}
}

This class compiles fine using an Oracle 1.6 JDK. Trying the exact same class using an Oracle 1.7 JDK, I get compile errors saying there is a name clash, but the method isn't overridden (but it is!!)

Here is the error I get when I use JDK7:

% /usr/java/jdk1.7.0/bin/javac GenericBug.java
GenericBug.java:10: error: name clash: <T#1>getListeners(Class<T#1>) in GenericBug and <T#2>getListeners(Class<T#2>) in AbstractListModel have the same erasure, yet neither overrides the other
        public <T extends EventListener> T[] getListeners(Class<T> listenerType) {
                                             ^
  where T#1,T#2 are type-variables:
    T#1 extends EventListener declared in method <T#1>getListeners(Class<T#1>)
    T#2 extends EventListener declared in method <T#2>getListeners(Class<T#2>)
GenericBug.java:12: error: incompatible types
                return super.getListeners(listenerType);
                                         ^
  required: T[]
  found:    EventListener[]
  where T is a type-variable:
    T extends EventListener declared in method <T>getListeners(Class<T>)
GenericBug.java:9: error: method does not override or implement a method from a supertype
        @Override
        ^
Note: GenericBug.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
3 errors

Can someone explain to me what is happening? Is this a compiler bug in JDK1.7, or am I missing something?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

海的爱人是光 2024-12-12 16:18:07

首先,AbstractListModel 是通用的,您不应该原始继承它。如果

class GenericBug extends AbstractListModel<Something>

代码编译通过。

现在它是原始遗传的,那么发生了什么?原始类型的实例方法也会被擦除 [4.8],因此原始 AbstractListModel 有一个方法

public EventListener[] getListeners(Class listenerType)

子类中的 GenericBug.getListeners 方法不会重写此方法[8.4。 8.1]。

这是基于 JLS3 的,Javac 6 应该遵循 JLS3。所以这肯定是 Javac6 的 bug。

看来 javac 7 重写了类型系统算法,并取得了更好的结果。

JSL3: http://java.sun.com/docs/books /jls/third_edition/html/j3TOC.html

First of all, AbstractListModel is generic, you should not inherit it raw. If

class GenericBug extends AbstractListModel<Something>

the code compiles.

Now it is inherited raw, so what's happening? A raw type's instance methods all undergo erasure too [4.8], so the raw AbstractListModel has a method

public EventListener[] getListeners(Class listenerType)

The GenericBug.getListeners method in the subclass does not override this method[8.4.8.1].

This is based on JLS3, which Javac 6 should follow. So it must have been a Javac6 bug.

It appears that javac 7 has rewritten the type system algorithms, with a much better result.

JSL3: http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文