2015-01-16 15 views
17

Nghe có vẻ hơi lạ, nhưng có thể thêm công cụ sửa đổi final vào thời gian chạy không?Thêm công cụ sửa đổi cuối cùng khi chạy trong Java

Tôi có một biến được đánh dấu là public static int/short. Tại thời điểm nhất định, tôi muốn ngăn thay đổi giá trị của nó và tôi muốn giữ khả năng truy cập của nó dưới dạng giá trị tĩnh chuẩn (ClassName.field).

public class Main { 

    private static int a = 0; 

    public static void addFinalMod(Field f) { 

     Field modifiersField = null; 
     try { 
      modifiersField = Field.class.getDeclaredField("modifiers"); 
     } 
     catch (NoSuchFieldException e) { 
      e.printStackTrace(); 
     } 
     modifiersField.setAccessible(true); 
     try { 
      modifiersField.setInt(f, f.getModifiers() & Modifier.FINAL); 
     } 
     catch (IllegalAccessException e) { 
      e.printStackTrace(); 
     } 
    } 

    public static void main(String[] args) { 

     System.out.println(a); 
     try { 
      Field f = Main.class.getDeclaredField("a"); 
      addFinalMod(f); 
     } 
     catch (NoSuchFieldException e) { 
      e.printStackTrace(); 
     } 
     a = 10; //I was expecting error/exception here 
     System.out.println(a); 
    } 

Output:

0 
10 
+1

Đây thực sự là một câu hỏi thú vị. Bây giờ, với tôi, có vẻ như các quy tắc 'final' chỉ được kiểm tra trong thời gian biên dịch (điều này bao gồm cả yêu cầu khởi tạo và bảo đảm JMM). –

+3

Tôi nghĩ bạn có nghĩa là 'f.getModifiers() | Modifier.FINAL' thay vào đó 'f.getModifiers() & Modifier.FINAL' để cho các biến tố khác ở lại. Ngoài ra, nếu bạn sẽ sử dụng 'f.thiết lập (null, 5); 'bạn sẽ nhận được ngoại lệ dự kiến. – Pshemo

Trả lời

32

Tại thời điểm nhất định tôi muốn ngăn chặn việc thay đổi giá trị của nó

Do đó trong logic ứng dụng. Làm cho biến chỉ có thể truy cập thông qua các phương thức. Giữ một lá cờ theo dõi bất kỳ thay đổi nào đối với biến. Sau khi bạn đã áp dụng thay đổi hoặc đã đạt đến điểm nhất định, tăng cờ và ném ngoại lệ cho bất kỳ nỗ lực nào khác để thay đổi biến.

final là từ khóa/tính năng ngôn ngữ để viết mã nguồn và ngăn việc gán lại biến trong mã nguồn. Khi chạy, nó hầu như không có gì.

+1

Đây là những gì tôi sẽ làm quá, tôi muốn nhìn thấy một giải pháp thực sự nhưng tôi nghi ngờ nó có thể. –

+1

Upvote và một điểm brownie cho "(gần như)" :) – yshavit

+1

Tôi biết, sự sollution này sẽ hoạt động và rất dễ thực hiện. nhưng tôi không muốn sử dụng bất kỳ phương pháp nào. – user2749903

1

Sử dụng một đối tượng bất biến:

public class Thing { 
    private int value; 
    public Thing(int value) { this.value = value; } 
    public int getValue() { return this.value; } 
} 

Sau đó chỉ cần thay thế nó khi nó cần sửa đổi:

Thing x = Thing(1); 
// do some stuff 
x = Thing(2); 
// more stuff 

Nếu bạn đang nghĩ, "Nhưng sau đó họ vẫn có thể sửa đổi giá trị bằng cách thay thế vật!" tất nhiên. Cách duy nhất để ngăn chặn điều đó là khóa một số trạng thái toàn cầu (điều thực sự là không thể nếu nó không phải là một hằng số), nhưng bạn không sử dụng trạng thái toàn cầu, đúng không? Trạng thái toàn cầu là một điều xấu TM.

Trạng thái toàn cầu có một vấn đề rất đơn giản: nó làm cho mã của bạn ít bị tái sử dụng hơn và dễ bị lỗi hơn. Lỗi dễ xảy ra là đặc biệt đúng nếu bạn đang sửa đổi trạng thái toàn cục đó khi chạy. "Aw, crap, mọi thứ đang xảy ra theo thứ tự sai." Bạn không có ý tưởng dễ dàng như thế nào. Đang cố gắng theo dõi thứ tự các sự kiện là lý do khiến việc cắt xén quá khó. Về khả năng sử dụng lại, điều đó có nghĩa là bạn không thể có hai trường hợp độc lập, điều này có nghĩa là bạn không thể có bất kỳ hai trường hợp nào phụ thuộc vào nó (ít nhất là khi bạn cần thay đổi điều này sau khi tất cả). Thậm chí nếu đây không phải là toàn cầu, thì đây là một trạng thái kỳ lạ mà tất cả những người phải sửa đổi mã của bạn (bao gồm cả bản thân) sẽ phải nhận thức và suy nghĩ khi họ thực hiện thay đổi. Điều đó nghe có vẻ như nó sẽ làm thay đổi mọi thứ dễ dàng hơn hay khó hơn? (Gợi ý: sau này.) Đừng làm điều này cho bản thân hoặc đồng nghiệp của bạn. Làm cho nó đơn giản hơn. Hãy học một bài học từ Zen of Python: "Đơn giản là tốt hơn so với phức tạp."

Vì vậy, dòng dưới cùng: nếu bạn cần một đối tượng bất biến, hãy sử dụng một đối tượng bất biến. Nếu bạn cần một toàn cầu bất biến không phải là một hằng số, hãy tìm ra cách tốt hơn để tổ chức mã của bạn.

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