编程语言
首页 > 编程语言> > Java入门part8--String类01

Java入门part8--String类01

作者:互联网

String类


创建字符串的方式

方式1: 直接赋值

String str="abed";//直接赋值

方式2: 构造方法

String str2=new String("abce"); 

这样会产生两个对象 不建议使用

方式3:

 char[] array={'a','b','c','d'};
 String str3=new String(array);

请解释String类中两种对象实例化的区别

  1. 直接赋值:只会开辟一块堆内存空间,并且该字符串对象可以自动保存在对象池中以供下次使用。
  2. 构造方法:会开辟两块堆内存空间,其中一块成为垃圾空间,不会自动保存在对象池中,可以使用intern()方法手工入池。

因此,一般采用直接赋值的方法创建字符串

字符串比较相等

    public static void main(String[] args) {
        String str = "abcdef";//直接赋值
        String str2 = new String("abcdef");
        char[] array = {'a','b','c','d','e','f'};
        String str3 = new String(array);
        String str4 = "abc"+"def";//编译期已经确定-》"abcdef"
        String str5 = "abc"+new String("def");
        System.out.println(str == str2);//false
        System.out.println(str == str3);//false
        System.out.println(str == str4);//true
        System.out.println(str == str5);//false
        String str6 = "abc";
        String str7 = "def";
        String str8 = str6+str7;
        System.out.println(str == str8);//false

图解剖析内部存储布局:
在这里插入图片描述
文字详解各种方式的内部存储

注意:
String str="ab"+"cd"+30; 其中产生了两个对象,“ab”+“cd"在编译期间已经确定是"abcd"了,所以"ab”+“cd"创建了一个对象,然后再创建一个对象存放"abcd”+30的结果,将结果的地址给str。所以创建了两个对象

intern()

.intern()手动将String对象加入到字符串常量池中

  1. 常量池当中已经有该字符串 直接返回常量池当中字符串对象的地址
  2. 常量池当中不存在 在常量池当中生成该对象的引用

理解字符串的不可变

String类内部部分源码如下:

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    private final char value[];
    private int hash; // Default to 0
    ...
    public String() {
        this.value = "".value;
    }
    public String(String original) {
        this.value = original.value;
        this.hash = original.hash;
    }
    ...

有源码可得String类内部实现也是基于 char[] 来实现的, 但是 String 类中char value[]被final修饰,所以无法修改

String str = "hello" ;
str = "Horld" ;
System.out.println(str);
//执行结果:Hello

在这里插入图片描述

由上面的内部存储图上看,虽说结果确实改变了,但并不是 String 对象本身发生改变, 而是 str 引用到了其他的对象

如果一定要修改Sring,只有两种方法:

str="Hello";
str="h"+str.substring(1); 

str.substring(1);从1号下标开始提取一直到字符串结束
这样产生了一个新对象"hello" 并没有改变常量池中的Hello

 public static void main(String[] args) throws NoSuchFieldException,
        IllegalAccessException {
    String str = "hello";
    
    // 获取 String 类中的 value 字段  这个 value 和 String 源码中的 value 是匹配的
    Class clc = String.class;
    Field field = clc.getDeclaredField("value");

      // 将这个字段的访问属性设为 true
    field.setAccessible(true);
    
    // 把 str 中的 value 属性获取到.
    char[] value = (char[]) field.get(str);
    System.out.println(Arrays.toString(value));//执行结果[h, e, l, l, o]

    
    // 修改 value 的值
    value[0] = 'H';
    System.out.println(Arrays.toString(value));//执行结果[H, e, l, l, o]
}

为什么 String 要不可变?(不可变对象的好处是什么?)

  1. 方便实现字符串对象池. 如果 String 可变, 那么对象池就需要考虑何时深拷贝字符串的问题了.
  2. 不可变对象是线程安全的.
  3. 不可变对象更方便缓存 hash code, 作为 key 时可以更高效的保存到 HashMap 中.
穿撒板儿的追风少女 发布了22 篇原创文章 · 获赞 4 · 访问量 2404 私信 关注

标签:01,Java,String,对象,创建,str,part8,abcdef,常量
来源: https://blog.csdn.net/qq_43360037/article/details/104522736