Java中为GC置空对象与WeakReference的对比
Great question—this is a super common point of confusion because weak references don’t show their value in trivial examples like the one you shared. Let’s break down the difference and when weak references actually shine.
First, Your Example: Why They Look the Same
Let’s start with your two code snippets.
First, with WeakReference:
Integer prime = 1; WeakReference<Integer> soft = new WeakReference<>(prime); prime = null;
Second, without it:
Integer prime = 1; prime = null;
In both cases, the Integer object (value 1) will get garbage collected eventually. That’s because once you set prime = null, there are no strong references left pointing to the object. Weak references don’t count as strong references, so the GC treats the object as eligible for collection either way.
So why bother with WeakReference here? You’re right—this scenario doesn’t demonstrate its purpose. Weak references are useful when you need two things at once:
- You want to keep a way to access an object if it’s still alive (has other strong references).
- You don’t want your reference to prevent the object from being garbage collected when no one else needs it.
The Real-World Use Case: Caching
The classic example is caching. Let’s say you’re building an image loader for an app:
- You load images from disk/network and store them in a cache so you don’t reload them constantly.
- But you don’t want the cache to hog memory indefinitely—if an image isn’t being used (no strong references from UI elements), it should be eligible for GC when memory is tight.
A WeakHashMap (which uses weak references for keys) is perfect here. When an image’s key loses all strong references, the entry gets automatically removed from the map, and the image can be GC’d.
Here’s a simplified code example:
// Cache that uses weak references for keys WeakHashMap<String, Bitmap> imageCache = new WeakHashMap<>(); // Load an image and store it in cache Bitmap profilePic = loadBitmapFromDisk("profile.jpg"); imageCache.put("profile.jpg", profilePic); // When the UI uses this image, it holds a strong reference imageView.setImageBitmap(profilePic); // Later, if the UI stops using the image (e.g., user navigates away) profilePic = null; // Now, the only reference to the Bitmap is the weak one in the cache. // When GC runs, the Bitmap will be collected, and the cache entry will be removed automatically. // If another part of the app tries to get "profile.jpg" before GC, it can still reuse the existing Bitmap! Bitmap cachedPic = imageCache.get("profile.jpg"); if (cachedPic != null) { // Reuse the existing bitmap instead of reloading imageView.setImageBitmap(cachedPic); } else { // Bitmap was GC'd, reload it cachedPic = loadBitmapFromDisk("profile.jpg"); imageCache.put("profile.jpg", cachedPic); imageView.setImageBitmap(cachedPic); }
The Core Difference
- Setting the strong reference to null: You lose all access to the object immediately. Even if the object hasn’t been GC’d yet (GC doesn’t run instantly), you can’t get it back.
- Using a WeakReference: You retain a "hook" to the object. As long as the object has at least one strong reference elsewhere,
weakRef.get()will return it. Once all strong references are gone, the object becomes eligible for GC—but you can still check if it’s alive before it’s collected and reuse it if possible.
Another Concrete Example
Let’s expand your initial code to show the difference:
// With WeakReference Integer prime = 1; WeakReference<Integer> weakPrime = new WeakReference<>(prime); prime = null; // Before GC runs, we can still retrieve the object! Integer retrievedPrime = weakPrime.get(); if (retrievedPrime != null) { System.out.println("Got the prime back: " + retrievedPrime); // This will print if GC hasn't run yet } else { System.out.println("Prime was already GC'd"); } // Without WeakReference Integer prime2 = 1; prime2 = null; // There's no way to get this object back—we lost all references to it // Integer retrievedPrime2 = ??? // Impossible
In this expanded example, the WeakReference lets you recover the object before GC collects it, which you can’t do when you just set the strong reference to null.
内容的提问来源于stack exchange,提问作者Nick




