"hashCode" 和 "toString" 不应在数组实例上调用 (SonarLint)

"hashCode" and "toString" should not be called on array instances (SonarLint)

我正在通过 SonarLint 传递我的代码,我遇到了这个 linter 违规行为: "hashCode" and "toString" should not be called on array instances.

这是我的代码:

byte[] lblobPic;
lblobPic = r.get(PEOPLE.PPIC);
if (lblobPic != null) {
    String argStr = lblobPic.toString();
    peopleDto.setUrlPic(argStr);
}

SonarLint 提供以下代码片段作为改进我的代码的提示:

public static void main( String[] args )  {
    String argStr = Arrays.toString(args);
    int argHash = Arrays.hashCode(args);    
}

我应该如何更改我的代码以满足 linter,为什么?

实际答案

SonarLint 向您建议,与其在数组实例上调用 toString(),不如使用 Arrays 实用程序的方法。

它建议您将代码更改为以下内容:

byte[] lblobPic;
lblobPic = r.get(ALUNO.PFOTO);
if (lblobPic != null) {
    String argStr = Arrays.toString(lblobPic);
    peopleDto.setUrlPic(argStr);
}

答案背后的原因

a) 人类可读性

考虑以下代码片段:

String[] strings = { "foo", "bar", "bla", "boo" };

System.out.println(strings.toString());
// prints: [Ljava.lang.String;@7852e922 

System.out.println(Arrays.toString(strings));
// prints: [foo, bar, bla, boo]

Linter 规则假定,开发人员实际上想要数组的可读输出(考虑其元素)并建议您使用执行此操作的 Arrays.toString() 方法(如 the documentation 中所述) .

类似地,Arrays.hashCode() 在散列中考虑给定数组的元素(如 the docoumentation 中所述)。

b) 决定论
(根据@andi-turner 的建议)

Arrays 实用程序的方法,在构造字符串/计算哈希时仅考虑元素。当使用由相同序列中的相同字符串(或另一种类型的值)组成的输入数组时,您将始终得到相同的 string/hash。 yourArray.toHashcode()yourArray.toString() 不会给你那个。

String argStr = lblobPic.toString();

最好是

String argStr = Arrays.toString(lblobPic);

因为原来的 Object.toString 会给出一个神秘的十六进制地址。

无论您想实现什么,将字节存储为 String 在 java 中都是不行的, 因为 java 将 Unicode 用于 String 和 char(两个字节,UTF-16),总是带有转换(这些字节的假定文本编码)。

有时这样的字节是 Base64 编码的:

byte[] lblobPic = r.get(ALUNO.PFOTO);
if (lblobPic != null) {
    String argStr = Base64.getUrlEncoder().encode(lblobPic);
    peopleDto.setUrlPic(argStr);
}

最好在 DTO 中提供一个 byte[] 字段。


应该是进一步处理有问题;存在图像嵌入。

如何(正常)Base64 用于 HTML 嵌入图像:

    String argStr = Base64.getEncoder().encode(lblobPic);
    String html = "<img src="data:image/jpeg;base64," + argStr + "\" alt=\"\">";

(此处假设为 JPEG。)