接口内的内部类


97

是否可以在接口创建内部类
如果可能的话,由于我们不打算创建任何接口对象,为什么还要创建一个内部类呢?

这些内部类在任何开发过程中都有帮助吗?

Answers:


51

是的,您可以在Java接口内创建嵌套类或内部类(请注意,与普遍看法相反,没有“ 静态内部类 ”之类的东西:这根本没有意义,没有“内部”也没有“嵌套类是静态的,因此它不能是“静态内部”)。

无论如何,以下代码可以正常编译:

public interface A {
    class B {
    }
}

我已经看到它曾经在接口定义中直接放置了某种“合同检查器”(好吧,在嵌套在接口中的类中,它可以具有静态方法,而与接口本身相反,而不能)。如果我没记错的话,看起来像这样。

public interface A {
    static class B {
        public static boolean verifyState( A a ) {
            return (true if object implementing class A looks to be in a valid state)
        }
    }
}

请注意,我没有评论这种事情的用处,我只是在回答您的问题:它可以完成,这是我见过的一种用法。

现在,我不会评论这种构造的有用性,并且从我已经看到的内容:我已经看到了,但是它不是很常见的构造。

200KLOC代码库在这里发生的时间恰好是零时间(但是,我们还有很多其他事情,我们认为不良行为也恰好发生在零时间,所以其他人也会发现这很正常)。


您可以添加一些用法示例吗?一段时间前,我已经测试过类似的东西,但我不了解使用这种结构能获得什么。
罗马2010年

@罗马:好吧,我记得我在某个项目上遇到过这个问题(我会添加相对干净的项目,但它们不是我的),但是我不知道它是否真的干净。我添加了一个很小的例子,看起来像我所看到的,但是再一次:这不是我的代码,并且我没有使用该构造,所以我不是最有资格提出有效例子的:) IIRC内部的类总是被命名,例如StateChecker,并且调用总是看起来像:A.StateChecker.check(a)或类似的东西。
语法T3rr0r,2010年

8
如果您说“没有“ 静态内部类 ”之类的东西”,那么您的回答“您可以在Java接口内创建嵌套类或内部类”根本就是错误的。使用缩小的定义,interfaces 不能具有内部类。您可以省略嵌套类的static修饰符,interface但仍然是嵌套类,而不是内部类。
Holger 2014年

6
这个答案是错误的。接口可以具有静态嵌套类,但不能具有内部类。
Paul Boddington,2015年

1
@PaulBoddington你是对的。即使删除“ static”,B该类也是静态嵌套类,而不是内部类。接口得到特殊处理。除了规范本身之外,我在网上找不到这方面的内容:“接口的成员类是隐式静态的,因此永远不被视为内部类。” docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3
Max Barraclough

109

是的,我们可以在接口内部有类。用法的一个例子可能是

public interface Input
{
    public static class KeyEvent {
         public static final int KEY_DOWN = 0;
         public static final int KEY_UP = 1;
         public int type;
         public int keyCode;
         public char keyChar;
    }
    public static class TouchEvent {
         public static final int TOUCH_DOWN = 0;
         public static final int TOUCH_UP = 1;
         public static final int TOUCH_DRAGGED = 2;
         public int type;
         public int x, y;
         public int pointer;
    }
    public boolean isKeyPressed(int keyCode);
    public boolean isTouchDown(int pointer);
    public int getTouchX(int pointer);
    public int getTouchY(int pointer);
    public float getAccelX();
    public float getAccelY();
    public float getAccelZ();
    public List<KeyEvent> getKeyEvents();
    public List<TouchEvent> getTouchEvents();
}

这里的代码有两个嵌套的类,用于封装有关事件对象的信息,这些信息随后在诸如getKeyEvents()的方法定义中使用。将它们包含在Input接口中可以提高凝聚力。


3
@Levit只是想知道,实现的类是什么样子?
过度兑换

1
希望看到上述用法的实际实现。谢谢。
2013年

45

有效的使用,恕我直言,正在定义由封闭的接口方法接收或返回的对象。通常是数据保存结构。这样,如果该对象仅用于该接口,那么您将拥有更紧密结合的方式。

例如:

interface UserChecker {
   Ticket validateUser(Credentials credentials);

   class Credentials {
      // user and password
   }

   class Ticket {
      // some obscure implementation
   }
}

但是无论如何……这只是口味的问题。


35

引用Java 7规范

接口可能包含成员类型声明(第8.5节)。

接口中的成员类型声明是隐式静态的和公共的。可以冗余地指定这两个修饰符之一或全部。

无法在Java接口中声明非静态类,这对我来说很有意义。


谢谢。这可能是所有问题中最简洁的答案。
约瑟夫

1
这是我一直在寻找的答案..但是,OP提出了几个问题..无论如何,我对此表示怀疑。
查理·华莱士


7

当然是有可能的,我发现它有用的一种情况是接口必须引发自定义异常。您将异常与它们的关联接口保持在一起,我认为这通常比将琐碎的异常文件堆堆满源代码树更整洁。

interface MyInterface {

   public static class MyInterfaceException extends Exception {
   }

   void doSomething() throws MyInterfaceException;
}

7

是的,可以在接口中包含静态类定义,但是此功能最有用的方面可能是在使用枚举类型(这是静态类的特殊类型)时。例如,您可以具有以下内容:

public interface User {
    public enum Role {
        ADMIN("administrator"),
        EDITOR("editor"),
        VANILLA("regular user");

        private String description;

        private Role(String description) {
            this.description = description;
        }

        public String getDescription() {
            return description;
        }
    }

    public String getName();
    public void setName(String name);
    public Role getRole();
    public void setRole(Role role);
    ...
}


1

也许当您想要更复杂的构造(例如某些不同的实现行为)时,请考虑:

public interface A {
    public void foo();

    public static class B implements A {
        @Override
        public void foo() {
            System.out.println("B foo");
        }
    }
}

这是您的界面,这将是实现者:

public class C implements A {
    @Override
    public void foo() {
        A.B b = new A.B();
        b.foo(); 
    }

    public static void main(String[] strings) {
        C c = new C();
        c.foo();
    }
}

可能会提供一些静态实现,但我不知道这不会造成混淆。


0

我发现这种结构可以使用。

  1. 您可以使用此构造来定义和分组所有静态最终常量。
  2. 既然是接口,则可以在类上实现它。

您可以访问所有分组的常量。在这种情况下,类的名称充当名称空间。


0

您还可以为实现此接口的对象的常用功能创建“ Helper”静态类:

public interface A {
    static class Helper {
        public static void commonlyUsedMethod( A a ) {
           ...
        }
    }
}

0

我现在需要一个。我有一个接口,可以方便地从多个方法中返回一个唯一的类。此类仅作为该接口方法的响应的容器才有意义。

因此,拥有一个仅与该接口相关联的静态嵌套类定义会很方便,因为该接口应该是创建此结果容器类的唯一位置。


0

例如,Groovy中的特征(类似具有实现方法的接口)。它们被编译为一个接口,该接口包含内部类,所有方法都在其中实现。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.