Java中String类型的不可变性和驻留池

简介:

一 基本概念

可变类和不可变类(Mutable and Immutable Objects)的初步定义:

可变类:当获得这个类的一个实例引用时,可以改变这个实例的内容。

不可变类:不可变类的实例一但创建,其内在成员变量的值就不能被修改。其中String类就是不可变类的经典应用。

 


二 例子

package cn.xy.test;

public class StringTest
{

 /**
  * a的值在编译时就被确定下来,故其值"xy"被放入String的驻留池(驻留池在堆中)并被a指向。
  * b的值在编译时也被确定,那么b的值在String的驻留池中找是否有等于"xy"的值,有的话也被b 
指向。故两个对象地址一致
  * @return true
  */
 public static Boolean testString1()
 {
  String a = "xy";
  String b = "xy";
  return a == b;
 }
 
 /**
  * b的值在是两个常量相加,编译时也被确定。
  * @return true
  */
 public static Boolean testString2()
 {
  String a = "xyy";
  String b = "xy" + "y";
  return a == b;
 }

 /**
  * b的值为一个变量和一个常量相加,无法编译时被确定,而是会在堆里新生成一个值为"abc"的对象
  * @return false
  */
 public static Boolean testString3()
 {
  String a = "xyy";
  String b = "xy";
  b = b + "y";
  return a == b;
 }
 

 /**
  * b的值都无法编译时被确定,而是会在堆里分别新生成一个对象叫"xyy"。
  * @return false
  */
 public static Boolean testString4()
 {
  String a = "xyy";
  String b = "xy".concat("y");
  return a == b;
 }

 
 /**
  * new String()创建的字符串不是常量,不能在编译期就确定,所以new String() 创建的字符串不放入常量池中,它们有自己的地址空间。 
  * a,b的值都无法编译时被确定,会在堆里分别新生成一个值为"xy"的对象。
  * @return fasle
  */
 public static Boolean testString5()
 {
  String a = new String("xy");
  String b = new String("xy");
  return a == b;
 }

 /**
  * intern()把驻留池中"xy"的引用赋给b。
  * @return true
  */
 public static Boolean testString6()
 {
  String a = "xy";
  String b = new String("xy");
  b = b.intern();
  return a == b.intern();
 }

 

 /**
  * char的toString方法返回的是一个char对象的字符串,而不是我们想象的"xy"
  * @return false
  */
 public static Boolean testString7()
 {
  String b = "xy";
  char[] a = new char[]{'x','y'};
  return a.toString().equals(b);
 }
 


 /**
  * char是一种新的类型,不存在驻留池的概念。
  * @return fasle
  */
 public static Boolean testString8()
 {
  String b = "xy";
  char[] a = new char[]{'x','y'};
  return a.toString() == b;
 }

 

/**
  * String不可变性的体现
  */
 String str = "xy";

 public String chage(String str)
 {
  str = "xyy";
  return str;
 }

 

 /**
  * 一般引用类型的可变性(传值的时候把地址传过去,相当于把仓库的要是交给方法,方法拿到钥匙去移动仓库里的东西)
  */
 Person p = new Person("xy");

 public String changePerson(Person p)
 {
  p.setName("xyy");
  return p.toString();
 }

 public static void main(String[] args)
 {
  print(testString1()); // true
  print(testString2()); // true
  print(testString3()); // fasle
  print(testString4()); // false
  print(testString5()); // false
  print(testString6()); // true

  print(testString7()); // false

  print(testString8()); // false

  StringTest t = new StringTest();
  print(t.str); // xy
  print(t.chage(t.str)); // xxy
  print(t.str); // xy

  print(t.p.toString()); //xy
  print(t.changePerson(t.p)); //xyy
  print(t.p.toString()); //xyy
 }

 
 public static void print(Object o)
 {
  System.out.println(o);
 }

}

本文转自IT徐胖子的专栏博客51CTO博客,原文链接http://blog.51cto.com/woshixy/1031239如需转载请自行联系原作者


