且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使用反射修改字符串的目的是什么?

更新时间:2022-05-30 05:16:39

他在做什么:



他正在获取一些他知道正确长度的字符数组(例如String的大写版本)并将其作为String的后备数组。 (支持数组在String类中称为 value 。)

为了说明你可以在那里放置任何char数组。

To illustrate that you could put any char array there you wanted.

字符串是不可变的,这可以避免不变性。当然,不建议这样做 - 永远。相反,如果他说注意,因为人们可能会对你的代码执行此操作,我不会感到惊讶。即使你认为你的东西是安全的,也可能不是!

String is immutable, and this allows you to circumvent the immutability. Of course, this is not recommended to do - EVER. On the contrary, I would not be surprised if he was saying "Watch out, because people could potentially do this to YOUR code. Even if you think your stuff is safe, it might not be!"

这涉及广泛的影响。不可变变量不再是不可变的。最终变量不再是最终变量。线程安全对象不再是线程安全的。您认为可以依赖的合同,您不能再这样做了。所有这些都是因为某个工程师在某个地方遇到了问题,他无法用正常手段修复,所以他深入研究解决问题。 不要'那个人'。

The implications of this are wide reaching. Immutable variables are no longer immutable. Final variables are no longer final. Thread safe objects are no longer thread safe. Contracts you thought you could rely upon, you can no longer do so. All because some engineer somewhere had a problem he couldn't fix with normal means, so he delves into reflection to solve it. Don't be 'that guy'.

您还会注意到现在如何更改该String的hashCode。所以,如果你从未计算过该String的hashCode,它仍然为0,所以你没事。另一方面,如果你计算了它,当你把它放在HashMap或HashSet中时,它将不会被检索。

You'll also note that how the hashCode for that String would now be changed. So, if you've never calculated the hashCode for that String, it's still 0 so you're okay. On the other hand, if you have calculated it, when you go to put it in a HashMap or HashSet, it won't be retrieved.

考虑以下内容: / p>

Consider the following:

import java.util.*;
import java.lang.reflect.*;

class HashTest {        

    /** Results:
     C:\Documents and Settings\glowcoder\My Documents>java HashTest
        Orig hash: -804322678
        New value: ***
        Contains orig: true
        Contains copy: false
     */

    public static void main(String[] args) throws Exception {

        Set<String> set = new HashSet<String>();
        String str = "***";
        System.out.println("Orig hash: " + str.hashCode());
        set.add(str);

        Field stringValue = String.class.getDeclaredField("value");
        stringValue.setAccessible(true);
        stringValue.set(str, str.toUpperCase().toCharArray()); // 

        System.out.println("New value: " + str);

        String copy = new String(str); // force a copy
        System.out.println("Contains orig: " + set.contains(str));
        System.out.println("Contains copy: " + set.contains(copy));
    }

}

我敢打赌他这样做作为对不良行为的警告,而不是显示酷的伎俩。

I would bet he is doing this as a warning against bad behavior rather than showing a 'cool' trick.

编辑:我找到了你所指的文章,以及它所基于的文章。最初的文章指出:这意味着如果另一个包中的一个类使用实习字符串摆弄,它会对你的程序造成严重破坏。这是件好事吗?(你不需要回答;-)我我认为这很清楚这是一个保护指南,而不是如何编码的建议。

I found the article you're referring to, and the article it is based on. The original article states: "This means that if a class in another package "fiddles" with an interned String, it can cause havoc in your program. Is this a good thing? (You don't need to answer ;-) " I think that makes it quite clear this is more of a protection guide than advice on how to code.

所以如果你只用一条信息离开这个线程,反思是危险的,不可靠的,不容小觑!

So if you walk away from this thread with only one piece of information, it is that reflection is dangerous, unreliable, and not to be trifled with!