2014-03-28 23 views
2

當在java.util.HashSet<E>實施找:未使用的方法JDK8

你看到有一些不被所有使用方法writeObjectreadObject,他們還有私人的,所以他們不能通過擴展課程來使用。

爲什麼這些方法在執行Java 8,JDK 8?

代碼複製爲清楚:

/* 
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. 
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
* 
*/ 

package java.util; 

import java.io.InvalidObjectException; 

/** 
* This class implements the <tt>Set</tt> interface, backed by a hash table 
* (actually a <tt>HashMap</tt> instance). It makes no guarantees as to the 
* iteration order of the set; in particular, it does not guarantee that the 
* order will remain constant over time. This class permits the <tt>null</tt> 
* element. 
* 
* <p>This class offers constant time performance for the basic operations 
* (<tt>add</tt>, <tt>remove</tt>, <tt>contains</tt> and <tt>size</tt>), 
* assuming the hash function disperses the elements properly among the 
* buckets. Iterating over this set requires time proportional to the sum of 
* the <tt>HashSet</tt> instance's size (the number of elements) plus the 
* "capacity" of the backing <tt>HashMap</tt> instance (the number of 
* buckets). Thus, it's very important not to set the initial capacity too 
* high (or the load factor too low) if iteration performance is important. 
* 
* <p><strong>Note that this implementation is not synchronized.</strong> 
* If multiple threads access a hash set concurrently, and at least one of 
* the threads modifies the set, it <i>must</i> be synchronized externally. 
* This is typically accomplished by synchronizing on some object that 
* naturally encapsulates the set. 
* 
* If no such object exists, the set should be "wrapped" using the 
* {@link Collections#synchronizedSet Collections.synchronizedSet} 
* method. This is best done at creation time, to prevent accidental 
* unsynchronized access to the set:<pre> 
* Set s = Collections.synchronizedSet(new HashSet(...));</pre> 
* 
* <p>The iterators returned by this class's <tt>iterator</tt> method are 
* <i>fail-fast</i>: if the set is modified at any time after the iterator is 
* created, in any way except through the iterator's own <tt>remove</tt> 
* method, the Iterator throws a {@link ConcurrentModificationException}. 
* Thus, in the face of concurrent modification, the iterator fails quickly 
* and cleanly, rather than risking arbitrary, non-deterministic behavior at 
* an undetermined time in the future. 
* 
* <p>Note that the fail-fast behavior of an iterator cannot be guaranteed 
* as it is, generally speaking, impossible to make any hard guarantees in the 
* presence of unsynchronized concurrent modification. Fail-fast iterators 
* throw <tt>ConcurrentModificationException</tt> on a best-effort basis. 
* Therefore, it would be wrong to write a program that depended on this 
* exception for its correctness: <i>the fail-fast behavior of iterators 
* should be used only to detect bugs.</i> 
* 
* <p>This class is a member of the 
* <a href="{@docRoot}/../technotes/guides/collections/index.html"> 
* Java Collections Framework</a>. 
* 
* @param <E> the type of elements maintained by this set 
* 
* @author Josh Bloch 
* @author Neal Gafter 
* @see  Collection 
* @see  Set 
* @see  TreeSet 
* @see  HashMap 
* @since 1.2 
*/ 

