Khi các lớp bên trong được thêm vào Java trong phiên bản 1.1 của ngôn ngữ, ban đầu chúng được định nghĩa là sự chuyển đổi sang mã tương thích 1.0. Nếu bạn nhìn vào một ví dụ về sự chuyển đổi này, tôi nghĩ nó sẽ làm cho nó rõ ràng hơn rất nhiều về cách một lớp bên trong thực sự hoạt động.
Hãy xem xét đoạn mã từ câu trả lời của Ian Roberts:
public class Foo {
int val;
public Foo(int v) { val = v; }
class Bar {
public void printVal() {
System.out.println(val);
}
}
public Bar createBar() {
return new Bar();
}
}
Khi được chuyển đổi thành mã tương thích 1.0, lớp bên trong Barđó sẽ trở thành một cái gì đó như thế này:
class Foo$Bar {
private Foo this$0;
Foo$Bar(Foo outerThis) {
this.this$0 = outerThis;
}
public void printVal() {
System.out.println(this$0.val);
}
}
Tên lớp bên trong được đặt trước tên lớp bên ngoài để làm cho nó là duy nhất. Một this$0thành viên riêng tư ẩn được thêm vào để giữ một bản sao của bên ngoài this. Và một hàm tạo ẩn được tạo để khởi tạo thành viên đó.
Và nếu bạn nhìn vào createBarphương thức, nó sẽ được chuyển đổi thành một cái gì đó như thế này:
public Foo$Bar createBar() {
return new Foo$Bar(this);
}
Vì vậy, hãy xem điều gì sẽ xảy ra khi bạn thực thi đoạn mã sau.
Foo f = new Foo(5);
Foo.Bar b = f.createBar();
b.printVal();
Đầu tiên, chúng tôi khởi tạo một thể hiện của Foovà intialise valthành viên thành 5 (tức là f.val = 5).
Tiếp theo, chúng tôi gọi f.createBar(), khởi tạo một thể hiện của Foo$Barvà khởi tạo this$0thành viên thành giá trị thisđược truyền vào từ createBar(tức là b.this$0 = f).
Cuối cùng chúng ta gọi b.printVal()đó cố gắng để in b.this$0.valmà là f.valđó là 5.
Bây giờ đó là một mô tả thông thường của một lớp bên trong. Hãy xem điều gì sẽ xảy ra khi khởi tạo Bartừ bên ngoài Foo.
Foo f = new Foo(5);
Foo.Bar b = f.new Bar();
b.printVal();
Áp dụng lại phép biến đổi 1.0 của chúng tôi, dòng thứ hai đó sẽ trở thành như thế này:
Foo$Bar b = new Foo$Bar(f);
Điều này gần giống với f.createBar()cuộc gọi. Một lần nữa, chúng tôi khởi tạo một phiên bản của Foo$Barvà khởi tạo this$0thành viên thành f. Vì vậy, một lần nữa b.this$0 = f,.
Và một lần nữa khi bạn gọi b.printVal(), bạn đang in b.thi$0.valmà là f.valđó là 5.
Điều quan trọng cần nhớ là lớp bên trong có một thành viên ẩn giữ một bản sao của thislớp bên ngoài. Khi bạn khởi tạo một lớp bên trong từ bên trong lớp bên ngoài, nó được khởi tạo ngầm với giá trị hiện tại là this. Khi bạn khởi tạo lớp bên trong từ bên ngoài lớp ngoài, bạn chỉ định rõ ràng phiên bản của lớp bên ngoài sẽ sử dụng, thông qua tiền tố trên newtừ khóa.