0

使用错误查找器插件,我发现了这个错误,但不明白为什么它被视为代码中的错误。有人知道这些并给我适当的解释吗?谢谢。

源代码 - https://drive.google.com/open?id=1gAyHFcdHBShV-9oC5G7GeOtCGf7bXoso

Patient.java:17 Patient.generatePriority() 使用 Random 的 nextDouble 方法生成随机整数;使用 nextInt 更有效 [Of Concern(18), Normal confidence]

 public int generatePriority(){
    Random random = new Random();
    int n = 5;
    return (int)(random.nextDouble()*n);
 }

ExamRoom.java:25 ExamRoom 定义 equals 并使用 Object.hashCode() [Of Concern(16), Normal confidence]

public boolean equals(ExaminationRoom room){
        if (this.getWaitingPatients().size() == room.getWaitingPatients().size()){
            return true;
        }
        else {
            return false;
        }
    }

ExamRoom.java:15 ExamRoom 定义 compareTo(ExaminationRoom) 并使用 Object.equals() [Of Concern(16), Normal confidence]

    // Compares sizes of waiting lists
    @Override
    public int compareTo(ExaminationRoom o) {
        if (this.getWaitingPatients().size() > o.getWaitingPatients().size()){
            return 1;
        }
        else if (this.getWaitingPatients().size() < o.getWaitingPatients().size()){
            return -1;
        }
        return 0;
    }

Hospital.java:41 错误的月份值 12 传递给 Hospital.initializeHospital() 中的新 java.util.GregorianCalendar(int, int, int) [可怕(7),正常信心]

    doctors.add(new Doctor("Hermione", "Granger", new GregorianCalendar(1988, 12, 10), Specialty.PSY, room102));

Person.java:29 在 Person.getFullName() 中忽略 String.toLowerCase() 的返回值 [最可怕的 (3),高置信度]

public String getFullName(){
    firstName.toLowerCase();
    Character.toUpperCase(firstName.charAt(0));
    lastName.toLowerCase();
    Character.toUpperCase(lastName.charAt(0));
    return firstName + " " + lastName;

}
4

2 回答 2

2
  1. 不要Random每次都创建一个新对象。
  2. 使用random.nextInt(n).
  3. 在 中定义一个hashCode方法ExaminationRoom
  4. 让你的compareTo方法不一致equals()可能会也可能不会。
  5. 使用LocalDate而不是GregorianCalendar.
  6. 拾取并使用 和 的返回String.toLowerCase()Character.toUpperCase()
  7. 将 SpotBugs 视为 FindBugs 的更新替代品。

细节

Random

Random每次需要一个新对象时创建一个新对象,都会产生较差的伪随机数,并且数字重复的风险很高。在你的方法之外声明一个包含对象的静态变量Random并在声明中初始化它(Random是线程安全的,所以你可以安全地这样做)。为了绘制一个从 0 到 4 的伪随机数,请使用

int n = 5;
return random.nextInt(n);

它不仅更高效(正如 FindBugs 所说),我首先发现它更具可读性。

hashCode()

@Override
public int hashCode() {
    return Objects.hash(getWaitingPatients());
}

compareTo()

equals您向我们展示的方法似乎与这里的 FindBugs 相矛盾。不过,它看起来确实有点滑稽。如果两个候诊室有相同数量的候诊病人,它们是否被视为相同?请再想一想。如果您最终决定它们不相等,但应该毫无区别地归类到同一位置,那么您的compareTo方法与equals(). 如果是这样,请插入说明这一事实的评论。如果您希望 FindBugs 在后续分析中不将此报告为错误,您有两种选择:

  1. 插入一个注释告诉 FindBugs 忽略“错误”。
  2. 创建一个包含这一点的 FindBugs 忽略 XML 文件。

很抱歉,我不记得每个细节,但您的搜索引擎应该会有所帮助。

不要使用GregorianCalendar

GregorianCalendar课程设计不良且早已过时。我建议你将它从你的代码LocalDate中删除,然后使用现代 Java 日期和时间 API java.time。

doctors.add(new Doctor("Hermione", "Granger", LocalDate.of(1988, Month.DECEMBER, 10), Specialty.PSY, room102));

String.toLowerCase()

这已经在另一个答案中得到了处理。将名称更改为首字母大写,其余字母小写并不像听起来那么简单。

firstName.toLowerCase();
Character.toUpperCase(firstName.charAt(0));

这两行中的第一行没有修改字符串firstName,因为字符串被设计为不可变的,并且toLowerCase()返回一个所有字母都小写的新字符串(根据 JVM 的默认语言环境的规则,令人困惑)。第二行也没有修改任何字符,因为 Java 是按值调用(查找),所以没有方法可以修改作为参数传递的变量。您甚至没有传递变量,而是传递来自不同方法的返回值。还Character.toUpperCase()返回一个小写的新字符。

您需要做的是获取从这两个方法调用返回的值,使用子字符串操作从名称的小写版本中删除第一个字母,并将该字母的大写版本与其余部分连接起来小写字符串。如果它很复杂,我相信您的搜索引擎可以找到在哪里以及如何完成的示例。

顺便说一句:在将 Jack McNeil 博士写为 Mcneil 并将 Ludwig von Saulsbourg 博士写为Von saulsbourg之前,您可能需要三思而后行。

斑点虫

这只是我听到的,我没有检查过自己。FindBugs 的源代码已被一个名为 SpotBugs 的项目接管。他们说 SpotBugs 的开发比 FindBugs 更积极。所以你可以考虑换。在我的日常工作中,我自己是一个快乐的 SpotBugs 用户。

链接

于 2020-01-26T08:26:53.813 回答
0

关于“bug finder”工具,首先要记住的是它们通常只是指导方针。照这样说:

该类GregorianCalendar从 0 开始计算月份,这意味着 0 是一月,11 是十二月。12 代表不存在的第 13 个月。由于该函数需要一个int,而您给了它一个int,因此不会生成编译器错误,即使这肯定是一个错误。这篇文章很好地解释了升级的原因,并举例说明了如何使用新的 API:https ://www.baeldung.com/java-8-date-time-intro

如有疑问,您可以随时查看文档。在这种情况下,类CalendarGregorianCalendar扩展)删除了一个静态常量public static final int JANUARY = 0;,这证实了 january 确实是0,但也表明我们可以在代码中使用这个常量。您可能会发现new GregorianCalendar(1988, Calendar.JANUARY, 10)更具可读性。

您可能还需要考虑切换到用于处理时间的更现代和更标准的系统。Java 8 Time 库是“新标准”,绝对值得研究。

其次,Strings 在 Java 中是不可变的。这意味着一旦 aString被创建,它的值就永远不能改变。这可能与您的直觉相反,因为您可能已经看过以下代码:

String s = "hello";
s = s + " world";

但是,这不会修改string s。相反,s + " world"创建一个新的String,并将其分配给变量s

同样,s.toLowerCase()不会改变现状s,它只会生成一个String您必须分配的新内容。

你可能想要firstName = firstName.toLowerCase();

在您的第一个示例中,没有什么立即让我觉得“不好”,但是如果您查看工具生成的消息,他们会将第一个示例标记为“关注”,但将其他示例(例如string.toLowerCase()示例)标记为“可怕”/“最可怕”。虽然我对这个工具并不特别熟悉,但我想这更多地表明了“代码气味”,而不是实际的错误。

如果您想向自己保证您的代码有效,也许可以研究一下单元测试。

于 2020-01-26T05:40:36.237 回答