public class HashSet<E> 
    extends AbstractSet<E> 
    implements Set<E>, Cloneable, java.io.Serializable 
{ 
    static final long serialVersionUID = -5024744406713321676L; 

    private transient HashMap<E,Object> map; 

    // Dummy value to associate with an Object in the backing Map 
    private static final Object PRESENT = new Object(); 

    /** 
    * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has 
    * default initial capacity (16) and load factor (0.75). 
    */ 
    public HashSet() { 
     map = new HashMap<>(); 
    } 

    /** 
    * Constructs a new set containing the elements in the specified 
    * collection. The <tt>HashMap</tt> is created with default load factor 
    * (0.75) and an initial capacity sufficient to contain the elements in 
    * the specified collection. 
    * 
    * @param c the collection whose elements are to be placed into this set 
    * @throws NullPointerException if the specified collection is null 
    */ 
    public HashSet(Collection<? extends E> c) { 
     map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16)); 
     addAll(c); 
    } 

    /** 
    * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has 
    * the specified initial capacity and the specified load factor. 
    * 
    * @param  initialCapacity the initial capacity of the hash map 
    * @param  loadFactor  the load factor of the hash map 
    * @throws  IllegalArgumentException if the initial capacity is less 
    *    than zero, or if the load factor is nonpositive 
    */ 
    public HashSet(int initialCapacity, float loadFactor) { 
     map = new HashMap<>(initialCapacity, loadFactor); 
    } 

    /** 
    * Constructs a new, empty set; the backing <tt>HashMap</tt> instance has 
    * the specified initial capacity and default load factor (0.75). 
    * 
    * @param  initialCapacity the initial capacity of the hash table 
    * @throws  IllegalArgumentException if the initial capacity is less 
    *    than zero 
    */ 
    public HashSet(int initialCapacity) { 
     map = new HashMap<>(initialCapacity); 
    } 

    /** 
    * Constructs a new, empty linked hash set. (This package private 
    * constructor is only used by LinkedHashSet.) The backing 
    * HashMap instance is a LinkedHashMap with the specified initial 
    * capacity and the specified load factor. 
    * 
    * @param  initialCapacity the initial capacity of the hash map 
    * @param  loadFactor  the load factor of the hash map 
    * @param  dummy    ignored (distinguishes this 
    *    constructor from other int, float constructor.) 
    * @throws  IllegalArgumentException if the initial capacity is less 
    *    than zero, or if the load factor is nonpositive 
    */ 
    HashSet(int initialCapacity, float loadFactor, boolean dummy) { 
     map = new LinkedHashMap<>(initialCapacity, loadFactor); 
    } 

    /** 
    * Returns an iterator over the elements in this set. The elements 
    * are returned in no particular order. 
    * 
    * @return an Iterator over the elements in this set 
    * @see ConcurrentModificationException 
    */ 
    public Iterator<E> iterator() { 
     return map.keySet().iterator(); 
    } 

    /** 
    * Returns the number of elements in this set (its cardinality). 
    * 
    * @return the number of elements in this set (its cardinality) 
    */ 
    public int size() { 
     return map.size(); 
    } 

    /** 
    * Returns <tt>true</tt> if this set contains no elements. 
    * 
    * @return <tt>true</tt> if this set contains no elements 
    */ 
    public boolean isEmpty() { 
     return map.isEmpty(); 
    } 

    /** 
    * Returns <tt>true</tt> if this set contains the specified element. 
    * More formally, returns <tt>true</tt> if and only if this set 
    * contains an element <tt>e</tt> such that 
    * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>. 
    * 
    * @param o element whose presence in this set is to be tested 
    * @return <tt>true</tt> if this set contains the specified element 
    */ 
    public boolean contains(Object o) { 
     return map.containsKey(o); 
    } 

    /** 
    * Adds the specified element to this set if it is not already present. 
    * More formally, adds the specified element <tt>e</tt> to this set if 
    * this set contains no element <tt>e2</tt> such that 
    * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>. 
    * If this set already contains the element, the call leaves the set 
    * unchanged and returns <tt>false</tt>. 
    * 
    * @param e element to be added to this set 
    * @return <tt>true</tt> if this set did not already contain the specified 
    * element 
    */ 
    public boolean add(E e) { 
     return map.put(e, PRESENT)==null; 
    } 

    /** 
    * Removes the specified element from this set if it is present. 
    * More formally, removes an element <tt>e</tt> such that 
    * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>, 
    * if this set contains such an element. Returns <tt>true</tt> if 
    * this set contained the element (or equivalently, if this set 
    * changed as a result of the call). (This set will not contain the 
    * element once the call returns.) 
    * 
    * @param o object to be removed from this set, if present 
    * @return <tt>true</tt> if the set contained the specified element 
    */ 
    public boolean remove(Object o) { 
     return map.remove(o)==PRESENT; 
    } 

    /** 
    * Removes all of the elements from this set. 
    * The set will be empty after this call returns. 
    */ 
    public void clear() { 
     map.clear(); 
    } 

    /** 
    * Returns a shallow copy of this <tt>HashSet</tt> instance: the elements 
    * themselves are not cloned. 
    * 
    * @return a shallow copy of this set 
    */ 
    @SuppressWarnings("unchecked") 
    public Object clone() { 
     try { 
      HashSet<E> newSet = (HashSet<E>) super.clone(); 
      newSet.map = (HashMap<E, Object>) map.clone(); 
      return newSet; 
     } catch (CloneNotSupportedException e) { 
      throw new InternalError(e); 
     } 
    } 

    /** 
    * Save the state of this <tt>HashSet</tt> instance to a stream (that is, 
    * serialize it). 
    * 
    * @serialData The capacity of the backing <tt>HashMap</tt> instance 
    *    (int), and its load factor (float) are emitted, followed by 
    *    the size of the set (the number of elements it contains) 
    *    (int), followed by all of its elements (each an Object) in 
    *    no particular order. 
    */ 
    private void writeObject(java.io.ObjectOutputStream s) 
     throws java.io.IOException { 
     // Write out any hidden serialization magic 
     s.defaultWriteObject(); 

     // Write out HashMap capacity and load factor 
     s.writeInt(map.capacity()); 
     s.writeFloat(map.loadFactor()); 

     // Write out size 
     s.writeInt(map.size()); 

     // Write out all elements in the proper order. 
     for (E e : map.keySet()) 
      s.writeObject(e); 
    } 

    /** 
    * Reconstitute the <tt>HashSet</tt> instance from a stream (that is, 
    * deserialize it). 
    */ 
    private void readObject(java.io.ObjectInputStream s) 
     throws java.io.IOException, ClassNotFoundException { 
     // Read in any hidden serialization magic 
     s.defaultReadObject(); 

     // Read capacity and verify non-negative. 
     int capacity = s.readInt(); 
     if (capacity < 0) { 
      throw new InvalidObjectException("Illegal capacity: " + 
              capacity); 
     } 

     // Read load factor and verify positive and non NaN. 
     float loadFactor = s.readFloat(); 
     if (loadFactor <= 0 || Float.isNaN(loadFactor)) { 
      throw new InvalidObjectException("Illegal load factor: " + 
              loadFactor); 
     } 

     // Read size and verify non-negative. 
     int size = s.readInt(); 
     if (size < 0) { 
      throw new InvalidObjectException("Illegal size: " + 
              size); 
     } 

     // Set the capacity according to the size and load factor ensuring that 
     // the HashMap is at least 25% full but clamping to maximum capacity. 
     capacity = (int) Math.min(size * Math.min(1/loadFactor, 4.0f), 
       HashMap.MAXIMUM_CAPACITY); 

     // Create backing HashMap 
     map = (((HashSet<?>)this) instanceof LinkedHashSet ? 
       new LinkedHashMap<E,Object>(capacity, loadFactor) : 
       new HashMap<E,Object>(capacity, loadFactor)); 

     // Read in all elements in the proper order. 
     for (int i=0; i<size; i++) { 
      @SuppressWarnings("unchecked") 
       E e = (E) s.readObject(); 
      map.put(e, PRESENT); 
     } 
    } 

    /** 
    * Creates a <em><a href="Spliterator.html#binding">late-binding</a></em> 
    * and <em>fail-fast</em> {@link Spliterator} over the elements in this 
    * set. 
    * 
    * <p>The {@code Spliterator} reports {@link Spliterator#SIZED} and 
    * {@link Spliterator#DISTINCT}. Overriding implementations should document 
    * the reporting of additional characteristic values. 
    * 
    * @return a {@code Spliterator} over the elements in this set 
    * @since 1.8 
    */ 
    public Spliterator<E> spliterator() { 
     return new HashMap.KeySpliterator<E,Object>(map, 0, -1, 0, 0); 
    } 
} 
+0

