Java中关于String类详解

目录

一、创建字符串

常见的创建字符串的三种方式:

public class test01 {
   
    public static void main(String[] args) {
   
         //方式一
        String s = "zbd";
        System.out.println(s);
         //方式二
        String str = new String("hello");
        System.out.println(str);
         //方式三
        char[] chars = {
   'z','b','c'};
        System.out.println(chars);
    }
}

Java数组, String, 以及自定义的类都是引用类型
如下面的例子:ss1指向同一块对象,修改s的指向,不会改变s1的指向,它只是将 s 这个引用指向了一个新的 String 对象。
用双引号引起来的是字面值常量,它里面的内容是不能被修改的,我们只能修改其指向。
例:

 public static void main(String[] args) {
   
        String s = "zbd";
        String s1 = s;
        System.out.println(s);
        System.out.println(s1);
        System.out.println("===========");
        s = "q";
        System.out.println(s);
        System.out.println(s1);
    }

执行结果如下:
在这里插入图片描述
不是说传引用就能改变实参的值,要看引用的指向到底有没有改变。
如:

public static void func(String str, char[] chars){
   
         str = "niHao";
        chars[0] = 'u';
    }
    public static void main(String[] args) {
   
        String str = "zbd";
        char[] chars = {
   'z','b','c'};
        func(str,chars);
        System.out.println(str);
        System.out.println(chars);
    }

运行结果:
在这里插入图片描述
内存图:

在这里插入图片描述
在传参的时候,str和chars的地址都被传了过去,可是str指向了新的对象,所以其地址也就改变了,但是chars只是通过传参修改了其引用的第一个元素,其地址并未改变。

二、字符串常量池

三种常见的常量池:

  1. Class文件常量池: 如:int a = 10;磁盘上的
  2. 运行时常量池:当程序把编译好的字节码文件加载到JVM当中后,会生成一个运行时常量池,存放在方法区、实际上是Class文件常量池。
  3. 字符串常量池:主要存放字符串常量,本质上是一个哈希表又称为StringTable,是由双引号引起来的字符串常量。从JDK1.8开始,字符串常量池放在了堆里面。
    哈希表为一种数据结构,是描述和组织数据的一种方式。
    哈希表在存储数据的时候,会根据一个映射关系进行存储,如何映射,需要设计一个函数(哈希函数)。

String类的设计使用了共享设计模式。

JVM底层实际上会自动维护一个对象池(字符串常量池)。

  • 如果现在采用了直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存到这个对象池之中.
  • 如果下次继续使用直接赋值的模式声明String类对象,此时对象池之中如若有指定内容,将直接进行引用。
  • 如若没有,则开辟新的字符串对象而后将其保存在对象池之中以供下次使用。

String类中两种对象实例化的区别:

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

三、字符串比较相等

String 使用 == 比较并不是在比较字符串内容, 而是比较两个引用是否是指向同一个对象

例一:

 public static void main(String[] args) {
   
        String str1 = "hello";
        String str2 = new String("hello");
        System.out.println(str1 == str2);//false
    }

通过 String str2 = new String("hello"); 这样的方式创建的 String 对象,相当于在堆上另外开辟了空间来存储"hello" 的内容, 也就是内存中存在两份 “hello”.
例二:

  public static void main(String[] args) {
   
        String str1 = "hello";
        String str2 = "hello";
        System.out.println(str1 == str2);//true
    }

str1str2 是指向同一个对象的. 此时如 “hello” 这样的字符串常量是在字符串常量池 中。
像 “hello” 这样的字符串字面值常量, 也是需要一定的内存空间来存储的. 这样的常量具有一个特点, 就是不需要修改(常量). 所以如果代码中有多个地方引用都需要使用 “hello” 的话, 就直接引用到常量池的这个位置就行了, 而没必要把 “hello” 在内存中存储两次.

例三:

 public static void main(String[] args) {
   
        String str1 = "hello";
        String str2 = "he"+"llo";//此时 he和llo都是常量,编译的时候,就已经确定好了是"hello"
        String str3 = "he";
        String str4 = str3+"llo";//此时str3是一个变量,编译的时候,不知道是啥
        System.out.println(str1 == str2);//true
        System.out.println(str1 == str4);//false
    
  • 14
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值