我一直在阅读Sun Microsystem的Java教程,并在阅读以下内容时遇到了一些问题:
I/O from the Command Line: The Console Object
"Second, readPassword returns a character array, not a String, so the password can be overwritten, removing it from memory as soon as it is no longer needed."
我的问题是:
1)关于其他数据类型,例如值数据类型(int,float,boolean等)和引用类型(用户定义的对象等),Java中的数组和字符串有何不同?
2)你能详细说明关于字符数组和字符串的上述陈述吗?
P.S:
对第一季的澄清:我想在Q1上问的更多关于数组和字符串作为Java中的数据类型的问题......由于它们具有类似对象的属性,当有人声称字符串和数组是不是严格意义上的对象......
答案 0 :(得分:4)
String
在内部将其内容存储为chars
的数组。 1}}是不可变的,因此你不能直接操纵这个数组(没有反射)。
密码位于Strings
的原因是您可以立即在内存中覆盖它。如果它在char[]
中,你将不得不等待下一次垃圾收集,你永远不知道它会持续多久;在此之前,攻击者可能会将其从内存中读出来。
答案 1 :(得分:4)
在实际层面上,String
和char[]
之间的主要区别在于前者的实例是不可变的,后者的实例是可变的。当然,String API提供了各种有用的方法字符串操作方法。
让我们来谈谈语言上的相同点和不同点。
首先,(尽管您可能已经听过)Java 中的字符串和数组实例都是对象。根据Java语言规范:
4.3.1对象对象是类实例或数组。
参考值(通常只是 引用)是指向这些的指针 对象和特殊的空引用, 这指的是没有对象。
...字符串的类是java.lang.String
。
数组和其他对象类型之间的语言区别是数组的类型不是普通的Java类。例如:
但是所有数组类型都是java.lang.Object
的(直接)子类型,这意味着您可以(例如)将数组分配给类型为Object
的变量,并调用Object API中的方法。 (你可以用这些方法做一些有趣的事情来演示数组的“对象”......但我离题了)
那么弦乐呢?如上所述,“字符串”是普通对象,它是类java.lang.String
的一个实例。从语言学的角度来看,这门课程并不罕见。它被声明为“最终”,因此您无法声明子类型,但这并不罕见。
与其他类相比,使String
有点特殊的是Java语言提供了一些语言结构来支持字符串:
String
字面语法,用于获取其内容可在编译时确定的字符串。String
连接。switch
语句支持切换String
值。concat
方法,字符串文字是“实习”。顺便说一下,所有字符串实例都保存在字符串池中的答案是不正确的。字符串仅在它们实现时放入池中,这仅对字符串文字和可在编译时计算其值的字符串自动发生。 (您可以通过调用String.intern()
方法强制执行字符串实例,但这有点贵,通常不是一个好主意。)
答案 2 :(得分:1)
正如其他人所说,String是不可变的,所以你不能自己擦除它。即使在收集垃圾之后,内存仍可能完好无损。因此,所有安全协议都将敏感数据定义为字节数组,以便您可以执行此操作,
char[] password = "secret";
// After using it
for (int i; i < password.length; i++)
password[i] = 0;
password = null;