使用日期或列表

时间:2017-02-09 08:48:45

标签: java sonarqube getter-setter

我将这个getter / setter写入Eclipse源菜单列表:

public Date getDate() {
    return date;
}

public void setDate(Date date) {
    this.date = date;
}

Sonar报告了两个问题:

  

返回“日期”和“日期”的副本存储“日期”的副本

带有解释

  

“不应直接存储或退回可变成员”

和示例代码:

public String [] getStrings() {
    return strings.clone();}

public void setStrings(String [] strings) {
    this.strings = strings.clone();}

我认为如果我的Date为null,它将抛出NullPointerException。然后我将代码更改为:

public Date getDate() {
    if (this.date != null) {
        return new Date(this.date.getTime());
    } else {
        return null;
    }
}

public void setDate(Date date) {
    if (date != null) {
        this.date = new Date(date.getTime());
    } else {
        this.date = null;
    }
}

现在标志着其他问题:

  

“将对象分配给null是一种代码气味。考虑重构”。

我在互联网上搜索并设置或返回一个新数组对我来说不是一个解决方案,如果setter param为null以覆盖现有的前一个列表,我想保留我的列表为null。

我对List有同样的问题,我想为空List返回/保留null而不是新的ArrayList。在这种情况下,setter标记了另一个问题:

  

“返回一个空集合而不是null。”。

这个问题的解决方案是什么?

4 个答案:

答案 0 :(得分:3)

如果您使用的是Java 8并且不想处理空日期,那么使用Optional可能会对您有所帮助。

编辑:“POJO”类的示例

public class Toto {

    public Optional<Date> myDate;

    public Optional<Date> getMyDate() {
        return this.myDate;
    }

    public void setMyDate(final Date myDate) {
        this.myDate = Optional.ofNullable(myDate);
    }

}

代码使用示例:

Toto toto = new Toto();
toto.setMyDate(null);
System.out.println("Value is null ? " + toto.getMyDate().isPresent());
System.out.println("Value: " + toto.getMyDate().orElse(new Date()));

尝试使用具体日期值更改toto.setMyDate(...)以查看发生的情况。

如果你不知道什么是Optional或如何使用它,你可以找到很多例子。

但是:这只是解决违规问题的一种方式,我完全赞同Brad的评论,可选不打算用作类型,但更像是潜在空的合同/ null返回。 一般情况下,如果违规行为不正确,您不应该以错误的方式更正代码以修复违规行为。在你的情况下,我认为你应该忽略违规行为(因为大多数声纳的不幸)

如果你真的想在你的代码中使用Java 8和Optional,那么你的POJO类就是这样的(仅在getter上使用Optional作为contrat)

public class Toto {


    public Date myDate;

    public Optional<Date> getMyDate() {
        return Optional.ofNullable(this.myDate);
    }

    public void setMyDate(final Date myDate) {
        this.myDate = myDate;
    }

}

这样,

  • 你的bean可以序列化(可选不是)
  • 您仍然可以让“客户”代码选择如何处理属性的空/空值
  • 将您的声纳违规配置为误报,因为它是您想要的而不是更改您的代码

答案 1 :(得分:1)

您不必在您的二传手中明确设置null,只需使用这样传入的值...

public void setDate(Date date) {
    if (date != null) {
        this.date = new Date(date.getTime());
    } else {
        this.date = date;
    }
}

就个人而言,我永远不会允许null值进入我的Value对象,但这只是我自以为是的编码风格。

我对任何人的建议是更喜欢不可变值对象,你可以在构造函数中设置所有值,并且不允许空值。这种样式可能不适合所有期望java bean getter /的第三方库setters所以要注意它可以有效地用于简化你的代码。

修改

如果上面的代码仍然给你警告,你必须要设置&#34;属性&#34;功能,另一种方法是定义一个&#34; null对象&#34;像这样

public static final Date NO_DATE = new Date(Long.MIN_VALUE);

public void setDate(Date date) {
    this.date = (date == null) ? NO_DATE : new Date(date.getTime());
}

此类的用户可以像这样引用NO_DATE对象,这仍然是可读代码

if(toto.getDate() != NO_DATE) ...

或者将其封装到另一种方法中,以便像这样使用

if(toto.hasDate()) ...

当然,这样做比@kij的Java 8 Optional方法更有优势,但它适用于任何版本的Java

答案 2 :(得分:1)

通常,虽然使用静态分析工具来验证代码是有价值的,但您不应盲目地修复弹出的每个警告。您需要分析触发的问题并检查它是否真的适用于您的上下文。

现在解决你提到的问题

  

返回&#34; date&#34;的副本&安培;存储&#34;日期&#34;

的副本

这似乎是有效的。优秀的做法是防守并且不会通过吸气剂/安装者暴露可变状态。因此,应该在getter / setter中创建一个防御性副本。这可以通过您执行此操作的方式完成,也可以使用提供不可变对象的新Java Time API来完成。

  

将Object指定为null是代码气味。考虑重构

IMO可疑的一个。 PMD插件(分析代码的工具,SonarQube正在显示报告)引发了这个问题。问题http://pmd.sourceforge.net/pmd-4.3.0/rules/controversial.html#NullAssignment提出了问题,因为您可以看到它属于有争议的类别。我不认为您的代码有任何问题,而且可以采取适当的措施来忽略此警告,并将问题标记为&#34;无法修复&#34;。您还可以将SonarQube配置为不在质量配置文件设置中使用此特定规则。

  

返回一个空集合而不是null。

您没有提供触发它的代码,但这似乎是一个有效的建议。通常最好返回空集合而不是空值。

答案 3 :(得分:-1)

我建议使用lombok库,而不是手动创建getter和setter。它将自动避免此类声纳问题。