package statictest;
import java.util.*;
class A
{
int a=3;
String str="hello";

public String toString() 
{
return str+String.valueOf(a);
}
}public class StaticTest
{
public static void main(String[] args) throws Exception
{
    Map map=new WeakHashMap();     
    String a="a";
    String av="av";
    A ca=new A();
    map.put("ca", ca);
    map.put(a, av);    
    System.out.println(map);    
    System.gc(); 
    a=null;
    ca=null;    
    Thread.sleep(1000);
    System.gc();    
    System.gc();      
    System.out.println(map);

    /*运行结果:
    {a=av, ca=hello3}
    {a=av, ca=hello3}
两次一样*/
    
    Map map2=new WeakHashMap();
    map2.put("obj", new A());
    A xyz=(A)map2.get("obj");
    System.out.println(map2);
    xyz.a=10000;
    System.out.println(map2);
    /*运行结果:
          {obj=hello3}
  {obj=hello10000}
    对象的成员变量可改变*/     
}}疑惑1:
为什么我把WeakHashMap的键设为了null,而且也调用了垃圾回收器,也让主线程休眠了一段时间,可是这个map还是不放掉这一对值?
疑惑2:
map里的值存的一律是引用,可是为什么我将第一个map的键ca对应的值设为了null,可是它打印出来还是原来的值?而第二个map2里面我更改了它里面保存对象的成员值后,能反应出正确的结果?

解决方案 »

  1.   

    为什么会这样呢?lz运行的程序是不是有点问题?import java.util.*;
    class Mouse
    {
    private int i;
    Mouse(int i){
    this.i=i;
    }
    public String toString(){return "Mouse "+i;}
    }
    public class Test2
    {
    public static void main(String[] args)
    {
    Map hashMap=new WeakHashMap();
    Mouse s=new Mouse(1);
    s=null;
    hashMap.put(s,new Integer(1));
    //s=null;
    System.out.println(hashMap);
    }
    }
    java Test2
    打印:null=1
      

  2.   

    如楼上所说,如果显式的把键设为null,是可以加进去的,如果键是一个对象,不是字符串,则当这个对象为null时,weakhashmap 会自动减小容量,把这个键值对删出集合中.
    字符串表现出的性质让人百思不解,它虽然是最终类,可是集合里保存的是引用,不是它本身,理说这个引用会指向新对象,可是为什么还是指向老对象呢?老对象不是应该会GC回收的吗?
    代码如下:
    package statictest;
    import java.util.*;
    import java.lang.ref.*;
    import java.lang.ref.*;class A
    {
    int a=3;
    String str="hello";

    public String toString() 
    {
    return str+a;
    }
    }public class StaticTest
    {
    public static void main(String[] args) throws Exception
    {
        Map map=new WeakHashMap();  
        String b="this is b:";    
        A ab=new A();
        map.put(ab, new A());
        map.put(b, "b");
        System.out.println(map);
        String c=(String)map.get(b);
        c=null;  //把键b的值设为null,但打印出来却没有变化.
        ab=null; //由于ab是一个类对象的引用,所以会被移出map   
        b=null;  //可是键b也是一个对象,为什么置为null时会没变化呢??    
        System.gc();  //一定要调用,否则GC来不及回收,仍会打印出原来的键值对     
        System.out.println(map); 
    }}
    打印结果:
    {hello3=hello3, this is b:=b}
    {this is b:=b}
      

  3.   

    有这样一段相关描述This class will work perfectly well with key objects whose equals methods are not based upon object identity, such as String instances. With such recreatable key objects, however, the automatic removal of WeakHashMap entries whose keys have been discarded may prove to be confusing. String instance是recreatable key object
    再者可能也是由于gc()只回收堆区而非栈区的垃圾内存
    导致了这种情况的发生。
      

  4.   

    三楼说的对gc()只回收堆区,而String   b= "this   is   b: ";  b只是存放在字符串池中,如果new一个对象出来就对了import java.util.Map;
    import java.util.WeakHashMap;
    class   StaticTest 

    int   a=3; 
    String   str= "hello "; public   String   toString()   

    return   str+a; 

    public   static   void   main(String[]   args)   throws   Exception 

            Map   map=new   WeakHashMap();   
            String   b= new String("this   is   b: ");       
            StaticTest   ab=new   StaticTest(); 
            map.put(ab,   new   StaticTest()); 
            map.put(b,   "b "); 
            System.out.println(map); 
            String   c=(String)map.get(b); 
            c=null;     //把键b的值设为null,但打印出来却没有变化. 
            ab=null;   //由于ab是一个类对象的引用,所以会被移出map     
            b=null;     //b在堆内存中,这下没打印出东西来了       
            System.gc();     //一定要调用,否则GC来不及回收,仍会打印出原来的键值对         
            System.out.println(map);   

    } {this   is   b: =b , hello 3=hello 3}
    {}