0

在 Java 类中可以或不可以有内部接口是否有充分的理由?(就像你会一个内部类)。我无法通过 Google 找到明确的答案,但您似乎无法像使用内部类一样嵌入接口。我的猜测是 Java 的创建者没有看到一个很好的理由让它成为可能,所以它不是,但也许真的有很好的理由?

例如我无法编译它(这都是一个大类)

package buttonGetSourceObject;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ClassWithButton implements ActionListener, ButtonOwner{

    private String objectName = "";

    public ClassWithButton(String string) {
        objectName = string;
        JFrame f = new JFrame();
        JPanel p = new JPanel();
        MyJButton b = new MyJButton(this,"Press This Button for Name of Owner of Button");
        b.addActionListener(this);
        f.add(p);
        p.add(b);
            f.pack();
        f.setVisible(true);


    }

    public static void main(String[] args){
        ClassWithButton c = new ClassWithButton("object1name");
    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        ((ButtonOwner)((MyJButton)arg0.getSource()).getOwner()).printInstanceName();

    }


    public interface ButtonOwner {
        public void printInstanceName();
    }


    private class MyJButton extends JButton {

        /**
         * 
         */
        private static final long serialVersionUID = 1L;
        Object owner = null;

        public Object getOwner() {
            return owner;
        }

        public void setOwner(Object owner) {
            this.owner = owner;
        }

        public MyJButton(Object o, String string){
            owner = o;
            this.setText(string);
        }
    }


   @Override
    public void printInstanceName() {

        System.out.println(this);

    }

    public String getObjectName() {
        return objectName;
    }

    public void setObjectName(String objectName) {
        this.objectName = objectName;
    }

    public String toString(){
        return this.getObjectName();
    }

} //end

编译器似乎根本无法识别内部接口“ButtonOwner”存在

4

2 回答 2

6

因为它是一个内部类,所以您必须使用您要扩展的类的全名(例如使用ClassWithButton.ButtonOwner而不是 just ButtonOwner):

public class ClassWithButton implements ActionListener, ClassWithButton.ButtonOwner

但是,这不起作用,因为您正在扩展内部接口

检测到循环:ClassWithButton 类型无法扩展/实现自身或其自己的成员类型之一

至于为什么一个类不能实现内部接口,对上述问题的评论表明可能是因为:

类加载是如何工作的。对其他类的正常引用是延迟加载的,但外部类、超类和实现的接口会在类本身加载之前自动加载。当您的外部类实现内部接口并且该构造有效时,在运行时加载类时,您会在类加载器中获得 StackOverflowError ...

于 2013-06-08T04:43:56.387 回答
3

这是一个明确的答案:JLS第 9 章

“嵌套接口是其声明出现在另一个类或接口的主体中的任何接口。”

“顶级接口是不是嵌套接口的接口。”

语法在第 18 章

ClassBody: 
    { { ClassBodyDeclaration } }

ClassBodyDeclaration:
    ; 
    {Modifier} MemberDecl
    [static] Block

MemberDecl:
    ...
    InterfaceDeclaration

您的代码无法编译的原因是您试图使外部类成为其自身嵌套接口的子类型。(我找不到禁止这样做的 JLS 部分,但编译器错误消息清楚地表明这是被禁止的。)


我不确定“为什么”他们决定禁止扩展自身内部类或接口的类。可能只是因为他们认为所涉及的规范和实现工作超过了允许它的效用。

(防止类加载期间的解释StackOverflowError不成立:

  • 嵌套类实际上被编译为独立的“.class”文件。
  • JLS 没有指定加载类的顺序。(初始化是另一回事。
  • 根据 JLS,类之间的链接(包括到超类的链接)的解析实际上是在加载类之后发生的。
  • 事实上,无论如何你都可以“实现”这种问题(例如,通过弄乱“.class”文件以在继承图中创建循环)......并且验证器会在它造成任何伤害之前检测到它。)
于 2013-06-08T04:51:06.500 回答