답변:
예, Java 인터페이스 내에 중첩 된 클래스 또는 내부 클래스를 모두 만들 수 있습니다 (일반적인 믿음과는 반대로 " 정적 내부 클래스 " 와 같은 것은 없습니다 . 이것은 단순히 말이되지 않고 "내부"도없고 "도 없습니다. outter "클래스는 중첩 된 클래스가 정적이므로"정적 내부 "일 수 없습니다.
어쨌든 다음은 잘 컴파일됩니다.
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 코드베이스에서 이것이 정확히 제로 시간에 발생합니다 (하지만 우리는 다른 사람들이 완벽하게 정상이라고 생각할 정도로 정확히 제로 시간이 발생하는 나쁜 관행을 고려하는 다른 많은 것들을 가지고 있습니다 ...).
interface
s 는 내부 클래스를 가질 수 없습니다 . 의 중첩 클래스 의 static
수정자를 생략 할 수 interface
있지만 여전히 내부 클래스가 아닌 중첩 클래스입니다.
B
클래스는 내부 클래스가 아닌 정적 중첩 클래스입니다. 인터페이스는 특별한 대우를받습니다. "인터페이스의 멤버 클래스는 암시 적으로 정적이므로 내부 클래스로 간주되지 않습니다." docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3
예, 인터페이스 내부에 클래스를 가질 수 있습니다. 사용의 한 가지 예는 다음과 같습니다.
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 ()와 같은 메서드 정의에서 사용되는 이벤트 객체에 대한 정보를 캡슐화하기위한 두 개의 중첩 클래스가 있습니다. 입력 인터페이스 내부에두면 응집력이 향상됩니다.
IMHO라는 유효한 용도는 둘러싸는 인터페이스 메서드에서 수신하거나 반환하는 개체를 정의하는 것입니다. Tiply 데이터 보유 구조. 이런 식으로 객체가 해당 인터페이스에만 사용되는 경우 더 일관된 방식으로 작업을 수행 할 수 있습니다.
예를 들어 :
interface UserChecker {
Ticket validateUser(Credentials credentials);
class Credentials {
// user and password
}
class Ticket {
// some obscure implementation
}
}
하지만 어쨌든 ... 그것은 단지 맛의 문제입니다.
Java 7 사양 에서 인용 :
인터페이스에는 멤버 형식 선언 (§8.5)이 포함될 수 있습니다.
인터페이스의 멤버 형식 선언은 암시 적으로 정적이며 공용입니다. 이러한 수정 자 중 하나 또는 둘 다를 중복으로 지정할 수 있습니다.
Java 인터페이스 내에서 비 정적 클래스를 선언하는 것은 불가능합니다.
흥미로운 사용 사례는 https://stackoverflow.com/a/3442218/454667 (단일 클래스 상속 문제를 극복하기 위해)에 설명 된대로 내부 클래스를 통해 인터페이스 메서드에 일종의 기본 구현을 제공하는 것입니다 .
예, 인터페이스 내부에 정적 클래스 정의를 가질 수 있지만이 기능의 가장 유용한 측면은 enum 유형 (특수한 종류의 정적 클래스)을 사용할 때입니다. 예를 들어 다음과 같은 것을 가질 수 있습니다.
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);
...
}
@Bachi가 언급하는 것은 Scala의 특성과 유사하며 실제로 인터페이스 내부의 중첩 된 클래스를 사용하여 구현됩니다. 이것은 Java에서 시뮬레이션 할 수 있습니다. 자바 특성 또는 믹스 인 패턴 도 참조하세요 ?
다른 구현 동작과 같은 더 복잡한 구성을 원할 때 다음을 고려하십시오.
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();
}
}
일부 정적 구현을 제공 할 수 있지만 혼란 스럽지는 않습니다. 모르겠습니다.