【问题标题】:Is there a good reason why you can or cannot have an inner interface within a Java class? [closed]在 Java 类中可以或不可以有内部接口是否有充分的理由? [关闭]
【发布时间】:2013-06-08 04:21:43
【问题描述】:

在 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”存在

【问题讨论】:

  • 您发现嵌套接口的哪些方面是不可能的(对于嵌套类恰好可能)?
  • 你可以有内部接口(类内部的接口)。您是指接口中的接口吗?
  • 我很确定我的 IDE (Eclipse Juno) 在我尝试这样做时会失败。此外,我在谷歌上找不到任何证据支持您可以嵌套接口的信念(或者不是,也没有任何证据)。
  • 我的意思是类内部的接口。
  • 您的问题“为什么可以或不能”完全没有意义。

标签: java interface inner-classes


【解决方案1】:

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

public class ClassWithButton implements ActionListener, ClassWithButton.ButtonOwner

但是这行不通,因为您正在扩展 inner interface:

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

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

类加载的工作原理。对其他类的正常引用是延迟加载的,但外部类、超类和实现的接口会在类本身加载之前自动加载。如果你的外部类实现了一个内部接口并且该构造是有效的,那么在运行时加载类时你会在类加载器中得到一个 StackOverflowError ......

【讨论】:

  • +1 这是唯一真正回答 OP 的“为什么?”问题的答案。其他答案只是说“编译器说不”
  • 这个推理(支持所谓的“为什么”)是不正确的。如果他们愿意,他们本可以让它发挥作用。事实上,类加载的顺序……或者加载是急切的还是惰性的……在JLS中没有指定。 (指定了类初始化的顺序,但这是不同的过程。)(以及超类型引用的解析等,是在类加载之后发生的链接过程的一部分......根据 JLS。)
  • (另一个挑剔 - 嵌套接口不是“内部”。根据 JLS,嵌套接口隐式为 static。)
【解决方案2】:

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

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

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

而且语法在Chapter 18:

ClassBody: 
    { { ClassBodyDeclaration } }

ClassBodyDeclaration:
    ; 
    {Modifier} MemberDecl
    [static] Block

MemberDecl:
    ...
    InterfaceDeclaration

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


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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-16
    • 2021-08-21
    • 2020-10-31
    • 2019-12-09
    相关资源
    最近更新 更多