Java中的String详解

本文详细探讨了 Java 中 String 类的使用方式,包括字符串字面量与 new 创建的区别,以及 intern 方法的作用。并通过实例展示了不同情况下字符串比较的结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

String类代表字符串。Java 程序中的所有字符串字面值(如 “abc” )都作为此类的实例实现。

首先来看一个关于String示例:

 String s1 = "HelloWorld";
 String s2 = "HelloWorld";
 String s3 = new String("HelloWorld");
 String s4 = "Hello";
 String s5 = "World";
 String s6 = "Hello" + "World";
 String s7 = s3 + s4;

 System.out.println(s1 == s2);//1:输出为true

 System.out.println(s1 == s3);//2:输出为false

 System.out.println(s1 == s6);//3:输出为true

 System.out.println(s1 == s7);//4:输出为false

 System.out.println(s1 == s7.intern());//5:输出为true

 System.out.println(s3 == s3.intern());//6:输出为false

输出结果:
这里写图片描述
看了输出结果,你可能会有很多疑惑,没关系,我们对输出结果分别进行分析:

一、为什么输出语句1输出为true,而输出语句2却输出为false?

在解析这个问题之前,我们先来了解一下JVM内存中的栈(stack)、堆(heap)和方法区:

► 栈中保存的是:基本数据类型的变量、对象的引用、函数调用的现场。

► 堆中保存的是:通过new关键字和构造器创建的对象。堆是垃圾收集器管理的主要区域。

► 它们之间的区别是:栈空间操作起来最快但是栈很小,通常大量的对象都是放在堆空间,栈和堆的大小都可以通过JVM的启动参数来进行调整,栈空间用光了会引发StackOverflowError,而堆和常量池空间不足则会引发OutOfMemoryError。

► 举例说明:String str = new String(“hello”)这个语句中变量str放在栈上,用new创建出来的字符串对象放在堆上,而”hello”这个字面量是放在方法区的。

JVM中内存分布:
图片源于网络
了解完内存后我们来解决这个问题,String实例的创建方式主要是以下两种:

  • 直接赋值:String s1 = "HelloWorld"
  • 通过new关键字来创建:String s3 = new String("HelloWorld")
    这两种方式的内存示意图:
    示意图
    这两种创建方式的区别是它们产生实例的过程,以上面示例进行演示:1.直接赋值会先检查字符串常量池中是否含有HelloWorld字符串,如果HelloWorld字符串已经存在,那么就直接指向; 如果没有,则将HelloWorld添加进常量池并且指向。
    2.通过new关键字来创建,会向堆申请内存,来存储HelloWord字符串对象,指向的是堆中的字符串对象。通过new操作符创建的字符串对象不指向字符串池中的任何对象,采用new 创建的字符串对象也不会进入字符串池。

输出语句1比较的是s1和s2,在执行String s1="HelloWorld"时会将“HelloWorld”添加进常量池,s2赋值时“HelloWorld”已经存在于常量池中,因此s1和s2指向常量池中同一个字符串,所以输出为true。而输出语句比较的是s1和s3,s3是通过new关键字创建的字符串,通过new操作符创建的字符串对象不指向字符串池中的任何对象,因此输出为false。

二、为什么输出语句3输出为true,而输出语句4却输出为false?

解析:字符串相加的时候,如果相加的都是静态字符串,那么跟直接赋值相同,会先检查字符串常量池中字符串是否存在,如果经存在,就直接指向,如果不存在,就将字符串添加进常量池并且指向【String s6="Hello"+"World"String s1="HelloWorld"实质上是相同的,String s6="Hello"+"World"在编译阶段就会被处理成String s6="HelloWorld"】,所以输出语句3输出为true;如果相加时包含了变量,如String s7=s3 + s4中包含了s3,s4两个变量,那么就相当于通过new关键字来创建,因此输出语句4输出为false。

三、String中intern方法详解

当调用 intern 方法时,如果字符串常量池已经包含一个等于此 String 对象的字符串(用 equals(Object) 方法确定),则返回池中的字符串。否则,将此 String 对象添加到池中,并返回此 String 对象的引用。
这就可以解释输出语句5和6的输出结果:
输出语句5比较的是s1跟s7.intern(),s1指向的是字符串常量中的“HelloWorld”,s7是由s3+s4拼接起来,字面量为“HelloWorld”,调用s7的intern()时,由于字符串常量池中已经包含了HelloWorld,因此返回的是已经存在的HelloWorld,跟s1所指向的是同一个对象,所以输出语句5输出的为true;

输出语句6中比较的是s3和s3.intern();s3是通过new关键字创建的对象,跟字符串常量池没有丝毫关系,因此输出为false。

四、String中常用的方法(了解更多方法请参考API)

(1)length() 字符串的长度
   例:char chars[]={‘a’,’b’.’c’};
     String s=new String(chars);
     int len=s.length();

(2)charAt() 截取一个字符
   例:char ch;
     ch=”abc”.charAt(1); 返回’b’
    
(3)indexOf()和lastIndexOf()
indexOf() 查找字符或者子串第一次出现的地方。
   lastIndexOf() 查找字符或者子串是后一次出现的地方。
  
(4)substring()
此方法有两个重载:String substring(int startIndex) 和String substring(int startIndex,int endIndex)

(5)替换:replace()
  
(6)trim() 去掉起始和结尾的空格

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值