【问题标题】:Method returns null and tries to call method方法返回 null 并尝试调用方法
【发布时间】:2017-05-07 02:18:22
【问题描述】:

我有一个小但非常烦人的错误。

实际上,我正在编写家谱,在某些情况下我会搜索一个人,但有时该人不在树中(有道理)。所以我的方法返回null。

问题是当我尝试做这样的事情时。

familytree.getNode("Peter").getName();

Peter 不在树中,但他试图获取名称,我的代码给了我一个 NullPointerException(再次有意义)。

虽然我不知道如何处理这种问题,但我有很多类似的方法,例如 getName()... 例如 getGender()getWife()

我有两个类,familytree(带有搜索、删除等方法)和节点(带有有关此人的所有信息)。

也许你们有一个想法!

编辑:

例如这是我的主要方法;

familytree.getNode("Fred").getGender(); //布尔值

familytree.getNode("Max").getGender();

familytree.getNode("Peter").getGender();

familytree.getNode("Fe").getPartner(); //合作伙伴名称

familytree.getNode("Freddyy").getName(); //字符串

如何检查每个案例是否为空指针?

【问题讨论】:

  • Node 是框架类还是你自己的代码?如果后者最好的方法是返回一个虚拟元素而不是 null
  • @TimothyTruckle 好吧,“虚拟”元素有时是有意义的;但在这里,很难。为“空”的假人定义“正确”的语义看起来很难。我不认为这是自然的第一个解决方案。
  • @GhostCat 我会说这是一个有用的虚拟元素的完美例子。 OP 在想要访问元素上的 getter 的程序中有很多代码。空检查的唯一原因是显示一些替换文本,这些替换文本也可以从虚拟对象中获取。
  • @TimothyTruckle 那么请向我解释一个“虚拟”人的语义。假人几岁?它叫什么名字?你如何对一个包含 3 个真人和 7 个假人的数组进行排序?继续进行。您现在只是将 *real 问题转移到许多不同的地方。突然之间,你有 50 种方法需要对假人进行特殊处理。
  • @GhostCat “那么请给我解释一下“Dummy”人的语义。Dummy 人多大?它叫什么名字?” null,你会打印出什么名字/年龄?不从假人那里得到那些“空替换”的确切原因是什么?

标签: java exception null


【解决方案1】:

如果您使用的是 java 8,而不是检查 null,请尝试使用 可选

也许这个话题可以帮到你:Uses for Optional

一开始使用 Optional 可能看起来像更多代码,但最终它更干净、更有效。

【讨论】:

  • 你肯定是对的;但是这个人在理解返回 null 需要检查 null 时遇到了问题。不确定 Optionals 是否真的适合他。
  • 不,检查是否为零不是问题,问题是我如何避免空(对象)尝试调用某些方法...
  • @Nado 您已被反复告知该怎么做。问题是:您如何实现您的应用程序的想法简直是破碎没有点你坚持“但我想这样做this方式”......因为this你的方式不工作。请接受现实,阅读您向我们提出的建议......然后继续。
  • 好的,那么请在问题中使用我的版本,并告诉我如何处理这个问题。
  • @Nado:我们必须多久告诉您一次不能保持代码不变?你的方法是破碎,并坚持“但我想保持这种方式”浪费你的时间......和我们的。您添加的代码可以将那些 NullPointerExceptions 到处抛出。您必须重新设计您的设计,以某种方式处理您的查找返回 null 或为空的 Optional 的事实。
【解决方案2】:

简单的想法:不要那样做!

如果您的方法可以返回 null,那么您必须为此检查,例如:

Person p = familytree.getNode("Peter");
if (p != null) {
 do something with p.getName();
} else {
 tell user: Peter is not known!

或者,预先检查:

if (familytree.contains("Peter")) {
  p = familytree.getNode("Peter"); // will be save

【讨论】:

  • 是的,但是当我尝试获取名称时,我必须检查所有内容
  • 当然。作为 Java 程序员,您一生中可能有 25% 的时间是检查空值。如果您设计了一个允许返回null的接口,那么是的,您必须检查该接口的每个和任何用法。另一种方法是提出永远不会返回 null 的方法。对于这种地图/查找代码来说,这很难。
【解决方案3】:

你应该做类似的事情

Node node = familytree.getNode("Peter");
if ( null == node ){

    return "non existant";
}

String name = node.getName();

【讨论】:

  • 是的,这是有道理的,但我有几种方法,返回布尔值、节点、字符串等。
【解决方案4】:

编辑:实际上,当找不到节点时,您可以在 FamilyTree#getNode 返回默认节点而不是 null,这应该是正确的方法。


或者您可以使用 Java8 Optional 并在每次调用时决定如果 getNode 为空该怎么办:

关键是修改FamilyTree#getNode方法使用Optional.ofNullable 然后使用 map 和 orElse 处理可能的 null 值,提供默认值或获取实际属性。

看到这个:

static class FamilyTree {
    private Map<String, Node> nodes = new HashMap<>();
    // put some values in this map

    Optional<Node> getNode(String key) {
        return Optional.ofNullable(this.nodes.get(key));
    }
}

static class Node {
    private boolean gender;
    private String partner;
    private String name;

    boolean getGender() {
        return this.gender;
    }

    String getPartner() {
        return this.partner;
    }

    String getName() {
        return this.name;
    }
}

@Test
public void test_nado() {
    FamilyTree familytree = new FamilyTree();

    familytree.getNode("Fred").map(Node::getGender).orElse(false); //boolean
    familytree.getNode("Max").map(Node::getGender).orElse(false);
    familytree.getNode("Peter").map(Node::getGender).orElse(false);
    familytree.getNode("Fe").map(Node::getPartner).orElse(""); //Partner Name
    familytree.getNode("Freddyy").map(Node::getName).orElse(""); //String
}

【讨论】:

  • map 告诉可选的如果它的值不为空(这里使用getter)如何处理它,如果它为空则什么也不做。 orElse 如果可选值为 null,则提供默认值。
  • 如前所述:我看不出这真的有什么帮助。想象一下,你问你的同事:“你能在电话簿中查找 X 并告诉我他的号码吗?”你的同事回来说“它是 000-000-000”,因为实际上 X 不在电话簿中,而那些零是“空人”的默认电话号码 --- 你认为这些号码对你有帮助吗?如果您被告知“X 不在电话簿中”,那不是更好吗?现在必须弄清楚“哦,000....意味着X是未知的”。
猜你喜欢
  • 2020-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-26
  • 2020-12-06
  • 2021-01-14
  • 2020-05-24
  • 2022-08-05
相关资源
最近更新 更多