2013-04-05 37 views
12

Theo JSR-133 đối tượng không thay đổi được chỉ an toàn và không cần đồng bộ hóa. Tuy nhiên, có thể cập nhật giá trị của các trường cuối cùng bằng cách sử dụng sự phản chiếu:Làm thế nào để phản chiếu và bất biến phải làm việc cùng nhau

package com.stackoverflow; 

import java.lang.reflect.Field; 

public class WhatsGoingOn { 

    static class Immutable { 
     private final int value; 

     public Immutable(int value) { 
      this.value = value; 
     } 

     public int getValue() { 
      return value; 
     } 
    } 

    public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { 
     final Immutable immutable = new Immutable(Integer.MIN_VALUE); 

     final Field f = Immutable.class.getDeclaredField("value"); 
     f.setAccessible(true); 

     System.out.println(immutable.getValue()); 
     f.set(immutable, Integer.MAX_VALUE); 
     System.out.println(immutable.getValue()); 
    } 
} 

Cho số khung (Spring và Hibernate chỉ là một vài) dựa vào sự phản chiếu Tôi tò mò về đặc điểm nào nói về trường hợp này. Ví dụ. nếu tôi đặt trường cập nhật vào khối đồng bộ sẽ đảm bảo khả năng hiển thị trong các chủ đề khác, hoặc giá trị sẽ được lưu trữ trong sổ đăng ký theo thông số kỹ thuật cho cuối cùng.

http://download.oracle.com/otndocs/jcp/memory_model-1.0-pfd-spec-oth-JSpec/

Trả lời

5

Một đối tượng được coi là không thay đổi nếu trạng thái của nó không thể thay đổi sau khi được xây dựng. http://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html

Bạn đang sử dụng Object mà như mutable kể từ khi bạn đang thay đổi trạng thái của nó.

Đúng là việc sử dụng Reflection phá vỡ bất biến như được định nghĩa trong hướng dẫn, vì bạn có thể sử dụng nó để thay đổi các trường cuối cùng không liên tục.

Một ví dụ về một đối tượng bất biến Reflection chịu sẽ là như sau:

static class Immutable { 
    // This field is a constant, and cannot be changed using Reflection 
    private final int value = Integer.MIN_VALUE; 

    public int getValue() { 
     return value; 
    } 
} 

public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException { 
    final Immutable immutable = new Immutable(); 

    final Field f = Immutable.class.getDeclaredField("value"); 
    f.setAccessible(true); 

    System.out.println(immutable.getValue()); 
    f.set(immutable, Integer.MAX_VALUE); 
    System.out.println(immutable.getValue()); 
} 

Trong trường hợp này kiểm tra phản xạ của bạn sẽ thất bại, và giá trị sẽ vẫn Integer.MIN_VALUE. Nhưng hey, chúng ta luôn có thể sử dụng mã nguồn gốc hoặc một trình soạn thảo bộ nhớ để thay đổi giá trị đó thành một cái gì đó khác.

Nếu bạn đi xa đến mức hacking với sự phản ánh, bạn có thể cũng không gọi trường của bạn cuối cùng và cung cấp các phương pháp để thao tác nó.

4

Tất cả các cược đang tắt với sự phản ánh nếu bạn nhấn mạnh vào chuyển mạch điều khiển truy cập tắt và làm những việc nghịch ngợm.

Hằng số tĩnh thường được inline tại thời gian biên dịch nên việc thay đổi giá trị của chúng có thể sẽ không có tác động. Kết quả thực sự phụ thuộc vào mức độ thông minh của trình tối ưu hóa khi biên dịch và trình biên dịch JIT thông minh như thế nào ở thời gian chạy.

Kết quả cuối cùng: "Đây là những con rồng, sợ tất cả những người dám bước tới đây!"

3

lỗi Memory quán xảy ra trong kịch bản này:

1 thread 1 lần đọc một lĩnh vực với b1.getField1() và được 1

2 chủ đề 2 thay đổi lĩnh vực này với b1.setField1 (2)

3 bây giờ khi chuỗi 1 gọi b1.getField1() nó có thể nhận được 1 lần nữa, vì không có JVM đồng bộ hóa được phép tối ưu hóa cuộc gọi này và trả về giá trị được lưu trong bộ nhớ cache.

Nhưng nếu chúng ta khởi tạo một bean có thể thay đổi chỉ một lần trong instantiation (có thể với sự phản ánh, như container mùa xuân không) và chủ đề khác sẽ chỉ đọc nó sau khi khởi tạo, sẽ không có lỗi bộ nhớ ổn định ngay cả khi không bất kỳ syncronization

Các quy tắc tương tự áp dụng cho các đối tượng không thay đổi khi bạn thay đổi trường của chúng bằng sự phản chiếu.

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