String类

创建字符串

//方式1
String str1 = “Hello world”;
//方式2
String str2 = new String("Hello world") ;
//方式3
char[] array = {'a','b','c'};
String str3 = new String(array);

解释:

//String是引用类型
String str = “Hello”;

这样的代码内存布局如下:
在这里插入图片描述
**引用解释:**引用类似于C语言中的指针,只是在栈上开辟了一小块内存空间保存一个地址,但和指针不同,指针可以进行各种数字运算(如:指针+1),但引用不能。除此我们也可以将引用想象成一个标签,“贴”到一个对象上,一个对象可以贴一个,也可以贴多个,如果一个对象上一个标签都没有,这个对象就会被JVM当成垃圾对象回收掉。
java中数组,String,以及自定义类型都是引用类型。

下面我们来看下面的代码及内存布局

String str1 = "Hello";
String str2 = str1;
//str1和str2指向同一个对象

在这里插入图片描述
在上面的基础上我们再来看下面的代码

str1 = "world";
System.out.println(str2);
// 执行结果 :Hello
//str1只是指向了一个新的string类对象,但是str2的指向还是没有改变。

字符串比较相等

两个int 型的变量可以用==判断其是否相等。但是String呢?
代码1:

String str1 = "Hello";
String str2 = "Hello";
System.out.println(str1 == str2);
// 执行结果:true
//这个代码中str1和str2指向同一个对象

但是下面的代码比较就出现了问题
代码2:

String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1 == str2);
// 执行结果:false
//这种方式创建的String对象相当于在堆上另外开辟了空间来存储“Hello”内容,内存中存了两份“Hello”。str1指向一份“Hello”,str2指向一份“Hello”。

所以Java中比较字符串的内容是否相等,要采用equals方法

String str1 = new String("Hello");
String str2 = new String("Hello");
System.out.println(str1.equals(str2));
// 执行结果:true
equals使用注意事项:
String str = new String("Hello");
// 方式一
System.out.println(str.equals("Hello"));
// 方式二
System.out.println("Hello".equals(str));
//“Hello”这样的字面值常量,本质上也是一个String对象,
   可以用equals等String对象的方法。

字符常量池

(1)直接赋值

String str1 = "hello" ;
String str2 = "hello" ;
String str3 = "hello" ;
System.out.println(str1 == str2); //true
System.out.println(str1 == str3); //true
System.out.println(str2 == str3); //true

在这里插入图片描述
从上图我们可以看到并没有开辟新的堆内存空间。
这是String类的设计使用了共享设计模式。
**解释:**如果现在采用了直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存到这个对象池之中。如果下次继续使用直接赋值的模式声明String类对象,此时对象池之中如若有指定内容,将直接进行引用;如若没有,则开辟新的字符串对象而后将其保存在对象池之中以供下次使用。
(2)采用构造方法

String str = new String ("Hello");

在这里插入图片描述
这样做有两个缺点:
a. 使用String构造方法会开辟两块堆内存,并且其中一块堆内存会成为垃圾空间(字符常量“Hello”也是一个匿名对象,用了一次之后就不在使用了,就会成为垃圾空间,被JVM自动回收掉)。
b.同一个字符串可能会被存储多次,比较浪费空间。
我们可以使用String的intern方法手动把String对象加入字符串常量池中。

// 该字符串常量并没有保存在对象池之中
String str1 = new String("hello") ;
String str2 = "hello" ;
System.out.println(str1 == str2);
// 执行结果:false

String str1 = new String("hello").intern() ;
String str2 = "hello" ;
System.out.println(str1 == str2);
// 执行结果:true

字符串的不可变性

字符串是一种不可变对象,它的内容不可改变。
String类的内部实现是基于Char[]来实现的,但是String类并没有提供set方法之类的来修改内部的字符串数组。

String str = "hello" ;
str = str + " world" ;
str += "!!!" ;
System.out.println(str);
// 执行结果:hello world!!!

上面的代码表面上改了字符串,其实并不是。内存变化如下
在这里插入图片描述
就我们看到str的结果改变了,但并不是String对象本身发生改变,而是str引用到了其他对象。

如果需要修改字符串,则需要借助原字符串,创建新的字符串。代码如下:

String str = 'Hello";
str = "h" + str.substring(1);
System.out.println(str);
//执行结果:hello
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
String a="hello world"; //在java中有一个常量池,当创建String 类型的引用变量给它赋值时,java会到它的常量池中找"hello world"是不是在常量池中已存在。如果已经存在则返回这个常量池中的"hello world"的地址(在java中叫引用)给变量a 。注意a并不是一个对象,而是一个引用类型变量。它里面存的实际上是一个地址值,而这个值是指向一个字符串对象的。在程序中凡是以"hello world"这种常量似的形式给出的都被放在常量池中。 String b=new String("hello world"); //这种用new关键字定义的字符串,是在堆中分配空间的。而分配空间就是由new去完成的,由new去决定分配多大空间,并对空间初始化为字符串"hello world" 返回其在堆上的地址。 通过上面的原理,可以做如下实验: String a="hello world"; String b="hello world"; String c=new String("hello world"); String d=new String("hello world"); if(a==b) System.out.println("a==b"); else System.out.println("a!=b"); if(c==d) System.out.println("c==d"); else System.out.println("c!=d"); //输出结果: a==b c!=d 为什么会出现上面的情况呢? String a="hello world"; String b="hello world"; 通过上面的讲解可以知道,a和b都是指向常量池的同一个常量字符串"hello world"的,因此它们返回的地址是相同的。a和b都是引用类型,相当于c语言里面的指针。java里面没有指针的概念,但是实际上引用变量里面放的确实是地址值,只是java为了安全不允许我们对想c语言中的那样对指针进行操作(如++ 、--)等。这样就有效的防止了指针在内存中的游离。 而对于 String c=new String("hello world"); String d=new String("hello world"); 来说是不相等的,他们是有new在堆中开辟了块内存空间,返回的地址当然是不相等的了。如果我们要比较这个字符串的内容怎么办呢?可以用下面的语句: if(c.equals(d)) System.out.println("c==d"); else System.out.println("c!=d"); //输出 c==d
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值