< prev index next >

src/java.base/share/classes/java/util/WeakHashMap.java

Print this page
@@ -1,7 +1,7 @@
  /*
-  * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
+  * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.  Oracle designates this

@@ -23,12 +23,12 @@
   * questions.
   */
  
  package java.util;
  
- import java.lang.ref.WeakReference;
  import java.lang.ref.ReferenceQueue;
+ import java.lang.ref.WeakReference;
  import java.util.function.BiConsumer;
  import java.util.function.BiFunction;
  import java.util.function.Consumer;
  
  

@@ -120,10 +120,26 @@
   *
   * <p>This class is a member of the
   * <a href="{@docRoot}/java.base/java/util/package-summary.html#CollectionsFramework">
   * Java Collections Framework</a>.
   *
+  * @apiNote
+  * <div class="preview-block">
+  *      <div class="preview-comment">
+  *          Objects that are {@linkplain Class#isValue() value objects} do not have identity
+  *          and can not be used as keys in a {@code WeakHashMap}. {@linkplain java.lang.ref.Reference References}
+  *          such as {@linkplain WeakReference WeakReference} used by {@code WeakhashMap}
+  *          to hold the key cannot refer to a value object.
+  *          Methods such as {@linkplain #get get} or {@linkplain #containsKey containsKey}
+  *          will always return {@code null} or {@code false} respectively.
+  *          The methods such as {@linkplain #put put}, {@linkplain #putAll putAll},
+  *          {@linkplain #compute(Object, BiFunction) compute}, and
+  *          {@linkplain #computeIfAbsent(Object, Function) computeIfAbsent} or any method putting
+  *          a value object, as a key, throw {@link IdentityException}.
+  *      </div>
+  * </div>
+  *
   * @param <K> the type of keys maintained by this map
   * @param <V> the type of mapped values
   *
   * @author      Doug Lea
   * @author      Josh Bloch

@@ -286,10 +302,12 @@
      }
  
      /**
       * Checks for equality of non-null reference x and possibly-null y.  By
       * default uses Object.equals.
+      * The key may be a value object, but it will never be equal to the referent
+      * so does not need a separate Objects.hasIdentity check.
       */
      private boolean matchesKey(Entry<K,V> e, Object key) {
          // check if the given entry refers to the given key without
          // keeping a strong reference to the entry's referent
          if (e.refersTo(key)) return true;

@@ -454,13 +472,15 @@
       * @param value value to be associated with the specified key.
       * @return the previous value associated with {@code key}, or
       *         {@code null} if there was no mapping for {@code key}.
       *         (A {@code null} return can also indicate that the map
       *         previously associated {@code null} with {@code key}.)
+      * @throws IdentityException if {@code key} is a value object
       */
      public V put(K key, V value) {
          Object k = maskNull(key);
+         Objects.requireIdentity(k);
          int h = hash(k);
          Entry<K,V>[] tab = getTable();
          int i = indexFor(h, tab.length);
  
          for (Entry<K,V> e = tab[i]; e != null; e = e.next) {

@@ -544,12 +564,17 @@
      /**
       * Copies all of the mappings from the specified map to this map.
       * These mappings will replace any mappings that this map had for any
       * of the keys currently in the specified map.
       *
+      * @apiNote If the specified map contains keys that are {@linkplain Objects#isValueObject value objects}
+      * an {@linkplain IdentityException } is thrown when the first value object key is encountered.
+      * Zero or more mappings may have already been copied to this map.
+      *
       * @param m mappings to be stored in this map.
       * @throws  NullPointerException if the specified map is null.
+      * @throws  IdentityException if any of the {@code keys} is a value object
       */
      public void putAll(Map<? extends K, ? extends V> m) {
          int numKeysToBeAdded = m.size();
          if (numKeysToBeAdded == 0)
              return;
< prev index next >