2010-06-26 25 views
11

Tôi đã gặp nhiều tình huống mà tôi cần phải chuyển giá trị cho một chủ đề khác và tôi đã sáng lập ra rằng tôi có thể làm theo cách này, nhưng tôi đã tự hỏi nó hoạt động như thế nào?Chính xác điều gì xảy ra khi bạn có các giá trị cuối cùng và các lớp bên trong trong một phương thức?

public void method() { 
    final EventHandler handle = someReference; 

    Thread thread = new Thread() { 
     public void run() { 
      handle.onEvent(); 
     } 
    }; 

    thread.start(); 
} 

Edit: Chỉ cần nhận ra câu hỏi của tôi đã không được chính xác hướng về những gì tôi muốn biết. Đó là "làm thế nào" nó hoạt động chứ không phải là "tại sao".

Trả lời

7

Bạn có thể nhận thấy điều gì xảy ra bên dưới bằng cách đơn giản giải mã lớp bên trong. Dưới đây là một ví dụ ngắn:

Sau khi biên dịch đoạn mã này:

public class Test { 

public void method() { 
    final Object handle = new Object(); 

    Thread thread = new Thread() { 
     public void run() { 
      handle.toString(); 
     } 
    }; 

    thread.start(); 
} 
} 

bạn sẽ nhận được Test.class cho Test.javaTest$1.class cho lớp bên trong Test.java. Sau decompiling Test$1.class bạn sẽ thấy điều này:

class Test$1 extends Thread 
{ 
    final Test this$0; 
    private final Object val$handle; 

    public void run() 
    { 
    this.val$handle.toString(); 
    } 
} 

Như bạn có thể thấy thay vì handle biến có this.val$handle. Điều này có nghĩa là handle được sao chép dưới dạng trường val$handle vào lớp bên trong. Và điều này sẽ hoạt động chính xác chỉ khi handle sẽ không bao giờ thay đổi - trong Java có nghĩa là nó phải là final.

Bạn cũng có thể nhận thấy rằng lớp bên trong có trường this$0 là tham chiếu đến lớp bên ngoài. Điều này lần lượt cho thấy cách các lớp bên trong không tĩnh có thể giao tiếp với các lớp bên ngoài.

8

Không có phương pháp nào có thể truy cập các biến cục bộ của các phương pháp khác. Điều này bao gồm các phương thức của các lớp ẩn danh như một lớp trong ví dụ của bạn. Tức là, phương thức run trong lớp Thread ẩn danh, không thể truy cập biến cục bộ là method().

Viết final trước biến cục bộ là cách để bạn làm lập trình viên cho trình biên dịch biết rằng biến thực sự có thể được coi là giá trị. Vì biến này (giá trị đọc!) Sẽ không thay đổi, nó là "ok" để truy cập nó trong các phương thức khác.

2

lớp bên trong này được dịch sang mã tương tự như:

class InnerClass extends Thread { 
    private EventHandler handle; 

    public InnerClass(EventHandler handle) { 
     this.handle = handle; 
    } 

    public void run() { 
     handle.onEvent(); 
    } 
} 

... 

EventHandler handle = someReference; 
Thread thread = new InnerClass(handle); 
thread.start(); 

Kể từ khi lớp bên trong thực sự được thông qua một bản sao của biến thức nó có thể không thực hiện bất kỳ thay đổi nào mà nó sẽ hiển thị trong lớp bên ngoài. Để không cho phép thậm chí cố gắng thay đổi tham số này, nó chỉ được phép truy cập các biến cuối cùng trong các lớp bên trong.

Các vấn đề liên quan