问题描述
考虑以下Java源代码:if(agents!= null){
for(Iterator iter = agents.keySet()。iterator(); iter.hasNext();){
//使用iter.next()...的代码...
//
}
}
agents 是一个 HashMap 。
为什么语句的有时会抛出 NullPointerException ?
谢谢。
线程安全
如果您的代码是多线程的,那么这是可能的。例如:
public class C {
private Hashtable agents = new Hashtable();如果(代理!= null){
for(Iterator iter = agents.keySet()。iterator(); iter.hasNext();
public iterate(){
){
// Code goes here
}
}
}
如果另一个线程立即在之后设置 agents 到 null if 语句执行(但在 for 循环之前),那么你将得到一个 NullPointerException 。避免使用访问器(与延迟初始化结合)。
另外,正如其他人所提到的,如果可能的话,应避免使用这种循环结构来支持泛型。
$ b 访问者提供的保护
public class C {
private Hashtable agents;
private synchronized Hashtable getAgents(){
if(this.agents == null){
this.agents = new Hashtable();
}
返回this.agents;
public iterate(){
Hashtable agents = getAgents();
(Iterator iter = agents.keySet()。iterator(); iter.hasNext();){
// Code goes here
}
}
}
迭代代理的代码不再需要检查空。由于许多原因,此代码更加冗余。您可以用 Hashmap (或任何其他抽象数据类型,例如 ConcurrentHashMap< K,V> )替换 Hashtable 。
开放原则
如果你对自己的时间特别慷慨,那么你可以尽量做到这一点:
public class C {
私有Hashtable代理;
private synchronized Hashtable getAgents(){
if(this.agents == null){
this.agents = createAgents();
}
返回this.agents;
public iterate(){
Iterator i = getAgentKeyIterator();
while(i.hasNext()){
//使用i.next()...
}
}
$ b的代码$ b保护Hashtable createAgents(){
返回新的Hashtable();
}
private Iterator getAgentKeyIterator(){
return getAgentKeys()。iterator();
}
私钥KeySet getAgentKeys(){
return getAgents()。keySet();
$ b $ p
$ b $这样可以让子类(由其他开发者编写)用他们自己的正在使用的抽象数据类型的子类来替换(允许系统在保持),而无需修改(或复制/浪费)您的原作。Consider the following Java source:
if( agents != null ) { for( Iterator iter = agents.keySet().iterator(); iter.hasNext(); ) { // Code that uses iter.next() ... // } }The agents is a HashMap.
Why does the for statement sometimes throw a NullPointerException?
Thank you.
解决方案Thread Safety
If your code is multi-threaded, then it is possible. For example:
public class C { private Hashtable agents = new Hashtable(); public iterate() { if( agents != null ) { for (Iterator iter = agents.keySet().iterator(); iter.hasNext();) { // Code goes here } } }If another thread sets agents to null immediately after the if statement executes (but before the for loop), then you will get a NullPointerException. Avoid this by using accessors (combined with lazy initialization).
Also, as others have mentioned, avoid such looping constructs in favour of generics, if possible. See other answers for details.
Accessors offer Protection
If you always use the following pattern you will never have NullPointerExceptions in your source code (third-party code, on the other hand, might have issues that cause your code to fail, indirectly, which cannot be easily avoided).
public class C { private Hashtable agents; private synchronized Hashtable getAgents() { if( this.agents == null ) { this.agents = new Hashtable(); } return this.agents; } public iterate() { Hashtable agents = getAgents(); for (Iterator iter = agents.keySet().iterator(); iter.hasNext();) { // Code goes here } } }The code that iterates over the agents no longer needs to check for null. This code is much more robost for many reasons. You can substitute Hashmap (or any other abstract data type, such as ConcurrentHashMap<K,V>) for Hashtable.
Open-Closed Principle
If you were feeling especially generous with your time you could go as far as:
public class C { private Hashtable agents; private synchronized Hashtable getAgents() { if( this.agents == null ) { this.agents = createAgents(); } return this.agents; } public iterate() { Iterator i = getAgentKeyIterator(); while( i.hasNext() ) { // Code that uses i.next() ... } } protected Hashtable createAgents() { return new Hashtable(); } private Iterator getAgentKeyIterator() { return getAgentKeys().iterator(); } private KeySet getAgentKeys() { return getAgents().keySet(); } }This would allow subclasses (written by other developers) to substitute their own subclass of the abstract data type being used (allowing the system greater flexibility in keeping with the Open-Closed Principle), without having to modify (or copy/waste) your original work.
这篇关于为什么这段代码有时会抛出一个NullPointerException?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!