深入了解Java中的String类

简介: 在C语言中已经涉及到字符串,但是在c语言中表示字符串只能使用字符数组或字符指针,可以使用标准库提供的字符串系列函数完成大部分操作,但这种将数据和操作数据分离开的方式不符合面向对象的思想,而字符串应用又非常广泛,因此Java专门提供了String类。

String类的重要属性


在C语言中已经涉及到字符串,但是在c语言中表示字符串只能使用字符数组或字符指针,可以使用标准库提供的字符串系列函数完成大部分操作,但这种将数据和操作数据分离开的方式不符合面向对象的思想,而字符串应用又非常广泛,因此Java专门提供了String类。


在开发和校招中,字符串也是常客,面试中也被频繁问到,比如String,StringBuffer,StringBuilder之间的区别等。


常用方法

字符串构造

String类常用的构造方式有以下三种:

public static void main(String[] args) {
        //使用常量串构造
        String s1 = "hello word";
        System.out.println(s1);
        //直接newString对象
        String s2 = new String("hello china");
        System.out.println(s2);
        //使用字符数组进行构造
        char[] array = {'h','e','l','l','o'};
        String s3 = new String(array);
        System.out.println(s3);
    }


注意:


1. String是引用类型,内部并不存储字符串本身,在String类的实现源码中,String类的实例变量如下:

微信图片_20221028193302.jpg



//s1和s2引用的不是同一对象,s1和s3引用的是同一对象
        String s1 = new String("hello");
        String s2 = new String("world");
        String s3 = s1;
        System.out.println(s1.length());    //获取字符串长度
        System.out.println(s1.isEmpty());   //如果字符串长度为0返回true,否则返回false

微信图片_20221028193331.jpg

2. 在Java中“ ”引起来的也是String类型对象

//打印“hello”字符串的长度
System.out.println("hello".length());

String对象的比较

1. == 比较是否引用同一个对象


注意:对于基本类型,==比较变量中的值,对于引用类型,==比较引用的地址

int a = 10;
        int b = 20;
        int c = 10;
        //基本类型比较变量的值
        System.out.println(a==b);     
        System.out.println(a==c);
        String s1 = new String("hello");
        String s2 = new String("world");
        String s3 = new String("hello");
        String s4 = s1;
        //对于引用变量,比较的是引用的地址
        System.out.println(s1==s2);   //false
        System.out.println(s1==s3);   //false
        System.out.println(s1==s4);   //true

   

2. boolean equals(Object anObject)方法:按照字典序比较---字符大小的顺序


String类重写了父类Object中equals方法,Object中equals默认按照==比较,String类重写equals后,按照如下规则进行比较,比如:s1.equals(s2)


3. int compareTo(String s)方法:按照字典序比较


与equals不同的是,equals返回的是boolean类型,而compareTo返回的是int类型,具体比较方式:


1. 先按照字典次序大小比较,如果出现不等的字符,直接返回这两个字符大小的差值


2. 如果前k个字符相等(k为两个字符长度最小值),返回两个字符串长度差值。

String s1 = new String("abc");
        String s2 = new String("abc");
        String s3 = new String("abcdef");
        String s4 = new String("ac");
        System.out.println(s1.compareTo(s2));   //输出结果0
        System.out.println(s1.compareTo(s3));   //输出结果-3
        System.out.println(s1.compareTo(s4));   //输出结果-1


4.int compareToIgnorCase(String str)方法:与compareTo方式相同,但是忽略大小写比较

String s1 = new String("abc");
        String s2 = new String("ABC");
        String s3 = new String("aBcDe");
        System.out.println(s1.compareToIgnoreCase(s2));   //输出结果为0
        System.out.println(s2.compareToIgnoreCase(s3));   //输出结果为-2

字符串查找

字符串查找也是字符串中重要的操作,String类提供常用查找的方法

方法 功能
char charAt(int index) 返回index位置字符
int indexOf(int ch) 返回ch第一次出现的位置,没有返回-1
int indexOf(int ch,int fromIndex) 从fromIndex位置找ch第一次出现的位置,无返回-1
int indexOf(String str) 返回str第一次出现的位置,无返回-1
int indexOf(String str,int fromIndex) 从fromIndex位置开始找str第一次出现的位置,无返回-1
int lastIndexOf(int ch) 从后往前找ch第一次出现的位置,无返回-1
int lastIndexOf(int ch,int fromIndex) 从fromIndex开始从后往前找ch第一次出现的位置,无返回-1

int lastIndexOf(String str)

从后往前找str第一次出现的位置,无返回-1
int lastIndexOf(String str,int fromindex) 从fromIndex开始从后往前找,返回str第一次出现的位置,无返回-1


