本文介绍了这个Java代码片段如何工作? (字符串池和反射)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Java字符串池加上反射可以在Java中产生一些难以想象的结果:

Java string pool coupled with reflection can produce some unimaginable result in 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" 

马里奥怎么了?

推荐答案

你基本上改变了它。是的,通过反射,你可以违反字符串的不变性......并且由于字符串实习,这意味着任何使用Mario(除了在更大的字符串常量表达式中,这将在编译时解析)将结束在程序的其余部分中作为Luigi。

You changed it, basically. Yes, with reflection you can violate the immutability of strings... and due to string interning, that means any use of "Mario" (other than in a larger string constant expression, which would have been resolved at compile-time) will end up as "Luigi" in the rest of the program.

这种情况是为什么反射需要安全权限......

This kinds of thing is why reflection requires security permissions...

请注意表达式 str ++Mario 执行任何编译时串联,因为左边-Anociativity + 。它实际上是(str +)+Mario,这就是为什么你仍然会看到 Luigi Luigi 。如果您将代码更改为:

Note that the expression str + " " + "Mario" does not perform any compile-time concatenation, due to the left-associativity of +. It's effectively (str + " ") + "Mario", which is why you still see Luigi Luigi. If you change the code to:

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

...然后你会看到 Luigi Mario 因为编译器会将Mario插入另一个字符串Mario

... then you'll see Luigi Mario as the compiler will have interned " Mario" to a different string to "Mario".

这篇关于这个Java代码片段如何工作? (字符串池和反射)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-16 07:42