天天看点

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

目录

1. 字符串

1. 字符串创建 

2. 实例化的区别

I. 直接赋值

II. 构造方法

3. 字符串比较

4. 字符串的修改

5. String类总结

【String类方法 】String 类是Java类中最常用用的类,记录一下 String类的对象实例以及String常用的一些方法

1. 字符串

【字符串的特点】

  1. 字符串内容永不可变
  2. 字符串可以共享使用【在常量池中】
  3. 字符串,字符数组,底层原理是byte[ ]字节数组

1. 字符串创建 

直接赋值 

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

这种赋值方式最为常用。

但是String本身毕竟是一个类,既然是类,那么类中一定存在构造方法。String类也不例外,String类的其中一种构造方法如下:

public String(String str);
           

构造方法创建

1. public String( ) :默认构造方法创建字符串

String msg = new String();
           

2. 根据字符数组创建字符串

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

3. 根据字节数组创建字符串(字符串底层其实还是字节存储)

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

2. 实例化的区别

I. 直接赋值

  • 对于基本类型来说:== 是数值的比较
  • 对于引用类型来说:== 是地址值的比较
String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结
String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

内存图详解:

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

为什么现在并没有开辟新的堆内存空间呢?

直接赋值会把创建的字符串放到字符串常量池中,只有通过构造方法new出来的,每次才会开辟新空间。

常量优化机制:

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

在JVM底层实际上会自动维护一个对象池(字符串对象池),如果现在采用了直接赋值的模式进行String类的对象实例化操作,那么该实例化对象(字符串内容)将自动保存到这个对象池之中。

  • 如果下次继续使用直接赋值的模式声明String类对象,此时对象池之中如若有指定内容,将直接进行引用;
  • 如若没有,则开辟新的字符串对象而后将其保存在对象池之中,以供下次使用(目的就是减少开销)
  • 所谓的对象池就是一个对象数组

II. 构造方法

类对象使用构造方法实例化是标准做法

String str = new String("hello");
           
String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

通过分析可知,如果使用String构造方法就会开辟两块堆内存空间,并且其中一块堆内存将成为垃圾空间。除了这

一缺点之外,也会对字符串共享产生问题。

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

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

因此,一般会采取第一种方式即直接赋值即可......

3. 字符串比较

  • == 
  • equals()
String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结
String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结
String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结
String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

== 本身是进行数值比较的,如果现在用于对象比较,那么所比较的就应该是两个对象所保存的地址值比较,而并没有比较对象的内容

那么要想比较内容比较,则必须采用String类提供的equals方法。

使用equals方法比较字符串内容:

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

Object类equals方法的覆写

用equals( )来比较对象内容是否相同:

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

两个对象stu1 和 stu2 的内容明明相等,应该是true呀?怎么会是false?

因为此时直接调用 

equals()

方法默认进行比较的是两个对象的地址。new一下就会在堆上创建新空间,地址自然不会相同,所以为false

我们在判断的是字符串的内容是否相等时,直接用 str1.equals(str2);

但是在判断两个对象是否相等时,比如要判断一个Person类的两个对象的姓名是否相同时,此时要重新覆写equals( )

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

面试题:请解释String类 == 与equals 的区别

  1.  " == ":引用类型进行的数值比较,比较的是两个字符串对象的内存地址数值
  2. "equals( )":可以进行字符串内容的比较

在Java中,本身也没有直接提供字符串常量的概念,所有使用 " " 定义的内容本质上来讲都是String的匿名对象

观察字符串常量:

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

那么在之前出现的String str = "Hello",本质上就是将一个匿名的String类对象设置有名字,而且匿名对象一定保存在堆内存中。

PS :

String str = null ; // 假设由用户输入
System.out.println(str.equals("Hello"));
           

在进行接收用户输入数据的时候一定要考虑到用户没有输入的问题,用户没有输入的时候,一定会出现 NullPointerException 问题

所以应当改为:

常量的字符串内容放在前面,来避免空指针异常:

System.out.println("Hello".equals(str));
           

4. 字符串的修改

String类是不可变类,String类的对象一旦被创建,其值将不能被改动

但实际情况是

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

此处str却是被修改过了,这是为什么呢?

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

可以发现字符串上没有发生任何变化,但是字符串对象的引用一直在改变,而且会形成大量的垃圾空间

String字符串修改实现原理:

当用String类型来对字符串进行修改时,首先是创建一个StringBuilder,其次调用 StringBuilder 的 append( ) 方法,最后掉调用StringBulider 的 toString( )将结果返回

示例如下:

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

等价于

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

str字符串的内容不可改变,改变的是引用的地址值

5. String类总结

面试题:

Q: String类能不能被继承,有没有子类?

String类被final修饰,其不能被继承,所以没有子类

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

Q1: s1 与 s2 是否相等?

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结
  • true
  • true

Q2:  s1 与 s2 是否相等?内存中共有几个abc?

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结
  • false
  • true
  • 内存中有两个abc,一个在堆区,一个在常量池中
String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结

Q3:  s1 与 s2 是否相等?

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结
  • true
  • true

这便是Java的常量优化机制。Java程序时半编译半解释性语言,先将 .java 文件编译成 .class 字节码文件,最后再执行。区别于编译型语言,直接将源代码翻译成二进制的机器码。在编译成 .class 文件后,s1 与 s2 的内容是相同的,所以只是引用改变了而已。

Q4:  s1 与 s2 是否相等?

String类,字符串的创建和比较1. 字符串1. 字符串创建 2. 实例化的区别3. 字符串比较4. 字符串的修改5. String类总结
  • false
  • true

s1,s2是变量,而 s3 则是变量.