public static void main(String[] args) {
       String s = "aabbccddccbbaa";
        System.out.println(s.charAt(2));          //b
        System.out.println(s.indexOf('c'));        //4
        System.out.println(s.indexOf("dd"));       //6
        System.out.println(s.indexOf('c',3));    //4
        System.out.println(s.indexOf("bb",5));    //10
        System.out.println(s.lastIndexOf('c'));        //9
        System.out.println(s.lastIndexOf("bb"));       //10
        System.out.println(s.lastIndexOf('b',5));   //3
        System.out.println(s.lastIndexOf("bb",6));   //2
    }


注意:上述方法都是实例方法


转化

1.数值和字符串转化

//数字转字符串
        String s1 = String.valueOf(20);
        String s2 = String.valueOf(3.14);
        String s3 = String.valueOf(true);
        System.out.println(s1);
        System.out.println(s2);
        System.out.println(s3);
        //字符串转数字
        int a = Integer.parseInt("20");
        double b = Double.parseDouble("3.14");   //Integer Double 都是包装类
        System.out.println(a);
        System.out.println(b);
2. 大小写转换
/大小写转换
        String s1 = "HELLO";
        String s2 = "hello";
        System.out.println(s1.toLowerCase()); //转小写
        System.out.println(s2.toUpperCase()); //转大写
//输出结果:
hello
HELLO

   


3. 字符串与数组相互转换

//字符串转数组
String s = "hello";
char[] ch = s.toCharArray();
for(int i=0;i<ch.length;i++){
    System.out.println(ch[i]);
}
System.out.println();
//数组转字符串
String s2 = new String(ch);
System.out.println(s2);


4. 格式化

String s = String.format("%d-%d-%d",2021,10,29);
System.out.println(s);    //2021-10-29


字符串的不可变性

String是一种不可变的对象,字符串中的内容是不可改变的,字符换不可被修改,是因为:


1. String类在设计时就是不可改变的,String类实现描述中已经说明了

image.png


String类中的字符实际保存在内部维护的value字符数组中,该图还可以看出:


1.String类被final修饰,表示该类不能被继承


2. value被final修饰,表明value自身的值不能改变,即不能引用其他字符数组,但是引用空间中的内容可以修改


2. 所有涉及到可能修改字符串内容的操作都是在创建一个新对象,改变的是新对象


final修饰引用类型表明该引用变量不能引用其他对象,但是其引用对象中的内容可以修改


为什么String要设计成不可变的?

1. 方便实现字符串对象池,如果String可变,那么对象池就需要考虑何时深拷贝字符串的问题。


2. 不可变对象是线程安全的


3. 不可变对象更方便缓存hash code,作为key时可以更高效的保存到HashMap中。


字符串修改

注意:尽量避免直接对String类型对象进行修改,因为String类是不能修改的,所有的修改都会创建新对象,效率非常低下。

public static void main(String[] args) {
        String s = "hello";
        s += "world";
        System.out.println(s);
    }


这种方式效率非常低,不推荐使用,中间创建了好多临时对象


StringBuilder和StringBuffer

StringBuilder的介绍

由于String的不可更改特性,为了方便字符串的修改,Java中提供了StringBuilder和StringBuffer类,这两个类大部分功能是相同的,这里介绍StringBuilder常用的一些方法。

方法 说明


StringBuilder() 构造一个空的字符串构建器


int length() 返回构建器中代码单元的数量


StringBuilder append(String str) 追加一个字符串


StringBuilder append(char c) 追加一个代码单元


void setCharAt(int i,char c) 将第i个代码单元设置为c


StringBuilder insert(int offset,String str) 在offset位置插入一个字符串


StringBuilder insert(int offset,char c)

在offset位置插入一个代码单元


StringBuilder delete(int starIndex,int endIndex) 删除偏移量从starIndex到endIndex-1的代码单元


StringBuilder reverse() 反转字符串


String toString() 将所有字符按照String方式返回


String substring(int start) 从start开始一直到末尾的字符以String的方式返回


public static void main(String[] args) {
        StringBuilder s = new StringBuilder("hello");
        s.append(' ');
        s.append("world");
        System.out.println(s);
        System.out.println(s.length());
        s.insert(6,"and");
        System.out.println(s);
        s.reverse();
        System.out.println(s);
        System.out.println(s.substring(5));
        System.out.println(s.toString());
    }
    执行结果:
hello world
11
hello andworld
dlrowdna olleh
dna olleh
dlrowdna olleh

注意:String和StringBuilder类不能直接转换,要转换,采用以下原则:


· String变为StringBuilder,利用StringBuilder的构造方法或append()方法


· StringBuilder变为String,调用toString()方法


区别

· String的内容不可修改,StringBuffer与StringBuilder的内容可以修改


· StringBuffer与StringBuilder大部分功能是相似的


· StringBuffer采用同步处理,属于线程安全操作;StringBuilder未采用同步处理,属于线程不安全操作


