[英]What is the difference between declaring a final variable in an Activity and instantiating it on the onCreate method?
[英]What is the difference between declaring a String and declaring it as final?
我知道字符串是不可变的。
然后,两者之间有什么区别?
String name ="Name";
final String name ="Name";
为什么在这种情况下使用final
? 因为String已经是不可变的,所以似乎没有必要。 第二个相关问题,为什么String是immutable
? 其他数据类型(如int,boolean)则不是。 如果String是不可变的,这是否使其成为线程安全的? 我读到“如果String是可变的,则可能已将加载“ java.io.Writer”的请求更改为加载“ mil.vogoon.DiskErasingWriter”” means
什么means
?
这里有很多问题,但是这里有一些注释可以回答大多数问题:
final
表示变量只能分配一次。 它与可变性无关,可变性是对象的属性,而不是变量(只是句柄) String
是不可变的,因为您无法更改其内部状态(它具有用于保存private char[] chars
的private char[] chars
)。 基元也是不可变的。 在它们的包装等效项中更好地看到Integer
, Long
等。 final
表示您无法为变量分配新值。
String name = "Name";
name = "MyName"; // legal
final String name = "Name";
name = "MyName"; // illegal, compiler error
这是一篇关于为什么字符串不可变的文章:
http://javarevisited.blogspot.com/2010/10/why-string-is-immutable-in-java.html
我读到“如果String是可变的,则加载“ java.io.Writer”的请求可能已更改为加载“ mil.vogoon.DiskErasingWriter””
好。 首先要意识到的是,这是一个假设性的讨论。 字符串是不可变的。
现在想象一下这段代码:
public static final String CLASS_NAME = "java.io.Writer";
...
Class<?> clazz = Class.forName(CLASS);
实际加载什么类?
如果String是可变的,则在安全沙箱中运行的某些恶意代码将能够使CLASS_NAME引用的String对象的内容发生突变。 特别是,可以将其从“ java.io.Writer”更改为“ mil.vogoon.DiskErasingWriter”。 最终结果是,您的应用程序将被诱骗加载错误的类。
通过将String设置为不可变的类型(以及其他一或两个事物),可以阻止这种攻击机制。
就像威廉所说:
final表示您无法为变量分配新值。
此外,如果您像这样玩匿名内部类:
final String mystring = "Hello";
button.addClickHandler(new ClickHandler() {
void click() {
System.out.println(mystring);
}
});
mystring
对象必须是最终对象。
它是对象与其参考之间的区别。 final
变量只能分配一次值。 无论变量是否指向不可变对象,这都是正确的。
请注意,“不可变”对象本身通常(但不一定)由final
引用集组成。
其他要点已经在这里得到了回答,但是您仍在寻找对所找到报价的解释:
如果String是可变的,则加载“ java.io.Writer”的请求可能已更改为加载“ mil.vogoon.DiskErasingWriter”
作为参考,这似乎是从不同的SO答案中得出的,该答案有些简短,但省略了细节。
通常,如果您编写一个接受可变对象并存储它们的公共类,或者返回一个正在存储的可变对象,则调用代码可以从该类的下面更改该对象。
举个例子。 免责声明:我对ClassLoader不太了解,所以这只是为了说明问题。 ClassLoader具有功能loadClass(String name)
。 想象一下,该方法首先检查该名称的类是否有效或受信任,然后加载它。 现在,如果String是可变的,则调用代码可以在检查了类之后,从类加载器的脚下更改类名称,从而规避安全措施。
当然,如果String是可变的,则可以希望ClassLoader的实现首先创建String的防御性副本 。 这样,调用代码没有任何机会规避安全性,因为它无法修改副本的内容。 这是一个通用规则:不要让调用代码对类的可变内部数据有任何处理。
所以字符串不需要是一成不变的,以确保安全类加载。 但是,对于不可变的对象,更容易确保这种安全性,因为它们根本无法在您身下更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.