为何String对象是immutable或final的?
2017-07-31 10:33
225 查看
1. 问题引入
本文内容主要参考自此处,感兴趣者可以自行移步查看。另,StackOverflow上也有关于该问题的回答,这里贴出部分答案。
String is immutable for several reasons, here is a summary:
Security: parameters are typically represented as String in network connections, database connection urls, usernames/passwords etc. If it were mutable, these parameters could be easily changed.
Synchronization and concurrency: making String immutable automatically makes them thread safe thereby solving the synchronization issues.
Caching: when compiler optimizes your String objects, it sees that if two objects have same value (a=”test”, and b=”test”) and thus you need only one string object (for both a and b, these two will point to the same object).
Class loading: String is used as arguments for class loading. If mutable, it could result in wrong class being loaded (because mutable objects change their state).
That being said, immutability of String only means you cannot change it using its public API. You can in fact bypass the normal API using reflection. See the answer here.
大概有四个方面内容(出于安全和效率考虑):
1. 安全性:网络通信、数据库链接url、用户名密码等涉及安全的参数都是以String类型的数据。如果String是可改变的,那么这些参数可以很容易被修改,导致系统容易被攻击。
2. 多线程安全:同步和并发问题上,String不可改变的特性使它本身就是线程安全的,因而解决了同步的问题。
3. 缓存问题:当编译器优化我们的String对象时,如果检测到2个或多个对象有相同的值(a=”test”, b=”test’, c=”test”) 因而可以优化为一个string对象。
4. 类加载: 比如”Class.forName(com.fqyuan.string.TestStr)”. String作为类加载的参数。如果String可变的话,那么可能导致加载错误的类, 如本意要加载的是”java.io.Writer”, 结果可能加载成了”mil.vogon.DiskErasingWriter”。
2. 关于String Literal pool 及相关String相等的讨论
部分内容参考自此,感兴趣者可自行查看,这里做了总结。1. 字符串常量池机制如果String对象是mutable的话,则根本无法正常工作,因为一个引用的改变将使得所有其他的引用的值也会改变。
String A = "Test"; String B = "Test"; /* * If calling B.toUppercase(), it create a brand new string representing the value. * /
2. 关于如下代码的思考。
以下的内容参考自stackoverflow, 可以通过点击如下链接。
package com.fqyuan.String; public class TestStr { public static void main(String[] args) { String str1 = "someThing"; String str2 = "someThing"; String str3 = new String("someThing"); String str4 = new String("someThing"); /* * 简言之,equal方法如果没有被重写,那么其效用和'=='相同。 如果重写了equals()方法,那么记得重写hashCode方法。 * 可以理解为:==比较的是引用的位置,而equal()比较的是引用的内容。 * 即:equal()如果返回为true,则其hashCode()必然相同。而反之,并不一定成立。 */ if (str1 == str2) System.out.println("str1 == str2"); else System.out.println("str1 != str2"); if (str1 == str3) System.out.println("str1 == str3"); else System.out.println("str1 != str3"); if (str3 == str4) System.out.println("str3 == str4"); else System.out.println("str3 !=str4"); if (str1 == str3.intern()) System.out.println("str1 == str3.intern()"); else System.out.println("str1 != str3.intern()"); if (str4.intern() == str3.intern()) System.out.println("str4() == str3.intern()"); else System.out.println("str4.intern() != str3.intern()"); System.out.println("str1.equals(str3): " + str1.equals(str3)); } }
//Running result: str1 == str2 str1 != str3 str3 !=str4 str1 == str3.intern() str4() == str3.intern() str1.equals(str3): true
3. String 不可改变特性,真的不可改变么?
该问题的讨论部分参见此处,感兴趣者可自行查看。There is no absolute truth in the universe. 哈哈,同样,String也不是绝对不可改变的。
String is immutable, but this only means you can’t change it using public API.
We can do all kinds of tricks with reflection. But we’re basically breaking the “warranty void if remove” sticker on the class the instant you do it.
翻译过来就是:我们常说的String是不可改变的,但这是在一般意义上讲的,是指使用public API我们无法改变String对象的值。但是我们可以使用一些奇淫巧技,Reflection来对其做修改,但是这样就改变了该类设计的初衷,就像商品上“标签撕毁无效”的约定。
package com.fqyuan.String; import java.lang.reflect.Field; public class StrMut { public static void main(String[] args) throws Exception { String str1 = "stack"; String str2 = "stack"; String str3 = str1.substring(2); System.out.println(str1); System.out.println(str2); System.out.println(str3); Field field = String.class.getDeclaredField("value"); field.setAccessible(true); char[] value = (char[]) field.get(str1); value[2] = 'u'; value[3] = 'd'; value[4] = 'y'; System.out.println(str1); System.out.println(str2); System.out.println(str3); } }
//Runnign result: stack stack ack study study ack
相关文章推荐
- Java中String为什么被设计成immutable(不可修改的)/final
- Java - Why String is Immutable or Final in Java
- 解释为何内部类访问外部对象时要设参数为final
- Why String is immutable or final in Java
- 深入理解final 类String 对象的创建以及内部方法
- Why String is immutable or final in Java
- 为何java.lang.String被声明为final
- [挖坑系列] Java String为毛是final或者immutable的?
- 调用Thread类的方法:public final String getName() 为什么得到的线程对象的名称默认是:Thread-0、Thread-1、Thread-2、...呢?
- Why String is Immutable or Final in Java
- Java中String为什么是final或immutable
- Why String is immutable or final in Java
- JS中Array对象和String对象的常用方法
- W3Cschool——学习二:JavaScript对象,String,Date,Array
- 输出操作符和getline读取string对象
- 黑马程序员--java中String创建几个对象
- String对象具备的一些基本方法
- string类型转换为json对象保存
- 泛型为Integer的ArrayList中存放一个String类型的对象