随笔 - 4  文章 - 13  trackbacks - 0
<2009年1月>
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567

常用链接

留言簿(1)

随笔档案

搜索

  •  

最新评论

阅读排行榜

评论排行榜

情景上这样的:我有一个重写了equals方法的类,该类源码如下。然后用一程序将此类多次循环put到HashMap中去,但每次put到1500次左右时,就会出现NullPointerException。
  在map.put的方法中,会先去判断put进去的对象是否已经存在于map中,判断方法调用的就是该对象的重写的equals方法,如果说我写的equals有问题的话,为什么前1000多次左右不会出现问题而在最后出现问题呢?起初以为是放到HashMap中的对象太大会出现内存溢出,但并未出现outofmemory异常,用JProfiler进行监测时也发现和heap的使用也没关系……有哪位兄弟帮我解释一下……

  重写了equals方法的类:
public class myPolSchema {
    
// @Field
    private String GrpContNo;
    
private String GrpPolNo;

    
public String getGrpContNo() {
        
return GrpContNo;
    }


    
public void setGrpContNo(String aGrpContNo) {
        GrpContNo 
= aGrpContNo;
    }


    
public String getGrpPolNo() {
        
return GrpPolNo;
    }


    
public void setGrpPolNo(String aGrpPolNo) {
        GrpPolNo 
= aGrpPolNo;
    }


    
public boolean equals(Object otherObject) {
        
if (this == otherObject)
            
return true;
        
if (otherObject == null)
            
return false;
        
if (getClass() != otherObject.getClass())
            
return false;
        myPolSchema other 
= (myPolSchema) otherObject;
        
return GrpContNo.equals(other.getGrpContNo())
                
&& GrpPolNo.equals(other.getGrpPolNo());
    }

}

测试类:

import java.util.* ;
public class MultiThreading{
// implements Runnable 
    Map m=Collections.synchronizedMap(new HashMap());
    
//HashMap m=new HashMap();
    Hashtable t=new Hashtable();
    
public myPolSchema polschema;
    
public void run() 
    
{
        polschema
=new myPolSchema();
        m.put(polschema, 
"UPDATE");
        System.out.println(
"put end at " + new Date());
    }

    
public static void main(String[] args) throws Exception {
        MultiThreading t
=new MultiThreading();
        
for(int i=0;i<=25000;i++){
            
try{
                t.run();
                
//Thread.sleep(100);
            }

            
catch(Exception ex){
                
//在我本地测试时当运行大概1500左右次的时间就会抛出NullPointerException
                System.out.println("i is: " + i);
                
throw ex;
            }

        }

    }


}

如果您有兴趣,请下载这两个类的源码并实际测试:
/Files/foxinsky/sourceCode.rar
如果哪位兄台有好的解决方案,请不吝赐教!
posted on 2009-01-14 12:34 foxinsky 阅读(1814) 评论(10)  编辑  收藏

FeedBack:
# re: 我无法解释的问题,请您一并来解释 2009-01-14 12:54 银河使者
只1500次,不可能产生内存溢出异常,根据你的描述是抛出NullPointerException异常,这说明你引用了一个对象变量,但这个对象变量值为null,问题出在equals方法中,有可能出在下面的代码中:

myPolSchema other = (myPolSchema) otherObject;
return GrpContNo.equals(other.getGrpContNo())
&& GrpPolNo.equals(other.getGrpPolNo());
上面的代码有可能other.getGrpConNo方法返回一个null,顺便问一下,GrpContNo字段在什么时候赋的值?  回复  更多评论
  
# re: 我无法解释的问题,请您一并来解释 2009-01-14 12:57 ourjavasky
# re: 我无法解释的问题,请您一并来解释 2009-01-14 13:37 lvq810
一楼是对的,类的属性未赋值为Null,null值equals()就会出现NullPointerException  回复  更多评论
  
# re: 我无法解释的问题,请您一并来解释 2009-01-14 13:39 Julia
If you use object as key for Hashtable, you should override both
equals() and hashCode() methods. Please see link

http://www.ibm.com/developerworks/java/library/j-jtp05273.html
  回复  更多评论
  
