您是否有充分的理由可以在Java类中拥有或不具有内部接口?

时间:2013-06-08 04:21:44

标签: java interface inner-classes

您是否有充分的理由可以在Java类中拥有或不具有内部接口? (就像你会内心一样)。我无法找到谷歌的确切答案,但看起来好像你不能像使用内部类一样嵌入界面。我的猜测是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”识别为存在于所有

2 个答案:

答案 0 :(得分:5)

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

public class ClassWithButton implements ActionListener, ClassWithButton.ButtonOwner

然而,这不起作用,因为您正在扩展inner interface

  

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

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

  

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

答案 1 :(得分:3)

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

  

“嵌套接口是任何接口,其声明发生在另一个类或接口的主体内。”

     

“顶级界面是不是嵌套界面的界面。”

语法在Chapter 18

ClassBody: 
    { { ClassBodyDeclaration } }

ClassBodyDeclaration:
    ; 
    {Modifier} MemberDecl
    [static] Block

MemberDecl:
    ...
    InterfaceDeclaration

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


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

(在课堂加载过程中防止StackOverflowError的解释并不成立:

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