我们都知道 Java 中的 String 类的设计是不可变的,来看下 String 类的源码。

public final class String
implements java.io.Serializable, Comparable<String>, CharSequence { /** The value is used for character storage. */
private final char value[]; /** Cache the hash code for the string */
private int hash; // Default to 0 // ... }

可以看出 String 类是 final 类型的,String 不能被继承。其值 value 也就是对字符数组的封装,即 char[],其值被定义成 private final 的,说明不能通过外界修改,即不可变。

String 真的 "不可变 " 吗?

来看下面这个例子。

String str = "Python";
System.out.println(str); // Python str = "Java";
System.out.println(str); // Java str = str.substring(1);
System.out.println(str); // ava

你有可能会问:str 不是由 Python 变成 Java 了吗?然后通过 substring 方法变成 ava 了吗?

这其实是初学者的一个误区,从上面看 String 的结构可以得知字符串是由字符数组构成的,str 只是一个引用而已,第一次引用了 "Python",后面变成了 "Java",而 substring 也是用 Arrays.copyOfRange 方法重新复制字符数组构造了一个新的字符串。

所以说,这里的字符串并不是可变,只是变更了字符串引用。

关于 substring 在 JDK 各个版本的差异可以看这篇文章《注意:字符串substring方法在jkd6,7,8中的差异》,也可以去看 substring 的各个版本的源码。

String 真的真的真的 "不可变 " 吗?

上面的例子肯定是不可变的,下面这个就尴尬了。

String str = "Hello Python";
System.out.println(str); // Hello Python Field field = String.class.getDeclaredField("value");
field.setAccessible(true); char[] value = (char[])field.get(str);
value[6] = 'J';
value[7] = 'a';
value[8] = 'v';
value[9] = 'a';
value[10] = '!';
value[11] = '!';
System.out.println(str); // Hello Java!!

通过反射,我们改变了底层的字符数组的值,实现了字符串的 “不可变” 性,这是一种骚操作,不建议这么使用,违反了 Java 对 String 类的不可变设计原则,会造成一些安全问题。

是不是又涨姿势了?分享给你的朋友们吧!

更多干货推荐

1.史上最强 Java 中高级面试题整理

2.史上最强 Spring Boot & Cloud 教程整理

3.史上最强架构设计分布式技术干货整理

更多请扫描下方的二维码关注我们的微信公众号,干货每日推送!

Java 中的 String 真的是不可变吗?的更多相关文章

  1. Java中的String为什么是不可变的?

    转载:http://blog.csdn.net/zhangjg_blog/article/details/18319521 什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那 ...

  2. Java中的String为什么是不可变的? -- String源码分析

    众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对象就是不可变的.不能改变状态的意思是, ...

  3. Java中的String为什么是不可变的? — String源码分析

    原文地址:http://www.importnew.com/16817.html 什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为 ...

  4. 【转】Java中的String为什么是不可变的? -- String源码分析

    什么是不可变对象? 众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对象就是不可变的.不 ...

  5. (转)Java中的String为什么是不可变的? -- String源码分析

    背景:被问到很基础的知识点  string  自己答的很模糊 Java中的String为什么是不可变的? -- String源码分析 ps:最好去阅读原文 Java中的String为什么是不可变的 什 ...

  6. (转)Java中的String为什么是不可变的

    转自:http://www.importnew.com/7440.html String是所有语言中最常用的一个类.我们知道在Java中,String是不可变的.final的.Java在运行时也保存了 ...

  7. 为什么Java中的String类是不可变的?

    String类是Java中的一个不可变类(immutable class). 简单来说,不可变类就是实例在被创建之后不可修改. 在<Effective Java> Item 15 中提到了 ...

  8. Java中的String真的无法修改吗

    Java中String一旦赋值将无法修改,每次对String值的修改都是返回新的String. 如何在不创建新的String对象的情况下,对String的值进行修改呢? String类中的包含一个字段 ...

  9. Java基础知识强化101:Java 中的 String对象真的不可变吗 ?

    1. 什么是不可变对象?       众所周知, 在Java中, String类是不可变的.那么到底什么是不可变的对象呢? 可以这样认为:如果一个对象,在它创建完成之后,不能再改变它的状态,那么这个对 ...

随机推荐

  1. django ajax提交form表单数据

    后台: from django.shortcuts import render from django.shortcuts import redirect from django.shortcuts ...

  2. zz-人生感悟

    1. 社交感想 首先来看一下聪明人和普通人的区别是什么? 普通人思考问题都是一步一步的来,由A推理出B,B推导到C,再推导出D,最后得出E,然而聪明人却可以由A直接推算到E. 这就像开车,普通人的是手 ...

  3. Chapter5_初始化与清理_方法重载

    方法重载是java中编译器在方法调用时采用的一个重要机制.起初方法重载的初衷是方便构造器的调用,比如对于一个类,可以实现用不同的方法来初始化它,又由于构造器的名称都是一样的,所以必须使用到方法重载的机 ...

  4. 跟踪SQL

    在数据库中,找到以下页面,并选择事件中的Tsql下的bath...与stm...

  5. A能ping通B,BpingA请求超时

    除了防火墙等,杀毒软件都已经关了: A是外网,B是内网,A有两个ip地址,请ping A 的内网地址.

  6. 在n个数字中求为k的和————Java

    给出N个正整数组成的数组A,求能否从中选出若干个,使他们的和为K.如果可以,输出:"YES",否则输出"NO".用Java实现 import java.util ...

  7. css隐藏多余的文字并出现省略号

    <meta charset="utf-8" /> <style> .txt{ width:200px; border:1px solid #ddd; ove ...

  8. mpdf-html转PDF,中文字符乱码、加粗问题

    $defaultConfig = (new ConfigVariables())->getDefaults(); $fontDirs = $defaultConfig['fontDir']; $ ...

  9. JavaScript 平时记录

    1,JS中的this 见下面例子,注意函数中的函数 中的this指的是window对象了!!! document.addEventListener('click', function (e) { co ...

  10. 数据库 的几种链接 join

    直接demo,懒的同学可以看看效果 两个表的数据 join和inner join一样 full join报错,可有大神知道原因?