Câu trả lời:
Có, bạn có thể tạo cả lớp lồng nhau hoặc lớp bên trong bên trong giao diện Java (lưu ý rằng trái ngược với niềm tin phổ biến, không có cái gọi là " lớp bên trong tĩnh ": điều này đơn giản là vô nghĩa, không có gì "bên trong" và không " lớp outter "khi một lớp lồng nhau là lớp tĩnh, vì vậy nó không thể là" lớp bên trong tĩnh ").
Dù sao, các biên dịch sau đây vẫn tốt:
public interface A {
class B {
}
}
Tôi đã thấy nó được sử dụng để đặt một số loại "trình kiểm tra hợp đồng" trực tiếp trong định nghĩa giao diện (tốt, trong lớp được lồng trong giao diện, có thể có các phương thức tĩnh, trái ngược với chính giao diện, điều này không thể). Trông như thế này nếu tôi nhớ không nhầm.
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)
}
}
}
Lưu ý rằng tôi không bình luận về tính hữu ích của một thứ như vậy, tôi chỉ đơn giản trả lời câu hỏi của bạn: nó có thể được thực hiện và đây là một cách sử dụng tôi đã thấy nó.
Bây giờ tôi sẽ không bình luận về tính hữu dụng của một cấu trúc như vậy và từ tôi đã thấy: Tôi đã thấy nó, nhưng nó không phải là một cấu trúc rất phổ biến.
Cơ sở mã 200KLOC ở đây, nơi điều này xảy ra chính xác không thời gian (nhưng sau đó chúng tôi có rất nhiều thứ khác mà chúng tôi coi là các hoạt động xấu xảy ra chính xác không thời gian mà người khác sẽ thấy hoàn toàn bình thường như vậy ...).
interface
s không thể có các lớp bên trong. Bạn có thể bỏ qua static
sửa đổi của một interface
lớp lồng nhau nhưng vẫn là một lớp lồng nhau, không phải lớp bên trong.
B
lớp là một lớp lồng nhau tĩnh và không phải là một lớp bên trong; giao diện được đối xử đặc biệt. Tôi không thể tìm thấy đề cập đến điều này trực tuyến, ngoại trừ trong thông số kỹ thuật: "Một lớp thành viên của giao diện là tĩnh hoàn toàn nên không bao giờ được coi là một lớp bên trong." docs.oracle.com/javase/specs/jls/se8/html/jls-8.html#jls-8.1.3
Có, chúng ta có thể có các lớp bên trong giao diện. Một ví dụ về cách sử dụng có thể là
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();
}
Ở đây mã có hai lớp lồng nhau dùng để đóng gói thông tin về các đối tượng sự kiện mà sau này được sử dụng trong các định nghĩa phương thức như getKeyEvents (). Có chúng bên trong giao diện Đầu vào cải thiện sự gắn kết.
Sử dụng hợp lệ, IMHO, là xác định các đối tượng được nhận hoặc trả về bởi các phương thức giao diện bao quanh. Cấu trúc lưu giữ dữ liệu theo mẹo. Bằng cách đó, nếu đối tượng chỉ được sử dụng cho giao diện đó, bạn có mọi thứ theo cách gắn kết hơn.
Ví dụ như:
interface UserChecker {
Ticket validateUser(Credentials credentials);
class Credentials {
// user and password
}
class Ticket {
// some obscure implementation
}
}
Nhưng dù sao thì ... vấn đề chỉ là hương vị.
Trích dẫn từ thông số kỹ thuật Java 7 :
Các giao diện có thể chứa các khai báo kiểu thành viên (§8.5).
Khai báo kiểu thành viên trong giao diện là hoàn toàn tĩnh và công khai. Được phép chỉ định dư thừa một trong hai hoặc cả hai từ bổ nghĩa này.
Không thể khai báo các lớp không tĩnh bên trong giao diện Java, điều này có ý nghĩa với tôi.
Một trường hợp sử dụng thú vị là cung cấp loại triển khai mặc định cho các phương thức giao diện thông qua một lớp bên trong như được mô tả tại đây: https://stackoverflow.com/a/3442218/454667 (để khắc phục vấn đề kế thừa một lớp).
Nó chắc chắn là có thể, và một trường hợp mà tôi thấy nó hữu ích là khi một giao diện phải ném các ngoại lệ tùy chỉnh. Bạn giữ các ngoại lệ với giao diện được liên kết của chúng, điều mà tôi nghĩ thường gọn gàng hơn là rải rác cây nguồn của bạn với hàng đống tệp ngoại lệ tầm thường.
interface MyInterface {
public static class MyInterfaceException extends Exception {
}
void doSomething() throws MyInterfaceException;
}
Có, có thể có các định nghĩa lớp tĩnh bên trong một giao diện, nhưng có lẽ khía cạnh hữu ích nhất của tính năng này là khi sử dụng các kiểu enum (là loại lớp tĩnh đặc biệt). Ví dụ, bạn có thể có một cái gì đó như thế này:
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);
...
}
Những gì @Bachi đề cập tương tự như các đặc điểm trong Scala và thực sự được triển khai bằng cách sử dụng một lớp lồng nhau bên trong một giao diện. Điều này có thể được mô phỏng trong Java. Xem thêm các đặc điểm java hoặc mô hình mixins?
Có thể khi bạn muốn các cấu trúc phức tạp hơn như một số hành vi triển khai khác nhau, hãy xem xét:
public interface A {
public void foo();
public static class B implements A {
@Override
public void foo() {
System.out.println("B foo");
}
}
}
Đây là giao diện của bạn và đây sẽ là người triển khai:
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();
}
}
Có thể cung cấp một số triển khai tĩnh, nhưng điều đó sẽ không gây nhầm lẫn, tôi không biết.
Tôi đã tìm thấy một cách sử dụng loại cấu trúc này.
Bạn có quyền truy cập vào tất cả các hằng số được nhóm lại; tên của lớp hoạt động như một không gian tên trong trường hợp này.
Tôi cần một cái ngay bây giờ. Tôi có một giao diện nơi sẽ thuận tiện để trả về một lớp duy nhất từ một số phương thức của nó. Lớp này chỉ có ý nghĩa như một vùng chứa các phản hồi từ các phương thức của giao diện này.
Do đó, sẽ rất tiện lợi nếu có một định nghĩa lớp lồng nhau tĩnh, chỉ được liên kết với giao diện này, vì giao diện này phải là nơi duy nhất mà lớp vùng chứa kết quả này từng được tạo.
Ví dụ các đặc điểm (giao diện giống như giao diện với các phương thức được triển khai) trong Groovy. Chúng được biên dịch sang một giao diện chứa lớp bên trong, nơi tất cả các phương thức được triển khai.