当前位置: 首页 > 知识库问答 >
问题:

这个Java代码片段是如何工作的?(字符串池和反射)[副本]

禹昊穹
2023-03-14

Java字符串池与反射耦合在一起可以产生一些在Java中难以想象的结果:

import java.lang.reflect.Field;

class MessingWithString {
    public static void main (String[] args) {
        String str = "Mario";
        toLuigi(str);
        System.out.println(str + " " + "Mario");
    }

    public static void toLuigi(String original) {
        try {
            Field stringValue = String.class.getDeclaredField("value");
            stringValue.setAccessible(true);
            stringValue.set(original, "Luigi".toCharArray());
        } catch (Exception ex) {
            // Ignore exceptions
        }
    }
}

以上代码将打印:

"Luigi Luigi" 

马里奥怎么了?

共有1个答案

陈斌
2023-03-14

马里奥怎么了??

基本上是你改了。是的,通过反射,你可以破坏字符串的不变性...由于string interning的原因,这意味着任何“mario”的使用(除了在编译时解析的更大的string常量表达式中)都将在程序的其余部分结束为“luigi”。

这就是为什么反射需要安全权限...

注意,表达式str+“”+“mario”不执行任何编译时级联,这是由于+的左关联性。它实际上是(str+“”)+“Mario”,这就是您仍然看到Luigi的原因。如果将代码更改为:

System.out.println(str + (" " + "Mario"));

...然后您将看到Luigi Mario,因为编译器将“Mario”嵌入到“Mario”的不同字符串中。

 类似资料:
  • Kotlin定义了自己的类: 该类的实例是通过中定义的内联函数构造的: null 我认为在编译之前必须进行某种代码预处理。 请随意用一个更贴切的标题编辑这个问题。

  • 问题内容: 通常,我在互联网上的许多文章中都读到,当我们编写上面的语句时,会创建两个对象。在堆上创建一个String对象,在Literal Pool上创建一个字符串对象。并且堆对象还引用在Literal Pool上创建的对象。(如果我的陈述是错误的,请更正。) 请注意,以上解释是根据我阅读互联网上一些文章后的理解得出的。 所以我的问题是..有什么方法可以停止在文字池中创建字符串对象。怎么做? [请

  • 本文向大家介绍Lua操作字符串的5个代码片段分享,包括了Lua操作字符串的5个代码片段分享的使用技巧和注意事项,需要的朋友参考一下 1.匹配字符串中的数字、字母和下划线 2.替换字符串中的指定字符 3.判断字符串中是否有目标字串 4.从文件的绝对路径中获取到文件名 5.去掉字符串中括号内的内容,并去掉收尾的空格

  • 问题内容: 我有一个方法: 当运行时,我得到如下输出: 现在我该怎样提取实际字符串值入, 使用反射? 问题答案: 看起来您需要引用该类的实例。您可能要调用get和pass的引用,将返回值转换为String。 您可以使用get,如下所示:

  • 问题内容: 众所周知,如果不存在,则在字符串池中添加String值的方法。如果存在,它将返回该值/对象的引用。 我需要知道,当我调用此实习生方法时会做什么? 在字符串池中添加具有不同引用的“ dog”或在字符串池中添加对象引用(我认为不是这种情况)? 我试过了 我只想确保当我调用它时在字符串池中创建具有相同值的新对象?现在我有2个对象的值为“ dog”。一个直接存在于堆中,另一个存在于字符串池中?