Java 字符串如何理解 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
huf
V2EX    Java

Java 字符串如何理解

  •  
  •   huf Jan 22, 2022 2487 views
    This topic created in 1555 days ago, the information mentioned may be changed or developed.

    在 JDK 中 String 的 String 参数的构造方法里面有这样的说明

    初始化一个新创建的 String 对象,使其表示与参数相同的字符序列;换句话说,新创建的字符串是参数字符串的副本。除非需要原始的显式副本,否则不需要使用此构造函数,因为字符串是不可变的。

    如图: 文档截图

    怎么理解其中的“新创建的字符串是参数字符串的副本。”这句话

    我做了如下实验 代码:

    import java.lang.reflect.Field; public class StringTest { public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException { String strabc1 = "abc"; Class<? extends String> aClass = strabc1.getClass(); Field abcValue = aClass.getDeclaredField("value"); abcValue.setAccessible(true); byte[] chars = (byte[]) abcValue.get(strabc1); chars[0] = 'd'; chars[1] = 'e'; chars[2] = 'f'; String newStrAbc1 = new String("abc"); String newStrAbc2 = new String("abc"); System.out.println(strabc1); System.out.println("abc".equals("def")); System.out.println(newStrAbc1.equals("def")); System.out.println(newStrAbc1 == newStrAbc2); System.out.println(newStrAbc1.equals(newStrAbc2)); } } 

    运行结果截图: 运行结果截图

    如图改变了“abc”的值之后字符串常量池中“abc”实际的值已经改变为“def”所以用“abc”equals“def”的时候返回 true ,我不理解的是文档中说的“副本”具体是怎么个副本法? 21 行代码输出的是 true 证明 new String 的这种方式创建出来的字符串也受字符串常量的影响,new String 创建出来的字符串使用==判断输出 false 比如如图 23 行代码输出的是 false ,按网上所说是地址不一样,地址不一样,但是又受字符串常量池的影响,我就疑惑这个文档中的“副本”是指什么概念?

    Supplement 1    Jan 22, 2022
    感谢各位,感谢 @chendy 提醒,用浅克隆可以很好的来理解,我也实验了一下 new String 出来的 String 对象里面的 value 数组是和常量方式 String 的 value 的数组 HashCode 值是一样的,是我愚钝了纠结了好久。
    8 replies    2022-01-23 03:27:53 +08:00
    chendy
        1
    chendy      Jan 22, 2022   1
    除非你 new String("abc"),否则所有的 "abc" 都是同一个对象
    所以把 "abc" 的内容修改成 “def" 之后 ,所有的 "abc" 都变成了 "def"
    所以 new String("abc") 得到的也是 "def"
    huf
        2
    huf  
    OP
       Jan 22, 2022
    @chendy 你好,我的意思是文档中的“新创建的字符串是参数字符串的副本”这句话怎么理解,既然是副本为什么会受字符串常量的影响?那都是使用的字符串常量为什么使用==符号判断又会是 false
    chendy
        3
    chendy  
       Jan 22, 2022
    @huf 分清楚”内容相同“和”是同一个“就行了
    likeunix
        4
    likeunix  
       Jan 22, 2022 via Android   1
    它说的那个副本是浅克隆,你说的副本是深克隆。它虽然产生了副本,但是都还是指向同一个存储字符的内存地址,所以你改了一个就都变了。
    eason1874
        5
    eason1874  
       Jan 22, 2022
    这里的 copy 翻译成拷贝会好理解很多吧

    new String("abc") 是拷贝 abc 的值,而非引用,所以是拷贝了 abc 的值 def 传入一个新的地址

    所以使用 == 比较引用地址的时候 false ,使用 equals() 比较值的时候则为 true
    huf
        6
    huf  
    OP
       Jan 22, 2022
    @chendy 其实就是不太理解这个“副本”是具体怎么个副本法,如果只是单纯的”内容相同“那么修改字符串常量池中字符串的内容不应该影响 new String 这种“副本”方式创建的字符串的内容,如果说是”同一个“那么使用==操作符应该是 true 才对,所以也很好奇他这个“副本”是怎么个”副本“法
    huf
        7
    huf  
    OP
       Jan 22, 2022
    @likeunix 谢谢你,好像用浅克隆可以来理解这个意思
    iseki
        8
    iseki  
       Jan 23, 2022
    换个角度理解,文档的含义是创建 String 对象的副本,至于对象里面的那个 array 属于不公开的实现细节,文档并没有保证会创建那个 array 的副本。而你用反射进行修改很显然是不正常的行为,那么出现问题就是很正常的咯~~~
    About     Help     Advertise     Blog     API     FAQ     Solana     1068 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 39ms UTC 23:26 PVG 07:26 LAX 16:26 JFK 19:26
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86