1. 概述
本文解释 Java 中为什么用 char[] 来示意明码而不是 String。
留神本文重点在内存中操作明码的办法而不是存储明码的理论办法,存储明码咱们通常放在长久层。
假如咱们不可能管制明码的格局(例如明码来自于三方库 API 的字符串)。只管看起来用字符串操作明码很正当,然而 Java 团队还是倡议用 char[]。
例如,javax.swing 中的 JPasswordField 中,咱们能够看到 getText() 自 Java2 以来就已被弃用,取而代之的是返回 char[] 的 getPassword() 办法。
因而,咱们来深刻理解一下为什么举荐用 char[] 来操作明码。
2. 字符串不可变
Java 中字符串是不可变的,这意味着咱们无奈用任何高级 API 更改它们。对于字符串中的任何一个变更都会产生一个新的字符串,旧的字符串将还保留在内存中。
因而,存储明码的字符串始终在内存中可用直到垃圾收集器革除它。咱们无法控制这个回收的过程,而且字符串生存的工夫可能比惯例对象要长得多,因为为了可重用字符串是保留在字符串池中的。
因为,任何有拜访内存权限的人都能够从内存中查看明码。应用 char[] 咱们能够在实现预期工作后显式擦除数据,这样即便在垃圾收集产生之前,咱们也能够确保从内存中删除明码。
应用 String 的场景:
String stringPassword = "password";
System.out.println(String.format("Original String password value: %s", stringPassword));
System.out.println(String.format("Original String password hashCode: %s",
Integer.toHexString(stringPassword.hashCode())));
String newString = "*********";
stringPassword.replace(stringPassword, newString);
System.out.println(String.format("String password value after trying to replace it: %s", stringPassword));
System.out.println(String.format("hashCode after trying to replace the original String: %s",
Integer.toHexString(stringPassword.hashCode())));
输入:
Original String password value: password
Original String password hashCode: 4889ba9b
String password value after trying to replace it: password
hashCode after trying to replace the original String: 4889ba9b
应用 char[] 的场景:
char[] charPassword = new char[]{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};
System.out.println(String.format("Original char password value: %s", charPassword));
System.out.println(String.format("Original char password hashCode: %s",
Integer.toHexString(charPassword.hashCode())));
Arrays.fill(charPassword, '*');
System.out.println(String.format("Changed char password value: %s", charPassword));
System.out.println(String.format("Changed char password hashCode: %s",
Integer.toHexString(charPassword.hashCode())));
输入:
Original char password value: [C@51cdd8a
Original char password hashCode: 51cdd8a
Changed char password value: [C@51cdd8a
Changed char password hashCode: 51cdd8a
能够看到,应用 String 时,替换原始字符串后,值和 hashCode 都没有变,这意味着 String 放弃不变。
对于 char[] 数组,值变了 hashCode 没变阐明咱们是更改的同一个对象数据。
3. 能够不经意间打印明码
应用 char[] 中操作明码的另一个益处是能够避免在控制台、监视器或其余不平安的中央记录明码。
上面是代码:
String stringPassword = "password";
char[] charPassword = new char[]{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};
System.out.println(String.format("Printing String password -> %s", stringPassword));
System.out.println(String.format("Printing char[] password -> %s", charPassword));
输入:
Printing String password -> password
Printing char[] password -> [C@51cdd8a
应用 String 打印了明码自身,应用 char[] 输入的 [C@51cdd8a 这样明码就不那么容易泄露了。
4. 论断
本文摸索了为什么不必字符串来操作明码而应用 char[] 来操作明码。