首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >使用带有日期或列表的简单getter和setter方法解决Sonar问题

使用带有日期或列表的简单getter和setter方法解决Sonar问题
EN

Stack Overflow用户
提问于 2017-02-09 16:48:45
回答 3查看 14.8K关注 0票数 10

我将此getter/setter编写为Eclipse源代码菜单中的列表:

public Date getDate() {
    return date;
}

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

和Sonar报告了两个问题:

返回"date“的副本并存储"date”的副本

有这样的解释

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

并给出了示例代码:

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

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

我想如果我的Date是空的,它会抛出一个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参数为null,我想保留我的列表为null,以覆盖现有的以前的列表。

对于List,我也遇到了同样的问题,我想为一个空列表返回/保留null,而不是一个新的ArrayList。在本例中,setter标记了另一个问题:

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

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-02-09 17:34:22

如果您使用的是Java8,并且不想处理空日期,那么使用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并不打算用作类型,而更像是一个潜在的空/空返回的契约。通常,如果冲突不正确,您不应该仅仅为了修复冲突而以错误的方式更正代码。在你的情况下,我认为你应该忽略这种违规行为(不幸的是,Sonar的大多数违规行为)

如果你真的想在你的代码中使用Java8和Optional,那么你的POJO类应该是这样的( Optional的用法只是在getter上作为一种控制)

public class Toto {


    public Date myDate;

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

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

}

这边请,

  • 你可以保持可序列化(可选不是)
  • 你仍然可以让你的“客户端”代码选择如何将你的Sonar违规的空/空值作为误报,因为这是你想要的,而不是改变你的代码
票数 3
EN

Stack Overflow用户

发布于 2017-02-14 19:40:52

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

现在来解决你提到的问题

返回"date“的副本并存储"date”的副本

这似乎是有效的。最好是防御性的,不要通过getter/setter暴露可变状态。因此,应该在getter/setter中创建一个防御性副本。这可以按照您的方式完成,也可以使用新的Java Time API来完成,它提供了不可变的对象。

将对象赋值为null是一种代码味道。考虑重构

这是一个可疑的问题。这个问题是由PMD plugin (分析代码的工具,SonarQube正在显示报告)引起的。这个规则http://pmd.sourceforge.net/pmd-4.3.0/rules/controversial.html#NullAssignment提出了问题,正如您可以看到的,它属于有争议的类别。我不认为您的代码有任何错误,正确的操作可能是忽略此警告,并将问题标记为“无法修复”。您还可以在质量配置文件设置中将SonarQube配置为不使用此特定规则。

返回空集合而不是null。

您没有提供触发它的代码,但这似乎是一条有效的建议。通常,返回空集合比返回null值更好。

票数 2
EN

Stack Overflow用户

发布于 2017-02-09 17:42:43

你不需要在你的setter中明确地设置null,只需要像这样使用传入的值就可以了。

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

就我个人而言,我永远不会在任何可能的情况下允许空值进入我的值对象,但这只是我固执己见的编码风格。

我对任何人的建议是首选不可变值对象,在这些对象中,您可以在构造函数中设置所有值,并且不允许使用空值。这种风格可能并不适合所有需要java bean getter/setter的第三方库,所以要知道在哪里可以有效地使用它来简化您的代码。

编辑

如果上面的代码仍然给出警告,并且您必须具有“属性尚未设置”功能,则另一种方法是定义一个"null对象“,如下所示

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的Java8可选方法相比,这并没有增加太多好处,但它确实适用于任何版本的Java

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42131930

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档