相关文章
|
6天前
|
Java
课时14:Java数据类型划分(初见String类)
课时14介绍Java数据类型,重点初见String类。通过三个范例讲解:观察String型变量、&quot;+&quot;操作符的使用问题及转义字符的应用。String不是基本数据类型而是引用类型,但使用方式类似基本类型。课程涵盖字符串连接、数学运算与字符串混合使用时的注意事项以及常用转义字符的用法。
|
6天前
|
存储 Java 编译器
课时11:综合实战:简单Java类
本次分享的主题是综合实战:简单 Java 类。主要分为两个部分: 1.简单 Java 类的含义 2.简单 Java 类的开发
|
7天前
|
传感器 监控 Java
Java代码结构解析:类、方法、主函数(1分钟解剖室)
### Java代码结构简介 掌握Java代码结构如同拥有程序世界的建筑蓝图,类、方法和主函数构成“黄金三角”。类是独立的容器,承载成员变量和方法;方法实现特定功能,参数控制输入环境;主函数是程序入口。常见错误包括类名与文件名不匹配、忘记static修饰符和花括号未闭合。通过实战案例学习电商系统、游戏角色控制和物联网设备监控,理解类的作用、方法类型和主函数任务,避免典型错误,逐步提升编程能力。 **脑图速记法**:类如太空站,方法即舱段;main是发射台,static不能换;文件名对仗,括号要成双;参数是坐标,void不返航。
28 5
|
6天前
|
存储 JavaScript Java
课时44:String类对象两种实例化方式比较
本次课程的主要讨论了两种处理模式在Java程序中的应用,直接赋值和构造方法实例化。此外,还讨论了字符串池的概念,指出在Java程序的底层,DOM提供了专门的字符串池,用于存储和查找字符串。 1.直接赋值的对象化模式 2.字符串池的概念 3.构造方法实例化
|
6天前
|
Oracle Java 关系型数据库
课时37:综合实战:数据表与简单Java类映射转换
今天我分享的是数据表与简单 Java 类映射转换,主要分为以下四部分。 1. 映射关系基础 2. 映射步骤方法 3. 项目对象配置 4. 数据获取与调试
|
1月前
|
安全 Java 编译器
JAVA泛型类的使用(二)
接上一篇继续介绍Java泛型的高级特性。3. **编译时类型检查**:尽管运行时发生类型擦除,编译器会在编译阶段进行严格类型检查,并允许通过`extends`关键字对类型参数进行约束,确保类型安全。4. **桥方法**:为保证多态性,编译器会生成桥方法以处理类型擦除带来的问题。5. **运行时获取泛型信息**:虽然泛型信息在运行时被擦除,但可通过反射机制部分恢复这些信息,例如使用`ParameterizedType`来获取泛型参数的实际类型。
|
1月前
|
安全 Java 编译器
JAVA泛型类的使用(一)
Java 泛型类是 JDK 5.0 引入的重要特性,提供编译时类型安全检测,增强代码可读性和可维护性。通过定义泛型类如 `Box&lt;T&gt;`,允许使用类型参数。其核心原理是类型擦除,即编译时将泛型类型替换为边界类型(通常是 Object),确保与旧版本兼容并优化性能。例如,`Box&lt;T&gt;` 编译后变为 `Box&lt;Object&gt;`,从而实现无缝交互和减少内存开销。
|
3月前
|
存储 JavaScript Java
Java 中的 String Pool 简介
本文介绍了 Java 中 String 对象及其存储机制 String Pool 的基本概念,包括字符串引用、构造方法中的内存分配、字符串文字与对象的区别、手工引用、垃圾清理、性能优化,以及 Java 9 中的压缩字符串特性。文章详细解析了 String 对象的初始化、内存使用及优化方法,帮助开发者更好地理解和使用 Java 中的字符串。
Java 中的 String Pool 简介
|
3月前
|
JSON Java Apache
Java基础-常用API-Object类
继承是面向对象编程的重要特性,允许从已有类派生新类。Java采用单继承机制,默认所有类继承自Object类。Object类提供了多个常用方法,如`clone()`用于复制对象,`equals()`判断对象是否相等,`hashCode()`计算哈希码,`toString()`返回对象的字符串表示,`wait()`、`notify()`和`notifyAll()`用于线程同步,`finalize()`在对象被垃圾回收时调用。掌握这些方法有助于更好地理解和使用Java中的对象行为。
|
3月前
|
缓存 安全 Java
java 为什么 String 在 java 中是不可变的?
本文探讨了Java中String为何设计为不可变类型,从字符串池的高效利用、哈希码缓存、支持其他对象的安全使用、增强安全性以及线程安全等方面阐述了不可变性的优势。文中还通过具体代码示例解释了这些优点的实际应用。
java 为什么 String 在 java 中是不可变的?

热门文章

最新文章