摘要:的不可变性众所周知,是常量,不可变,这一点很重要。那中,包装类的一个特质就是值操作时体现对应的基本类型的特质。同样的,等这些包装类和在这种情况下的表现是相同的。那么无论你对传入参数做了什么操作,都不会影响原来的值。
1. String的不可变性
众所周知,String是常量,不可变,这一点很重要。
其底层的实现是char[]:
/** The value is used for character storage. */ private final char value[];
而且,它是final的。
看两个构造函数:
/** * Initializes a newly created {@code String} object so that it represents * the same sequence of characters as the argument; in other words, the * newly created string is a copy of the argument string. Unless an * explicit copy of {@code original} is needed, use of this constructor is * unnecessary since Strings are immutable. * * @param original * A {@code String} */ public String(String original) { this.value = original.value; this.hash = original.hash; } /** * Allocates a new {@code String} so that it represents the sequence of * characters currently contained in the character array argument. The * contents of the character array are copied; subsequent modification of * the character array does not affect the newly created string. * * @param value * The initial value of the string */ public String(char value[]) { this.value = Arrays.copyOf(value, value.length); }
其内部的很多方法,也是会新生成一个char[]来构造一个新的String对象返回。
例如replace:
/** * Returns a new string resulting from replacing all occurrences of *oldChar
in this string withnewChar
. */ public String replace(char oldChar, char newChar) { if (oldChar != newChar) { int len = value.length; int i = -1; char[] val = value; /* avoid getfield opcode */ while (++i < len) { if (val[i] == oldChar) { break; } } if (i < len) { char buf[] = new char[len]; for (int j = 0; j < i; j++) { buf[j] = val[j]; } while (i < len) { char c = val[i]; buf[i] = (c == oldChar) ? newChar : c; i++; } return new String(buf, true); } } return this; }
doc中写的很明白,这个方法,会新生成一个String对象返回。
所以类似
str = str.replace("a","b"); str = str.substring(2); str = str.toLowerCase();
都会生成新的对象。原来的对象还是存在的,只是没有引用指向它,等待被垃圾回收。
2.传递String类型参数看一个例子:
public class StringTest { public static void main(String[] args) { StringTest stringTest = new StringTest(); String string = "abc"; stringTest.replace(string); System.out.println(string); Integer i = 1; stringTest.add(i); System.out.println(i); } public void replace(String string) { string = string.replace("a", "b"); string = string.toUpperCase(); System.out.println("inner:" + string); } public void add(Integer integer) { integer++; System.out.println("inner:" + integer); } }
Stirng内部实现时,是用char[] 来存储字符串的,所以String相当于char[]的包装类。那java中,包装类的一个特质就是值操作时体现对应的基本类型的特质。同样的,Integer、Float等这些包装类和String在这种情况下的表现是相同的。
分析一下,主要是还是由于包装类内部实现方式导致的。
包装类内部存储结构是final的原生类型,或原生类型数组,是不可变的。之后所做的操作都会新生成一个对象来返回。那么无论你对传入参数做了什么操作,都不会影响原来的值。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/65679.html
摘要:隐式类型转换类型转类型先定义一个类型的变量只要类型跟类型还是类型用号,其他类型都会被转为字符串输出结果字符串类型转类型或者类型定义类型的变量与类型的变量前端从测试结果可以看出,类型在跟数字类型做乘除减运算时,得到的是数字类型的值,但是类型必 隐式类型转换 number类型转string类型 //先定义一个number类型的变量 //只要string类型跟boolean类型还是numbe...
摘要:关于如何限速,有两个比较出名的算法,漏桶算法与令牌桶算法,这里对其简单介绍一下,最后再实践在我发邮件的中以下是发送邮件的,已限制为一分钟两次,你可以通过修改进行试验。 前段时间,我使用了 jwt 来实现邮箱验证码的校验与用户认证与登录,还特别写了一篇文章作为总结。 在那篇文章中,提到了一个点,如何限速。 在短信验证码和邮箱验证码,如果不限速,被恶意攻击造成大量的 QPS,不仅拖垮了服务...
摘要:为了提高程序运行的效率,在软件发布后,检查默认是被关闭的。注意不能保证原子性,不能代替,且其会阻止编译器对代码的优化。以下方法用来判断一个字符串中是否包含中文字符。 前言 面试中对于技术职位,一般分笔试与面谈,如果面试官的一些小问题你可以立马找到对应的知识点扩展开来,那么这就是你的优势,本系列将讲述一些java面试中的事,不会很详细,但是应该比较全面吧。 主要内容 assert有什么作...
摘要:小程序的登录跟平时自己这种登录验证还不太一样,多了一个角色,那就是微信服务器。的有效期默认是小时,当用户一直在使用小程序的话会自动刷新,这个是由微信这边来维护的。 最近团队在开发一款小程序,都是新手,一边看文档,一边开发。在开发中会遇到各种问题,今天把小程序登录这块的流程整理下,做个记录。 小程序的登录跟平时自己APP这种登录验证还不太一样,多了一个角色,那就是微信服务器。 showI...
阅读 2021·2023-04-25 17:57
阅读 1265·2021-11-24 09:39
阅读 2451·2019-08-29 16:39
阅读 3292·2019-08-29 13:44
阅读 3045·2019-08-29 13:14
阅读 2282·2019-08-26 11:36
阅读 3759·2019-08-26 11:00
阅读 927·2019-08-26 10:14