# re: 我无法解释的问题,请您一并来解释 2009-01-14 13:43 foxinsky
@lvq810
4楼给出的解释应该是正确的。下面是CSDN的网友MT502给出的解答:
MAP在执行put()的时候先调用myPolSchema的hashCode()方法看当前有没有一样的hashCode存在,如果没有就直接put,有的话就调用myPolSchema的equals()方法看是否相等。
因为你没有实现hashCode(),所以用默认的hashCode(),所以当产生相同的hashCode的时候(在我机器上是运行到2058时),因为检查到相同的hashcode,所以调用你自己的equals(),因为GrpContNo是null,所以这时候抛NullPointerException 。
你机器上显然是在1500的时候产生了相同了hashcode()。
如果实现了hashCode(),第一次就抛NullPointerException :

Java codepublic int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
+ ((GrpContNo == null) ? 0 : GrpContNo.hashCode());
result = prime * result
+ ((GrpPolNo == null) ? 0 : GrpPolNo.hashCode());
return result;
}


我现在在想,如何去重写hashCode方法才能保证生成的hashCode值不同呢……

或者去修改我的equals算法,在调用之前先去判断一下other.getGrpContNo==null(这两种方法怎么实现起来才算是比较合理的算法呢?

  回复  更多评论
  
# re: 我无法解释的问题,请您一并来解释 2009-01-14 13:57 lvq810
只有修改equals加上判断  回复  更多评论
  
# re: 我无法解释的问题,请您一并来解释 2009-01-14 21:43 darkmagician
如果equals是true,hashcode必须相同。 没必要担心不同的object有相同的hashcode, 否则还要equals干嘛, 保证hashcode分散,只是提高效率而已。  回复  更多评论
  
# re: 我无法解释的问题,请您一并来解释[未登录] 2009-01-15 08:40 nile black
MAP在执行put()的时候先调用myPolSchema的hashCode()方法看当前有没有一样的hashCode存在,如果没有就直接put,有的话就调用myPolSchema的equals()方法看是否相等。
因为你没有实现hashCode(),所以用默认的hashCode(),所以当产生相同的hashCode的时候(在我机器上是运行到2058 时),因为检查到相同的hashcode,所以调用你自己的equals(),因为GrpContNo是null,所以这时候抛 NullPointerException 。
你机器上显然是在1500的时候产生了相同了hashcode()。
如果实现了hashCode(),第一次就抛NullPointerException :   回复  更多评论
  
# re: 我无法解释的问题,请您一并来解释 2009-01-19 12:37 娃娃
楼上这个师傅解释很正确,学习了,记得考scjp的时候,有过一个题  回复  更多评论
  
# re: 我无法解释的问题,请您一并来解释 2009-01-20 14:55 笨牛
public class myPolSchema {
private String GrpContNo;
private String GrpPolNo;
public String getGrpContNo() {
return GrpContNo;
}
public void setGrpContNo(String aGrpContNo) {
GrpContNo = aGrpContNo;
}
public String getGrpPolNo() {
return GrpPolNo;
}
public void setGrpPolNo(String aGrpPolNo) {
GrpPolNo = aGrpPolNo;
}
public myPolSchema(String GrpContNo,String GrpPolNo){
this.GrpContNo=GrpContNo;
this.GrpPolNo=GrpPolNo;
}
public boolean equals(Object otherObject) {
if (this == otherObject)
return true;
if (otherObject == null)
return false;
if (getClass() != otherObject.getClass())
return false;
if(!(otherObject instanceof myPolSchema)){
return false;
}else{
myPolSchema other = (myPolSchema) otherObject;
return GrpContNo.equals(other.getGrpContNo())
&& GrpPolNo.equals(other.getGrpPolNo());
}
}

}

---------------------------

import java.util.* ;
public class MultiThreading{
// implements Runnable
Map m=Collections.synchronizedMap(new HashMap());
//HashMap m=new HashMap();
Hashtable t=new Hashtable();
public myPolSchema polschema;
public void run(int i)
{
polschema=new myPolSchema(i+"",i+"");
m.put(polschema, "UPDATE");
System.out.println("put end at " + new Date());
}
public static void main(String[] args) throws Exception {
MultiThreading t=new MultiThreading();
for(int i=0;i<=25000;i++){
try{
t.run(i);
//Thread.sleep(100);
}
catch(Exception ex){
//在我本地测试时当运行大概1500左右次的时间就会抛出NullPointerException
System.out.println("i is: " + i);
throw ex;
}
}
}

}


构造方法啊大哥 不赋值怎么能比较呢  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: