1.概述本文解释了为什么在Java中使用char[]而不是String来表示密码。请注意,本文重点关注在内存中操作密码的方法,而不是实际存储密码的方法。我们通常将密码存储在持久层中。假设我们无法控制密码的格式(例如,密码是来自第三方库API的字符串)。虽然使用字符串来操作密码似乎是合理的,但Java团队建议使用char[]。比如javax.swing中的JPasswordField,我们可以看到getText()从Java2开始就被弃用了,取而代之的是返回char[]的getPassword()方法。因此,让我们更深入地了解为什么建议使用char[]来操作密码。2.字符串是不可变的Java中的字符串是不可变的,这意味着我们不能用任何高级API更改它们。字符串的任何变化都会产生一个新的字符串,而旧的字符串会保留在内存中。因此,存储密码的字符串在内存中保持可用,直到垃圾收集器将其清除。我们无法控制这个回收过程,并且字符串可能比常规对象存活的时间长得多,因为字符串被保存在字符串池中以实现可重用性。因为,任何可以访问内存的人都可以从内存中查看密码。使用char[]我们可以在完成预期工作后明确擦除数据,因此我们可以确保甚至在垃圾收集发生之前就从内存中删除密码。使用String的场景:StringstringPassword="password";System.out.println(String.format("密码原字符串值:%s",stringPassword));System.out.println(String.format("密码原字符串hashCode:%s",Integer.toHexString(stringPassword.hashCode())));StringnewString="*********";stringPassword.replace(stringPassword,newString);System.out.println(字符串.format("尝试替换后的字符串密码值:%s",stringPassword));System.out.println(String.format("尝试替换后的hashCode:%s",Integer.toHexString(stringPassword.hashCode())));输出:OriginalStringpasswordvalue:passwordOriginalStringpasswordhashCode:4889ba9bString尝试替换后的密码值:passwordhashCode尝试替换后的String:4889ba9b使用char[]的场景:char[]charPassword=新字符[]{'密码'};System.out.println(String.format("原始字符密码值:%s",charPassword));System.out.println(String.format("原始字符密码hashCode:%s",Integer.toHexString(charPassword.hashCode())));Arrays.fill(charPassword,'*');System.out.println(String.format("Changedcharpasswordvalue:%s",charPassword));System.out.println(String.format("ChangedcharpasswordhashCode:%s",Integer.toHexString(charPassword.hashCode())));Output:Originalcharpasswordvalue:[C@51cdd8aOriginalcharpasswordhashCode:51cdd8aChangedcharpasswordvalue:[C@51cdd8aChangedcharpasswordhashCode:51cdd8a可以看到在使用String的时候,将原来的字符替换成字符串后,value和hashCode有未更改,这意味着String保持不变。对于char[]数组来说,value变了,hashCode没变,也就是说我们在变同一个对象数据。3.密码可以不经意打印在char[]中使用操作密码的另一个好处是可以防止密码被记录在控制台、监视器或其他不安全的地方。代码如下:StringstringPassword="password";char[]charPassword=newchar[]{'p','a','s','s','w','o','r','d'};System.out.println(String.format("打印字符串密码->%s",stringPassword));System.out.println(String.format("打印char[]密码->%s",字符密码));Output:PrintingStringpassword->passwordPrintingchar[]password->[C@51cdd8a使用String自己打印密码,使用char[]输出[C@51cdd8a这样密码就没那么容易泄露了。4.结论本文探讨了为什么不使用字符串来操纵密码而是使用char[]来操纵密码。
