Java 空指针无处不在,因为数据突然变得稀疏

Java 空指针无处不在,因为数据突然变得稀疏,java,refactoring,nullpointerexception,Java,Refactoring,Nullpointerexception,有人设计了依赖于完整数据的代码;XML总是包含所有元素。数据源现在正在发送稀疏XML;如果它以前是空的,现在就不见了。所以,是时候在修复bug的同时进行重构了 有100多行这样的代码: functionDoSomething(foo, bar, getRoot().getChild("1").getChild("A"). getChild("oo").getContent()); 除了现在,getChild(“A”)可能返回null。或者任何getChild(xxx)方法都可以 作为另

有人设计了依赖于完整数据的代码;XML总是包含所有元素。数据源现在正在发送稀疏XML;如果它以前是空的,现在就不见了。所以,是时候在修复bug的同时进行重构了

有100多行这样的代码:

functionDoSomething(foo, bar, getRoot().getChild("1").getChild("A").
    getChild("oo").getContent());
除了现在,getChild(“A”)可能返回null。或者任何getChild(xxx)方法都可以

作为另一个转折点,与getChild()不同,实际上有四个单独的方法,它们只能按特定顺序出现。有人建议打一个Varags电话,这不是个坏主意,但不会像我希望的那样干净

清理这个最快的方法是什么?最好的?每一条线都有人建议“尝试/抓住”,但伙计,这太难看了。将上述方法的第三个参数分解为它自己的函数可能会起作用。。。但这将需要100多种新方法,这让人感觉很难看,尽管不那么难看

getChild(xxx)调用的数量在每行6到10之间,没有固定的深度。对于这一点,也没有可能获得正确的DTD;稍后将在没有事先提示的情况下添加内容,我更希望在发生这种情况时在日志中显示警告,XML中的额外行需要优雅地处理

想法


实际上,getChild()是一个方便的方法。我想到的最简洁的方法是让便利方法返回一个有效的子对象,但让“空”子对象的getContent()始终返回“.”。

解决方案是对XML使用DTD文件。它验证您的XML文件,这样当A是必需的时,
getChild(“A”)
就不会返回null。

如果它总是深入到大致相同的级别,您可能可以使用Eclipse重构代码,例如,它会自动更改看起来相同的每一行

通过这种方式,您可以将方法修改得更智能,而不是单独修改每一行。

您所描述的(返回一个特殊的子对象)是模式的一种形式,这可能是这里最好的解决方案。

如何:

private Content getChildContent(Node root, String... path) {
    Node target = root;
    for ( String pathElement : path ) {
         Node child = target.getChild(pathElement);
         if ( child == null ) 
            return null; // or whatever you should do

         target = child;
    }

    return target.getContent();

}
用作

functionDoSomething(foo, bar, getChildContent(root, "1", "A", "oo"));

请考虑使用XPath代替这个混乱。

< P>您的问题可能是一个设计问题: 如果不是,您可以使用诸如将getChild的返回类型更改为选项之类的选项:

这是因为选项实现了Iterable,当未定义返回值时,它将中止。这与Scala类似,Scala可以用一个for表达式来表示

另一个优点是,您可以定义永不返回空值的接口。使用选项类型,您可以在接口定义中声明返回值可能未定义,并且客户机可以决定如何处理


不幸的是,没有这样的运气。它可以深入到半打级别中的任何一个,六到十个级别,不同的元素取决于它的分支方式。我没有,而且它一直在我身上轻微变化。以前的解决方案至少在抛出新内容时会让它优雅地失败。实际调用每行使用.getChild(xxx)6到10次,没有固定的深度。路径是一个var arg,它被转换为一个数组,因此您可以让路径使用任意多的参数。这不符合您的用例吗?例如,您可以将getChildContent(根,“a”,“b”)和getChildContent(根,“d”,“E”,“f”)与此签名一起使用。实际上,有不同类型的子项,它们会产生另一种扭曲。getEle、getComp、getLoop和getSeg,它们都可以以不同的顺序出现,并且具有不同的潜在子级。似乎我从原来的问题中剥离了太多内容,将重新添加该细节。这不是一个坏主意,因为我的映射是用(半正确的)XPATH提供给我的。这是我看到示例代码行后的最初反应。它只是因为使用XPath而尖叫。是的,它现在正在工作,虽然不像我在XPath中重写一些代码那样干净。
for(Node r : getRoot())
  for(Node c1 : r.getChild("1"))
    for(Node c2: c1.getChild("A"))
      return c2.getChild("oo")