具体的java方法返回空指针异常

时间:2013-08-13 11:37:28

标签: java nullpointerexception

我想指定特定节点是否与定义图中的节点集相邻?为此,我写了这个方法:

private boolean isNeighbor(ArrayList<Customer> collection, Customer node,DirectedSparseGraph<Customer, Transaction> network) throws SQLException {
        for(Customer customer:collection){
            if(network.isSuccessor(customer, node)) return true;
        }
        return false;
    }

遗憾的是,此方法返回空指针异常。所以我决定将其改为:

private boolean isNeighbor(ArrayList<Customer> collection, Customer node,DirectedSparseGraph<Customer, Transaction> network) throws SQLException {
        Collection<Customer> nodes=network.getVertices();
        ArrayList<Customer> acctualNodes = new ArrayList<Customer>();
        Customer acctualNode=new Customer();
        for(Customer customer: collection){
            for(Customer cust:nodes){
                if(cust.getName().equals(customer.getName())) acctualNodes.add(cust);
            }
        }
        for(Customer customer: nodes){
            if(node.getName().equals(customer.getName())) acctualNode=customer;
        }
        for(Customer customer: acctualNodes){
            if(network.isSuccessor(customer, acctualNode)) return true;
        }
        return false;
    }

新方法工作正常但需要大量资源和时间而且无用。我的问题是如何以定义的方法执行时间较短的方式处理空指针异常?

我调试了我的方法。以下是有关三个使用对象的信息:

collection: ArrayList<E> id=17
elementData Object[6246]  (id=37)   

node: Customer id=23
customerArray   null    
customerName    "9379090484" (id=1345)  
type    null    

network: DirectedSparseGraph<V,E> id=27
edge_type   EdgeType  (id=39)   
edges   HashMap<K,V>  (id=42)   
vertices    HashMap<K,V>  (id=47)   
entrySet    HashMap$EntrySet  (id=1349) 
hashSeed    -949367244  
keySet  HashMap$KeySet  (id=48) 
loadFactor  0.75    
modCount    64780   
size    64780   
table   HashMap$Entry<K,V>[131072]  (id=52) 
threshold   98304   
useAltHashing   false   
values  null

正如您所看到的,没有任何指定的对象为null!那么什么可能导致NPE?!

4 个答案:

答案 0 :(得分:1)

正如我所看到的,对于不同的集合,您有两个不同的同一对象实例。因此,您可以按名称搜索,这些行:

for(Customer customer: collection){
    for(Customer cust:nodes){
        if(cust.getName().equals(customer.getName())) acctualNodes.add(cust);
    }
}

然后使用isSuccessor方法获取正确的实例

如果我的假设是正确的那么你去的方式是:

private boolean isNeighbor(ArrayList<Customer> collection, Customer node,DirectedSparseGraph<Customer, Transaction> network) throws SQLException {
        HashMap<String, Customer> realNodes = new HashMap<String, Customer>();
        Collection<Customer> nodes=network.getVertices();

        for (Customer n: nodes) {
            realNodes.put(n.getName(), n);
        }

        Customer acctualNode = realNodes.get(node.getName());
        for(Customer customer:collection){
            Customer actualCustomer = realNodes.get(customer.getName());
            if(network.isSuccessor(actualCustomer, acctualNode)) {
                return true;
            }
        }
        return false;
    }

编辑 - 补充说明: 这将相对较快,但我相信网络对象的瓶颈,让所有节点对我来说都不好看。如果有一个方法通过名称返回CustomerNode,那么你需要使用它将所有对象放在HashMap中。

EDIT2 - 尝试加快速度。 我不知道你使用的包,但如果是这样,可能是jung实现的DirectSparseGraph。我在jung的源代码中找到了getSuccessor方法的实现:

public Collection<V>  getSuccessors(V vertex)
    {
        if (!containsVertex(vertex))
            return null;
        return Collections.unmodifiableCollection(getSuccs_internal(vertex));
    }

并且没有isSuccessor。我假设你的isSuccessor方法抛出NPE,因为getSuccessors方法返回null。它返回null,因为找不到传递的顶点。集合中的顶点使用equals方法进行比较。这是我的purpousal:在Customer对象中定义equals方法并按名称进行比较(更好地将equals和hashCode方法一起定义并从IDE生成它们 - Eclipse,IDEA,NetBeans):

public class Customer {
...
 private String name;

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Customer other = (Customer ) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
}

之后,您可以尝试使用第一种方法。如果它不起作用,那么我对isSuccessor方法和NPE的假设是不对的,你可以尝试定义自己的isSuccessor方法:

private boolean isNeighbor(ArrayList<Customer> collection, Customer node,DirectedSparseGraph<Customer, Transaction> network) throws SQLException {
        for(Customer customer:collection){
            //if(network.isSuccessor(customer, node)) { 
            if(isSuccessor(network, customer, node)) {
                return true;
            }
        }
        return false;
    }

    private boolean isSuccessor(DirectedSparseGraph<Customer, Transaction> network, Customer customer, Customer node) {
        Customer mockNode = node;
        Customer mockCustomer = customer;
        // If you can't redefine equals method for Customer object then you need to create a mock object mockNode.equals(node) == true && mockCustomer.equals(customer)
        Collection<Customer> successors = network.getSuccessors(mockNode);
        return successors != null && successors.indexOf(mockCustomer) != -1;
    }

如果无法为Customer对象重新定义equals方法,则需要先创建模拟对象,然后将其传递给网络对象,因此以下条件应为真:

mockNode.equals(node) && mockCustomer.equals(customer)

但如果你能定义equals和hasCode方法会更好,我相信它会对你有很大帮助。

答案 1 :(得分:0)

我不知道这是否是您正在寻找的,但如果您需要“微优化”,也许这会有所帮助:

private boolean isNeighbor(ArrayList<Customer> collection, Customer node,DirectedSparseGraph<Customer, Transaction> network) throws SQLException {
    if (network == null) {
        throw new IllegalArgumentException("Network may not be null.");
    }

    if (collection == null) {
        return false;
    }

    for(Customer customer : collection){
        if(network.isSuccessor(customer, node)) {
            return true;
        }
    }

        return false;
}

答案 2 :(得分:0)

在继续进行邻居分析之前检查是否为空。例如

private boolean isNeighbor(ArrayList<Customer> collection, Customer node, DirectedSparseGraph<Customer, Transaction> network) throws SQLException {
    if (null == collection || collection.size() == 0) {
        return false;
    } else {
        for (Customer customer : collection) {
            if (network.isSuccessor(customer, node)) return true;
        }
    }
    return false;

}  

同样,您必须对函数中的所有参数进行null检查以避免NPE。

答案 3 :(得分:0)

您也可以使用以下内容。

private boolean isNeighbor(ArrayList<Customer> collection, Customer node,DirectedSparseGraph<Customer, Transaction> network) throws SQLException {
    boolean isNeighbor = false;
    try {
        for(Customer customer:collection) {
            if (network.isSuccessor(customer, node)) {
                isNeighbor = true;
                break;
            }
        }
    }
    catch (NullPointerException npe) {
        npe.printStackTrace();
        isNeighbor = false;
    }

    return isNeighbor

}