大家都知道,在JAVA中字符串一旦声明就不可改变,如果尝试修改字符串的内容,将会重新实例化一个新的字符串对象,这也是为了安全性和效率。

  由于字符串在程序之中被大量使用,所以JAVA引入了一个字符串常量池,所有被声明的字符串都会保存在字符串常量池中,如果下次使用到同样的字符串,就会从常量池中获取。由于字符串可以用来表示很多重要的信息,例如用户名,密码,URL地址等,如果被引用的字符串可以随意修改,那么这些信息也会变得非常不安全。

  但是,反射让这一切发生了变化,字符串并不是一种基本数据类型,他的底层实际上是字符数组,虽然数组被定义为了final,但final关键字只在编译期有效果,运行期间就没有效果了,这个和泛型是一样的。那么,只要我们能够获取到这个字符数组,那么就可以修改字符串的内容了!String类虽然提供有一个toCharArray()方法,但是这个方法实际上是赋值的这个字符串的字符数组出来:

官方源代:

 public char[] toCharArray() {
// Cannot use Arrays.copyOf because of class initialization order issues
char result[] = new char[value.length];
System.arraycopy(value, 0, result, 0, value.length);
return result;
}

  这样一来,想要获取到这个字符数组,首先想到的就是反射了。反射同样可以解除封装,所以private也不会造成什么威胁!

反射消除String类对象不可变特性:

 public static void main(String[] args) throws Exception{
String str = "hello" ; //实例化一个String类对象
String s = str ; //用于后面的比较测试
//打印字符串和hashCode编码
System.out.println(str + "::" + str.hashCode());//hello::99162322
Class<?> cls = String.class;
Field value = cls.getDeclaredField("value");
value.setAccessible(true);
//反射取得str对象的字符数组
char[] arr = (char[]) value.get(str);
//修改字符数组的内容
arr[0] = 's' ;
//打印字符串和hashCode编码
System.out.println(str + "::" + str.hashCode());//sello::99162322
//比较两次是否相同
System.out.println(s == str);//true
}

  这样一来,就可以修改字符串的引用内容了。同样,只需要使用使用Field中的set方法设置一个新的字符数组就可以了。

 public static void main(String[] args) throws Exception {
String str = "hello"; // 实例化一个String类对象
char c[] = new char[]{'a','a','a','a','a','a','a','a'};
String s = str; // 用于后面的比较测试
// 打印字符串和hashCode编码
System.out.println(str + "::" + str.hashCode());// hello::99162322
Class<?> cls = String.class;
Field value = cls.getDeclaredField("value");
value.setAccessible(true);
// 修改字符数组的内容
value.set(str, c);
// 打印字符串和hashCode编码
System.out.println(str + "::" + str.hashCode());// aaaaaaaa::99162322
// 比较两次是否相同
System.out.println(s == str);// true
}

反射消除String类对象的不可变特性的更多相关文章

  1. Java技术——String类为什么是不可变的

    0. 前言   如果一个对象,在它创建完成之后不能再改变它的状态,包括对象内的成员变量.基本数据类型的值等等.那么这个对象就是不可变的.众所周知String类就是不可变的.转载请注明出处为SEU_Ca ...

  2. java中,方法可以访问他的类对象的任何私有特性

    java中,方法可以访问他的类对象的任何私有特性 读一本书(Core Java for the Impatient)时,发现这个注意,以前的时候没有在意,今天仔细想想发现记忆不深刻.记录一下 下面代码 ...

  3. Java的string类为什么是不可变的

    最流行的Java面试题之一就是:什么是不可变对象(immutable object),不可变对象有什么好处,在什么情况下应该用,或者更具体一些,Java的String类为什么要设成immutable类 ...

  4. String类为什么是不可变的

    String类为啥是final的? 我们找到string的jdk源码 1.看到String类被final修饰.这里你就要说出被final修饰的类不能被继承,方法不能被重写,变量不能被修改. 2.看到f ...

  5. Java反射 - 1(得到类对象的几种方法,调用方法,得到包下的所有类)

    通过反射获得对象的方法 准备工作: 有一个User类如下 package o1; /** * Created by yesiming on 16-11-19. */ public class User ...

  6. java笔记--String类对象解析与运用

    --如果朋友您想转载本文章请注明转载地址"http://www.cnblogs.com/XHJT/p/3877236.html "谢谢-- 1.String中的equals和==的 ...

  7. .NET解析xml字符串,通过反射给实体类对象赋值,获取实体类数据列表

    /// <summary> /// 解析xml字符串 转换为实体类列表数据 /// </summary> /// <param name="xmlStr&quo ...

  8. String类对象两种实例化方式比较

    第一种:直接赋值 String str =  "hello!" ; 在java中,有一个字符串常量池,对于这种直接赋值的,会直接写进常量池(常量池里面不存在其value,) 自JD ...

  9. JAVA笔记3__字符串String类/对象一对一关联

    import java.lang.String; import java.util.Scanner; public class Main { public static void main(Strin ...

随机推荐

  1. HDU 5768 - Lucky7

    题意: 给出x, y, m[1...n], a[1..n].     在[x,y]中寻找 p % 7 = 0 且对任意(1<= i <=n) p % m[i] != a[i] 的数字的个数 ...

  2. HttpClient基础教程

    1.HttpClient相关的重要资料 官方网站:http://hc.apache.org/ API:http://hc.apache.org/httpcomponents-client-4.3.x/ ...

  3. php-fpm日志告警"seem busy"

    php-fpm日志中出现"WARNING: [pool www] seems busy (you may need to increase pm.start_servers, or pm.m ...

  4. MYSQL <=>运算符

    <=> 与 =

  5. Nginx 变量漫谈(一)

    Nginx 的配置文件使用的就是一门微型的编程语言,许多真实世界里的 Nginx 配置文件其实就是一个一个的小程序.当然,是不是“图灵完全的”暂且不论,至少据我观察,它在设计上受 Perl 和 Bou ...

  6. python学习day4

    目录 一.迭代器 二.yield生成器 三.装饰器 四.递归 五.基础算法 迭代器 #1.在不使用for循环的情况下 li = [11 ,22, 33, 44] #count = len(li) #s ...

  7. LoggingApplicationListener

    org.springframework.boot:spring-boot:1.3.0.M1 spring-boot-1.3.0.M1.jar package org.springframework.b ...

  8. 必学100个常用linux命令大全

    1,echo “aa” > test.txt 和 echo “bb” >> test.txt //>将原文件清空,并且内容写入到文件中,>>将内容放到文件的尾部 2 ...

  9. Virtualbox下实现Ubuntu虚拟机和win7主机文件共享(很简单,亲自试用,按此步骤一般都会成功)

    最近做一个操作系统实验,第一个实验即是实现Ubantu虚拟机与主机之间的共享. 本例用的是VirtualBox虚拟机,若使用Vmware WorkStation虚拟机则方法与下文介绍略有不同,但基本相 ...

  10. uva540 Team Queue by sixleaves

    这道题目.主要是对队列的灵活应用.其实就是一道模拟题目,只要你洞察出题目的本质就十分简单.题目意思大体是有多组测试数据,每组的一开始是一个数字t,代表一共有多少的团队,接着是t行输入,每一行都由一个数 ...