2016-06-22 19 views
15

Đây là phương thức keySet() trên lớp HashMap từ JDK. Tại sao tác giả gán trường (keySet) cho biến ks cục bộ?gán trường mẫu cho biến cục bộ

public Set<K> keySet() { 
    Set<K> ks; 
    return (ks = keySet) == null ? (keySet = new KeySet()) : ks; 
} 

Sự khác biệt giữa bên trên và bên dưới là gì? Điều này có liên quan đến luồng an toàn không?

public Set<K> keySet() { 
    return (keySet == null ? (keySet = new KeySet()) : keySet; 
} 
+0

Có thể; mặc dù nó cũng có vẻ như anh ta đang cố gắng thiết lập một biến cấp lớp trong khi đảm bảo rằng biến không phải là null và trả về giá trị đó. Tôi đã không phải là một đầu mối vượt ra ngoài mặc dù. Tôi cần phải xem cả lớp. –

+0

Có lẽ để hiểu rõ ý định – alphablue

+1

Có thể được coi là bản sao của http://stackoverflow.com/q/28975415/3182664 http://stackoverflow.com/q/2785964/3182664 http://stackoverflow.com/q/ 37776179/3182664 http://stackoverflow.com/q/32619269/3182664 và có khả năng một số người khác ... – Marco13

Trả lời

6

Để mở rộng một chút về Câu trả lời của Michael, tôi hy vọng nó có đó để đảm bảo rằng phương pháp keySet() không bao giờ trả về null, có thể ngoài việc cung cấp các lợi ích hiệu suất được ghi nhận.

Với mã này:

public Set<K> keySet() { 
    return (keySet == null ? (keySet = new KeySet()) : keySet; 
} 

Nó sẽ là ít nhất về mặt lý thuyết có thể trong đa luồng mã mà lĩnh vực keySet có thể được thiết lập để null giữa đọc đầu tiên (keySet == null) và đọc thứ hai, nơi nó Được trả lại. Tôi đã không nhìn vào phần còn lại của mã, nhưng tôi giả sử có những nơi khác mà keySet có khả năng được giao null. Cho dù đây là kết quả của một vấn đề nhìn thấy trong tự nhiên, hoặc biện pháp phòng thủ sẽ là một câu hỏi cho các tác giả.

Mã thực tế:

public Set<K> keySet() { 
    Set<K> ks; 
    return (ks = keySet) == null ? (keySet = new KeySet()) : ks; 
} 

... không có vấn đề này như lĩnh vực này chỉ được đọc một lần.

+0

Yup. Điều này là về an toàn trong môi trường đa luồng. –

+0

@msandiford nó không nhất thiết được đặt thành null ở đâu đó, các thao tác đơn giản có thể được sắp xếp lại vì có hai lần đọc lỗi của biến được chia sẻ. – Eugene

8

Nếu bạn nhìn vào keySet khai trong abstract class AbstractMap<K,V>, bạn sẽ thấy rằng nó được định nghĩa là:

transient volatile Set<K> keySet; 

Vì nó là dễ bay hơi, đọc nó chỉ một lần bằng cách sử dụng sự phân công biến cục bộ là rẻ hơn so với đọc nó hai lần như trong ví dụ khác mà bạn cung cấp.

Hơn nữa, nếu bạn đã trả lại biến keySet trực tiếp, sau đó tất cả các mã khách hàng sẽ được giải quyết với một tham chiếu biến động so với một tham chiếu non-volatile (tức là Set<K> ks)

+2

Cảm ơn bạn đã trả lời về đọc trường dễ bay hơi, tôi chưa từng nghĩ về nó. Bạn có thể vui lòng giải thích "đối phó với một tham chiếu dễ bay hơi so với một tham chiếu không bay hơi" một phần? – joohwan

+1

Không có khái niệm nào như là "tham chiếu dễ bay hơi so với tham chiếu không bay hơi". – Boann

+0

@Boann Đúng vậy. Cảm ơn. –

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