• 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);
     }

    }

  • 相关阅读:
    测试sql 查询时间
    C# 数组 ArrayList Array 在C#里把ArrayList转换为Array 或 把Array转换为ArrayList
    DotNet软件开发框架
    C# Socket多线程编程实例
    Yahoo!网站性能最佳体验的34条黄金守则
    最基本的Socket编程(C#)
    完全解决VS2008通过Internet连接VSS2005
    追MM与设计模式的有趣见解
    一个GridView的PagerTemplate
    线程
  • 原文地址:https://www.cnblogs.com/zhanghongqiang/p/4341308.html
Copyright © 2020-2023  润新知