woshixuye111

相关文章
|
15天前
|
存储 JavaScript Java
Java 中的 String Pool 简介
本文介绍了 Java 中 String 对象及其存储机制 String Pool 的基本概念,包括字符串引用、构造方法中的内存分配、字符串文字与对象的区别、手工引用、垃圾清理、性能优化,以及 Java 9 中的压缩字符串特性。文章详细解析了 String 对象的初始化、内存使用及优化方法,帮助开发者更好地理解和使用 Java 中的字符串。
Java 中的 String Pool 简介
|
21天前
|
缓存 安全 Java
java 为什么 String 在 java 中是不可变的?
本文探讨了Java中String为何设计为不可变类型,从字符串池的高效利用、哈希码缓存、支持其他对象的安全使用、增强安全性以及线程安全等方面阐述了不可变性的优势。文中还通过具体代码示例解释了这些优点的实际应用。
java 为什么 String 在 java 中是不可变的?
|
2月前
|
Java 测试技术 开发者
Java零基础-indexOf(String str)详解!
【10月更文挑战第14天】Java零基础教学篇,手把手实践教学!
124 65
|
1月前
|
JSON Java 关系型数据库
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
在Java中,使用mybatis-plus更新实体类对象到mysql,其中一个字段对应数据库中json数据类型,更新时报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
63 4
Java更新数据库报错:Data truncation: Cannot create a JSON value from a string with CHARACTER SET 'binary'.
|
15天前
|
存储 Java
Java 11 的String是如何优化存储的?
本文介绍了Java中字符串存储优化的原理和实现。通过判断字符串是否全为拉丁字符,使用`byte`代替`char`存储,以节省空间。具体实现涉及`compress`和`toBytes`方法,前者用于尝试压缩字符串,后者则按常规方式存储。代码示例展示了如何根据配置决定使用哪种存储方式。
|
1月前
|
Java
在Java中如何将基本数据类型转换为String
在Java中,可使用多种方法将基本数据类型(如int、char等)转换为String:1. 使用String.valueOf()方法;2. 利用+运算符与空字符串连接;3. 对于数字类型,也可使用Integer.toString()等特定类型的方法。这些方法简单高效,适用于不同场景。
56 7
|
1月前
|
存储 Java 开发者
Java 中 Set 类型的使用方法
【10月更文挑战第30天】Java中的`Set`类型提供了丰富的操作方法来处理不重复的元素集合,开发者可以根据具体的需求选择合适的`Set`实现类,并灵活运用各种方法来实现对集合的操作和处理。
|
2月前
|
Java
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
本文深入探讨了Java中方法参数的传递机制,包括值传递和引用传递的区别,以及String类对象的不可变性。通过详细讲解和示例代码,帮助读者理解参数传递的内部原理,并掌握在实际编程中正确处理参数传递的方法。关键词:Java, 方法参数传递, 值传递, 引用传递, String不可变性。
68 1
【编程基础知识】(讲解+示例实战)方法参数的传递机制(值传递及地址传递)以及String类的对象的不可变性
|
1月前
|
Java 编译器 开发者
Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面
本文探讨了Java异常处理的最佳实践,涵盖理解异常类体系、选择合适的异常类型、提供详细异常信息、合理使用try-catch和finally语句、使用try-with-resources、记录异常信息等方面,帮助开发者提高代码质量和程序的健壮性。
76 2
|
1月前
|
存储 Java 编译器
Java泛型类型擦除以及类型擦除带来的问题
泛型擦除是指Java编译器在编译期间会移除所有泛型信息,使所有泛型类型在运行时都变为原始类型。例如,`List<String>` 和 `List<Integer>` 在JVM中都视为 `List`。因此,通过 `getClass()` 比较两个不同泛型类型的 `ArrayList` 实例会返回 `true`。此外,通过反射调用 `add` 方法可以向 `ArrayList<Integer>` 中添加字符串,进一步证明了泛型信息在运行时被擦除。
45 2