V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
asanelder
V2EX  ›  程序员

Java 原地修改字符串, how?

  •  
  •   asanelder · 55 天前 · 2093 次点击
    这是一个创建于 55 天前的主题,其中的信息可能已经有所发展或是发生改变。

    比如说

    String s = "hallo world";

    在不创建新的 string 下, 把 s 修改成

    s = "hello world";

    怎么做, 兄弟们...

    24 条回复    2022-06-16 00:47:10 +08:00
    chihiro2014
        1
    chihiro2014  
       55 天前
    重新赋值
    cheng6563
        2
    cheng6563  
       55 天前
    反射进去改 char[] value
    ianEros
        3
    ianEros  
       55 天前
    String 是 fianl 不能干
    luckyrayyy
        4
    luckyrayyy  
       55 天前
    反射和 unsafe
    dcsuibian
        5
    dcsuibian  
       55 天前   ❤️ 1
    Java 的字符串是不可变的(优点)。
    rainboat
        6
    rainboat  
       55 天前
    java 的 String 是不可变对象,创建一个新的 String 多简单,有啥不能这么做的理由吗?
    Kasumi20
        7
    Kasumi20  
       55 天前
    用二进制修改器去修改.class 或者.jar 文件
    chendy
        8
    chendy  
       55 天前
    反射进去改 value 就行
    脑筋急转弯类面试题吧,没啥实际用途
    后续问题还有给你一坨字符串,反射改了其中一个,问哪些会跟着一起改
    abc0123xyz
        9
    abc0123xyz  
       55 天前
    指鹿为马

    用暴力威胁地球人

    "hallo world" =√

    "hello world"=×
    nothingistrue
        10
    nothingistrue  
       55 天前
    String 是 final class + no setter ,你要想修改就只能用反射,还得是禁用安全限制的反射。虽然可以这样做,但是要做也得给其他类做,String 是可以这样设置的,强行进去修改会引起指数级的麻烦。问 String 为啥设计成不可变,都比借 String 问反射都好。
    yazinnnn
        11
    yazinnnn  
       55 天前
    是不是你的需求有问题?
    asanelder
        12
    asanelder  
    OP
       55 天前
    @rainboat #6
    @chendy #8
    @yazinnnn #11

    不是来自现实问题, 俺今天刷 leetcode, 要求 inplace, 所以突发这样的想法... 要是使用 char[]就好办多了
    qbqbqbqb
        13
    qbqbqbqb  
       55 天前
    @asanelder 这种应该属于某些题目的进阶要求吧,题目里也只是说如果你用的编程语言里字符串是可变数据类型的话可以尝试 inplace 做法,不用也能通过。想达成这个目标的话用 Java, Python 这些语言是没办法的,只能换成 C++.
    ragnaroks
        14
    ragnaroks  
       55 天前
    java 未来应该把 csharp 的 Span<T> 抄过去,到时候你再来解决这个问题即可
    CRVV
        15
    CRVV  
       55 天前
    @asanelder

    这是出题人的问题,出题的时候考虑的是用 C 来写,后来又加上了其它的语言。C 的 char* 当然可以随便改。
    你把原来的 String 转成 char[] 来做就好了,返回的时候再转回去。
    这种都是算法题,不是编程语言怎么用的题。
    dorothyREN
        16
    dorothyREN  
       55 天前   ❤️ 1
    String s = "hallo world";
    s = "hello world";
    搞定
    cpstar
        17
    cpstar  
       55 天前
    反射能做到么? String 编译后,放在常量池里,类加载的时候,常量池加载到内存上,然后给一个指针到变量上,所以反射是要反射到加载到内存里的常量池么?有点类似于 C++直接搞内存?
    zpxshl
        18
    zpxshl  
       55 天前 via Android
    java 级别的反射搞不定的
    Eathein
        19
    Eathein  
       54 天前
    可以通过反射修改的,这是测试代码
    public class Test {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
    String s = "a";
    Field value = String.class.getDeclaredField("value");
    value.setAccessible(true);
    byte[] bytes = (byte[]) value.get(s);
    bytes[0] = 66;
    System.out.println(s);//这里 s 输出的就是 66 对应的字符 B
    }
    }
    Eathein
        20
    Eathein  
       54 天前
    final 只能让 value 不指向新的对象,但通过反射光修改原对象是可行的,当然了,这样运行会报警告,不建议这么做,我只是想说实际上可以实现。
    asanelder
        21
    asanelder  
    OP
       54 天前
    @Eathein #19 感谢铁子提供的思路
    @CRVV #15 嗯, 这题俺感觉确实出的不太好, 解题思路和语言相关了
    lisongeee
        22
    lisongeee  
       54 天前
    如果你的变量不是 final 的,可以考虑用 字节码插桩,编译的时候插入修改这个变量的代码,从.java 源码角度来看,确实没有创建新 string
    asanelder
        23
    asanelder  
    OP
       54 天前
    @lisongeee #22 牛啊, 铁子, 真是脑洞大开!
    ericgui
        24
    ericgui  
       54 天前
    @asanelder in-place 指的是不创建新的 array

    你别钻牛角尖
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1773 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 31ms · UTC 16:57 · PVG 00:57 · LAX 09:57 · JFK 12:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.