簡而言之,這些方法描述了應該如何進行序列化/反序列化。也可以在他們外部使用它們的東西聲明的小[從反射幫助](http://stackoverflow.com/a/11484158/1393766)。 – Pshemo

+0

誰是Netbeans然後抱怨'writeObject' resp。 'readObject'沒有被使用?它是否應該認爲這些可能被用於序列化? – skiwi

+1

@skiwi公平點。如果還沒有,請提交問題:https://netbeans.org/community/issues.html – Puce

回答

4

它們用於序列化。

你可以閱讀更多關於它在這裏:http://docs.oracle.com/javase/8/docs/platform/serialization/spec/serialTOC.html

我也可以推薦系列化線索的書「有效的Java」,由約書亞·布洛克。

+0

那麼這是如何工作的? Netbeans 8.0強調他們爲*未被使用*,我也沒有看到它們是一些接口的實現? – skiwi

+0

@skiwi我更新了我的答案。 – Puce

+0

這些是稱爲反射式的特殊方法。在分析「未使用」方法時,NetBeans可能應該更改以考慮到這一點。 –

2

它們被Java Object Serialization機制使用。可以在其規範中找到解釋:http://docs.oracle.com/javase/7/docs/platform/serialization/spec/serial-arch.html

對象序列化的標準實現實際上忽略了各個方法的可見性。

+0

Externalizable接口支持'writeExternal()'和'readExternal()'。標準序列化支持'writeObject'和'readObject'。 – Pshemo

+0

哦,你說得對。我會糾正我的答案。 –