2012-04-15 39 views
33

Tôi có một dãy chỗ ngồi và mảng có hai chuỗi (được chọn và trống). Khi nhấp chuột, tôi muốn duyệt qua mảng và tìm chỗ ngồi đã chọn. Khi tôi nhấn nút, thông báo:Biến cục bộ cuối cùng không thể được gán

Không thể gán chỗ ngồi biến cục bộ cuối cùng vì nó được xác định trong loại bao quanh.

JButton btnContinue = new JButton("Next"); 
    btnContinue.addMouseListener(new MouseAdapter() { 
     public void mouseClicked(MouseEvent arg0) { 

      for(int x=0;x<17;x++){ 
       if(anArray[x]=="selected"){ 

        seatno = anArray[x]; 
       } 
      } 

      data page=new data(newfrom,newto,newtime,date2,seatno); 
      page.setVisible(true); 
      setVisible(false); 
     } 
    }); 
    btnContinue.setBounds(358, 227, 62, 23); 
    contentPane.add(btnContinue); 
+0

biến 'seatno' của bạn có từ khóa cuối cùng trong đó. –

Trả lời

89

Vấn đề là rằng các biến phương pháp địa phương từ các loại kèm theo là thực sự sao chép với các trường hợp lớp nặc danh (điều này là bởi vì vấn đề kích hoạt khung hình, nhưng tôi sẽ không đi sâu hơn vào chi tiết vì điều này không thực sự liên quan đến câu hỏi), đó là lý do tại sao chúng cần phải là cuối cùng, bởi vì biến trong thể hiện kiểu lồng nhau không giống nhau nữa.

Vì vậy, đây là ví dụ đầu tiên:

void foo() { 
    int a = 3; 
    new Runnable() { 
     @Override 
     public void run() { 
      a += 3; 
     } 
    }; 
} 

này không biên dịch, bởi vì bạn không có thể tham khảo một biến phi chính thức trong một phương pháp lớp vô danh. Khi bạn thêm công cụ sửa đổi cuối cùng vào khai báo a, giá trị của a sẽ được sao chép vào phiên bản đã tạo của lớp ẩn danh mà bạn đã xác định. Tuy nhiên, bạn sẽ không được phép thay đổi giá trị a, bởi vì các thay đổi sẽ không được hiển thị cho phương thức mà a được khai báo.

Tuy nhiên, các lớp học vô danh không phải là tĩnh, có nghĩa là, họ có một tham chiếu đến dụ kèm theo (trừ trường hợp phương pháp mà chúng được khai báo là static) mà bạn có thể sử dụng để sửa đổi các biến của dụ kèm theo:

int a = 3; 

void foo() { 
    new Runnable() { 
     @Override 
     public void run() { 
      a += 3; 
     } 
    }; 
} 

Ví dụ này biên dịch và nó sẽ tăng a 3 mỗi lần phương pháp run() của cá thể lớp ẩn danh 'được gọi. (Trong ví dụ này, nó không bao giờ được gọi, nhưng nó chỉ là một ví dụ.)

Vì vậy, để tóm tắt, bạn cần chuyển đổi biến seatno từ biến phương thức cục bộ sang biến mẫu của kiểu bao.Hoặc, nếu chưa, bạn cần loại bỏ công cụ sửa đổi cuối cùng vì các biến cuối cùng chỉ có thể được gán một lần.

Cập nhật: Trong Java 8, khái niệm về hiệu quả thức biến được giới thiệu (xem Java Language Specification). Tuy nhiên, trong ví dụ đầu tiên của bài đăng này, biến số a được gán nhiều lần, điều này ngăn không cho nó có hiệu lực cuối cùng. Điều này có nghĩa rằng ví dụ này vẫn không biên dịch với Java 8. (Lỗi biên dịch là "Biến cục bộ được xác định trong phạm vi bao quanh phải là cuối cùng hoặc hiệu quả cuối cùng")

0

Mà không biết việc kê khai của seatno, tôi muốn đề nghị để giới thiệu một biến mới trong mouseClicked() phương pháp đó là không cuối cùng và không được công việc tương tự như seatno hiện có, như biến dường như chỉ được sử dụng bên trong phương thức đó.

Nhân tiện: Viết hoa tên lớp của bạn (data phải là Data). Sẽ trông rõ ràng hơn nhiều.

3

Biến cuối cùng không thể thay đổi giá trị của nó (nó tương tự như const từ C/C++).

Bạn có thể muốn biến nó thành một trường trong một lớp (không có từ khóa cuối cùng), không phải là biến cục bộ bên trong một hàm.

0

Đảm bảo biến của bạn không có công cụ sửa đổi final.

//final, can be set only when the object is created. 
private final String seatno; 

//no final modifier, the value can be set every time you "want" 
private String seatno; 

Ngoài ra, để so sánh Strings bạn nên sử dụng equals:

if(anArray[x].equals("selected")) 
4

Thay vì xác định biến thành viên lớp mà bạn cũng có thể sử dụng một int có thể thay đổi để đạt được điều tương tự.

void foo() { 
    final MutableInt a = new MutableInt(3); 
    new Runnable() { 
     @Override 
     public void run() { 
      a.add(3); 
     } 
    }; 
} 

Vì MutableInt không phải là kiểu nguyên thủy (do đó được chuyển qua tham chiếu) và có thể được gán lại tác phẩm này.

+3

Lưu ý: MutableInt yêu cầu Apache Commons Lang. – Sundae

+0

Rất tốt, cảm ơn bạn. MutableInt là công thức hơn AtomicInteger, vì ít mã lệnh hơn (cần ít mã hơn) – Hartmut

1

Gần đây tôi đã gặp phải sự cố tương tự. Trong trường hợp của tôi nó được dễ dàng hơn để tạo mảng cuối cùng (hoặc bộ sưu tập) và để thêm biến, mà tôi muốn thay đổi bên trong lớp vô danh, để mảng này, như dưới đây.

int a = 3; 
    final int[] array = new int[1]; 
    array[0] = a; 
    new Runnable() { 
     @Override 
     public void run() { 
      array[0] += 3; 
     } 
    }; 
Các vấn đề liên quan