再谈Java-String

简介: 再谈Java-String


一个案例

有以下案例:

public class Main {
\
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "hello";
        String s3 = new String("hello");
        String s4 = new String("hello");
        System.out.println(s1 == s2);
        System.out.println(s1 == s3);
        System.out.println(s3 == s4);
    }
 
}

输出结果为:

true

false

false

为什么s1和s2是同一个对象为什么呢?

在Java程序中,类似于:1,2,3,3.14,“hello"等字面类型的常量经常频繁使用,为了使程序的运行速度更快更节省内存,Java为8种基本数据类型和String类都提供了常量池

这个字符串常量池底层就是一个哈希表, 名为StringTable. 也就是一个String对应一个Value.

什么是池?

池是编程中经常有的概念, 是一种重要的提升效率的方式, 我们会经常遇到各种池, 例如线程池, 内存池等等.

为了节省空间, 和提高运行效率, java中引用了:

  1. Class文件常量池
  2. 运行时常量池
  3. 字符串常量池

字符串常量池

这个字符串常量池底层使用c/c++写的, 我们在jvm中去看源码的话,会发现其实这个常量池是一个StringTable的类, 实际上是一个固定大小的哈希表

String对象的创建

一个完整的String对象:

可以看到里面有一个字符数字, 然后还有一个hash值, 其中这个hash值为0.

图解

那么对于字符串常量池, 字符串的存储又是怎么样的呢?

直接使用字符串常量赋值

public class Main {
    public static void main(String[] args) {
        String s1 = "hello";
        String s2 = "hello";
        System.out.println( s1 == s2); // true
    }
}

运行结果为True;

首先String s1是在main方法中的, 理论上他是一个局部变量,是一个字符串的引用, 他是被放在栈区的.

首先创建字符串S1, 将其放入常量池, 然后创建s2, 然后遍历哈希表, 发现哈希表对应的哈希值已经存在, 所以直接将这个s2引用指向s1的那个字符串.

只要是new的对象,都是唯一的

intern方法

intern方法是一个本地(native)方法, 底层使用c++实现, 看不到其实现的源代码, 该方法的作用是手动将创建的String对象, 添加到常量池当中去.

一个例子:

public class Main {
    public static void main(String[] args) {
        char[] ch = new char[] {'a','b','c'};
        String stringCh = new String(ch);
        String s1 = "abc";
        System.out.println(s1 == stringCh);
    }
}

提问: 在创建了stringCh对象只有, 常量池当中有abc字符串吗?

看运行结果:

结果为false, 说明stringCh中的"abc"没有被放入常量池, 此时再和s1比较的话, 就是两个不同的对象.

如果使用intern将其加入到常量字符串呢?

public class Main {
    public static void main(String[] args) {
        char[] ch = new char[] {'a','b','c'};
        String stringCh = new String(ch);
        stringCh.interm();
        String s1 = "abc";
        System.out.println(s1 == stringCh);
    }
}

结果为true, 可以看到intern方法把stringCh放入了常量池.


目录
相关文章
|
1月前
|
Java API 索引
Java基础—笔记—String篇
本文介绍了Java中的`String`类、包的管理和API文档的使用。包用于分类管理Java程序,同包下类无需导包,不同包需导入。使用API时,可按类名搜索、查看包、介绍、构造器和方法。方法命名能暗示其功能,注意参数和返回值。`String`创建有两种方式:双引号创建(常量池,共享)和构造器`new`(每次新建对象)。此外,列举了`String`的常用方法,如`length()`、`charAt()`、`equals()`、`substring()`等。
17 0
|
30天前
|
存储 安全 Java
Java中的这些String特性可能需要了解下
Java中的String特性你知道哪些?虽然String很常见,通过源码可以看到String的值传递、字符串表和不可变性。本文基于JDK17说明。
33 1
|
1月前
|
Java 索引
Java中String方法学习总结_kaic
Java中String方法学习总结_kaic
|
10月前
|
存储 安全 Java
【Java 基础】你真的会用 String 吗?
【Java 基础】你真的会用 String 吗?
62 0
|
1月前
|
Java C# C++
【JAVA】 String 类简述笔记
【JAVA】 String 类简述笔记
33 0
|
Java 索引
java基础string常用方法
String当中与获取相关的常用方法有: public int length():获取字符串当中含有的字符个数,拿到字符串长度。 public String concat(String str):将当前字符串和参数字符串拼接成为返回值新的字符串。 public char charAt(int index);获取指定索引位置的单个字符。(索引从0开始。) public int index0f(Stringstr):查找参数字符串在本字符串当中首次出现的索引位置,如果 没有返回-1值。
62 0
|
Java 索引
Java 最常见的面试题:String 类的常用方法都有那些
Java 最常见的面试题:String 类的常用方法都有那些
Java 面试,创建了几个String 对象? 我让问!让你问!让你问!(二)
Java 面试,创建了几个String 对象? 我让问!让你问!让你问!(二)
146 0
Java 面试,创建了几个String 对象? 我让问!让你问!让你问!(二)
|
存储 缓存 Java
Java 面试,创建了几个String 对象? 我让问!让你问!让你问!(一)
Java 面试,创建了几个String 对象? 我让问!让你问!让你问!(一)
115 0
Java 面试,创建了几个String 对象? 我让问!让你问!让你问!(一)
|
存储 缓存 安全
细读源码之Java String (一)
细读源码之Java String (一)
71 0
细读源码之Java String (一)

热门文章

最新文章