2010-10-10 56 views
16

Tôi đang cố gắng tạo một mảng các JLabels, tất cả chúng sẽ bị ẩn khi được nhấp. Vấn đề xảy ra khi cố gắng thiết lập trình lắng nghe chuột thông qua một lớp bên trong cần truy cập vào biến lặp của vòng lặp được sử dụng để khai báo các nhãn. Mã là tự giải thích:truy cập vào biến trong lớp bên trong trong java

for(int i=1; i<label.length; i++) { 
     label[i] = new JLabel("label " + i); 
     label[i].addMouseListener(new MouseAdapter() { 
      public void mouseClicked(MouseEvent me) { 
      label[i].setVisible(false); // compilation error here 
      } 
     }); 
     cpane.add(label[i]); 
    } 

Tôi nghĩ rằng tôi có thể khắc phục điều này bằng cách sử dụng this hoặc có thể super thay vì tiếng gọi của label[i] bên trong phương thức bên trong nhưng tôi đã không thể tìm nó ra.

Lỗi biên dịch là: biến cục bộ i được truy cập từ bên trong lớp bên trong; cần phải được khai báo cuối cùng`

Tôi chắc chắn rằng câu trả lời phải là điều gì đó thực sự ngớ ngẩn mà tôi chưa từng nghĩ đến hoặc có thể tôi đang mắc phải một số sai lầm nhỏ.

Bất kỳ trợ giúp sẽ được đánh giá

+0

Các lỗi này là: 'biến cục bộ i được truy cập từ bên trong lớp bên trong; cần được khai báo final' – omtinez

+0

@omtinez: thì có lẽ bạn nên khai báo biến đó là 'final', không? (xem [Hỏi đáp này] (http://stackoverflow.com/questions/3045130/constructors-in-inner-classes-implementing-interfaces), cũng) –

+1

@Matt Ball, không phải là một ý kiến ​​hay có biến lặp 'final'. –

Trả lời

27

Biến cục bộ của bạn phải là final để được truy cập từ lớp bên trong (và ẩn danh).

Bạn có thể thay đổi mã của bạn cho một cái gì đó như thế này:

for (int i = 1; i < label.length; i++) { 
    final JLabel currentLabel =new JLabel("label " + i); 
    currentLabel.addMouseListener(new MouseAdapter() { 
     public void mouseClicked(MouseEvent me) { 
      currentLabel.setVisible(false); // No more compilation error here 
     } 
    }); 
    label[i] = currentLabel; 
} 

Từ JLS:

Bất kỳ biến địa phương, thông số chính thức, hoặc tham số ngoại lệ được sử dụng nhưng không khai báo trong một lớp bên phải được khai báo final.

Bất kỳ biến cục bộ nào được sử dụng nhưng không được khai báo trong lớp bên trong phải được gán rõ ràng (§16) trước phần thân của lớp bên trong.


Resources:

+0

sẽ hữu ích khi có thể sử dụng biến lặp cho các phương pháp khác mà tôi cho là không liên quan đến câu hỏi. – omtinez

+0

@Colin Hebert Liên kết "tài nguyên" của bạn dường như liên kết tài liệu khác với phần 8.1.3 – trante

+0

@trante, cảm ơn đề cập đến một JLS trước đó, được tổ chức bởi mặt trời. Nó đã được cập nhật. –

0

Điều này xảy ra bởi vì label không được xác định như final.

Khai báo mảng của nhãn như:

final JLabel[] label;

thay vì:

JLabel[] label;

bạn MouseAdapter không phải là một lớp bên trong; đó là một lớp học ẩn danh. Các lớp ẩn danh chỉ có thể tham chiếu đến các biến số final của mã kèm theo của chúng.

+0

ẩn danh? trình biên dịch đã nói với tôi rằng nó là bên trong ... – omtinez

+1

Thực ra, nó là một * lớp bên trong vô danh *, ẩn danh có nghĩa là nó không có tên rõ ràng, và ý nghĩa bên trong nó chứa trong một lớp khác. – Jorn

0

Các lớp bên trong vô danh chỉ có thể truy cập các biến của phương pháp kèm theo là final.

4

Nếu bạn đang gặp một vấn đề truy cập i, thực hiện một biến nằm ngoài phạm vi nội lớp học của bạn (ví dụtrước label[i].addMouseListener(...)):

for(int i=1; i<label.length; i++) { 
    label[i] = new JLabel("label " + i); 

    final int localI = i; 
    label[i].addMouseListener(new MouseAdapter() { 
     public void mouseClicked(MouseEvent me) { 
     label[localI].setVisible(false); 
     } 
    }); 
    cpane.add(label[i]); 
} 
+1

có lẽ không phải là thanh lịch nhất giải pháp, nhưng tôi nghĩ rằng điều này nên làm công việc – omtinez

+0

Nó sẽ làm việc, nhưng giải pháp Colins là đẹp hơn nhiều. – Jorn

2

bạn cũng có thể sử dụng getSource trong chương trình của bạn. Sau này, bạn có thể truy cập vào thành phần của bạn với sự giúp đỡ của typecasting. nó sẽ làm giảm dòng thêm mã, mã của bạn sẽ trông giống như

for (int i = 1; i < label.length; i++) { 
    currentLabel.addMouseListener(new MouseAdapter(e) { 
     public void mouseClicked(MouseEvent me) { 
     JLabel label = (JLabel) me.getSource(); 
     } 
    }); 
} 
Các vấn đề liên quan