当前位置: 首页 > 面试题库 >

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

祖波光
2023-03-14
问题内容

我读的一篇文章说Java字符串不是完全不变的。但是,在修改字符串的文章示例代码中,它调用string.toUpperCase()。toCharArray(),该函数返回一个新字符串。那么,无论如何调用toUpperCase()来完成更改字符串的目的是什么?这是代码:

public static void toUpperCase(String orig)
{
 try
 {
    Field stringValue = String.class.getDeclaredField("value");
    stringValue.setAccessible(true);
    stringValue.set(orig, orig.toUpperCase().toCharArray());
 }
 catch (Exception ex){}
}

另外,我注意到string.toUpperCase()本身不起作用。它必须是string.toUpperCase()。toCharArray()。是否有一个原因?


问题答案:

他在做什么:

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

他为什么这样做:

为了说明您可以在其中放置任何char数组。

为什么这样有用:

字符串是不可变的,这使您可以规避不可变性。当然, 不建议这样做-EVER
。相反,如果他说“当心,因为人们可能会对您的代码执行此操作。即使您认为自己的东西是安全的,也可能不是!”,我不会感到惊讶。

其含义是广泛的。不可变的变量不再是不可变的。最终变量不再是最终变量。线程安全对象不再是线程安全的。您认为可以依靠的合同,您将不再可以依靠。所有这些都是因为某个地方的某个工程师遇到了一个他用常规手段无法解决的问题,因此他努力思考以解决问题。
不要成为“那个家伙”。

您还将注意到,现在将如何更改该String的hashCode。因此,如果您从未计算过该String的hashCode,它仍为0,所以您可以。另一方面,如果您已经计算出它,那么当您将其放入HashMap或HashSet中时,将不会检索它。

考虑以下:

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

class HashTest {

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

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

        Set<String> set = new HashSet<String>();
        String str = "StackOverflow";
        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));
    }

}

我敢打赌他这样做是为了警告人们不要不良行为,而不是表现出“酷”的把戏。

编辑:我找到了您所指的文章,以及它所基于的文章。原始文章指出:“这意味着,如果另一个程序包中的一个类在内部字符串的作用下“摆弄”,则会对您的程序造成破坏。这是件好事吗?(您无需回答;-)认为这很清楚,这更像是保护指南,而不是关于编码的建议。

因此,如果您仅通过一条信息就离开了该线程,那就是反射是危险的,不可靠的,并且不容小!!



 类似资料:
  • 我有一个String,newNumber=106,nn=3和差异=3。 输出: 我想修改这个字符串,使输出变成,然后用这个新字符串我想再次修改它,使它变成,基本上我只需要替换新的数字,它是106,并且一直变为11,正如你所看到的,我试图只修改newNumber并用另一个替换它,同时保持整个字符串不变,我只是替换并添加它,这是如何实现的?输出应该是这样的,输出: 我在用步骤求解一个方程,公式无关紧要

  • 修改字符串 到目前为止,我们简单地搜索了一个静态字符串。正则表达式通常也用不同的方式,通过下面的 RegexObject 方法,来修改字符串。 方法/属性 作用 split() 将字符串在 RE 匹配的地方分片并生成一个列表, sub() 找到 RE 匹配的所有子串,并将其用一个不同的字符串替换 subn() 与 sub() 相同,但返回新的字符串和替换次数

  • 问题内容: 我想在打字稿中使用字符串枚举,但在其中看不到对反向映射的支持。我有一个这样的枚举: 我需要这样使用它: 是的,我不知道字符串中有什么,如果字符串未在枚举定义中显示,我需要将其解析为枚举或在运行时解析失败。我该如何做到整洁呢?提前致谢 问题答案: 我们可以将其设为一个类型,并将值设为同一类型。 更严格的版本: 字符串枚举作为此答案:

  • 本文向大家介绍C++ 修改字符串文字,包括了C++ 修改字符串文字的使用技巧和注意事项,需要的朋友参考一下 示例 C ++ 11 "hello world" 是字符串文字,因此对其进行修改会产生未定义的行为。 str上面示例中的初始化在C ++ 03中已正式弃用(计划从该标准的将来版本中删除)。2003年之前,许多编译器可能对此发出警告(例如,可疑转换)。2003年之后,编译器通常会警告不要使用转

  • 介绍 我用这个项目挑战自己。 我需要修改.txt上特定行的数据,而无需执行以下操作: 将所有内容加载到内存中(地图,列表,数组... 必须复制文件(例如 - 一个简单的.txt文件将拥有一切! 文本文件 遵循这种格式,即以“;”作为分隔符的字符串。 我的代码尝试从0到9的数字 (0 到 9 表示第一个数字 - 理解问题 字符串 - 最后两个“0”将是另一个日期格式,即“yy/MM/dd HH:MM

  • 问题内容: true如果传入的数字包含,则此方法返回1。 该+ “”零件的目的是 什么?如何使一个?(据我所知.contains只能使用Strings)。 问题答案: Anint是原始元素。在字符串中添加基元将执行该基元到a的隐式转换,String并将两个字符串加在一起。在这种情况下,将int转换并添加”“(empty String), 可以重写为: 要么 要么