【Java原理探索】带你实战使用String的功能特性 | Java开发实战

简介: 【Java原理探索】带你实战使用String的功能特性 | Java开发实战

前提回顾

java.lang.String类用于描述字符串,Java程序中所有的字符串字面值都可以使用该类的对象加以描 述,如:"abc"。

  • 该类由final关键字修饰,表示该类不能被继承
  • 从jdk1.9开始该类的底层不使用char[]来存储数据,而是改成 byte[]加上编码标记,从而节约了一 些空间
  • 该类描述的字符串内容是个常量不可更改,因此可以被共享使用

如: String str1 = “abc”;  其中"abc"这个字符串是个常量不可改变。


image.png

public static void main(String[] args) {        
        String s1="abc";        
        String s2="abc";        
        System.out.println(s1==s2); //true 比较地址 abc存在常量池 
}
复制代码



常量池概念


String类描述的字符串内容是常量不可改变,因此Java虚拟机将首次出现的字符串放入常量池中,若后续代码中出现了相同字符串内容则直接使用池中已有的字符串对象而无需申请内存及创建对象,从而提高了性能(创建对象以分配内存消耗资源过大)且节省了空间。



常用的构造方法


方法声明 功能介绍
String() 使用无参方式构造对象得到空字符序列 ,“” 表示空字符串
String(byte[] bytes, int offset, int length) 使用bytes数组中下标从offset位置开始的length个字节来构造对象
String(byte[] bytes) 使用bytes数组中的所有内容构造对象
String(char[] value, int offset, int count) 使用value数组中下标从offset位置开始的count个字符来构 造对象
String(char[] value) 使用value数组中的所有内容构造对象
String(String original) 根据参数指定的字符串内容来构造对象,新创建对象为参数对象的副本




方法代码案例

public static void main(String[] args) {
 //下面代码会创建几个对象,分别存放在哪里
 String s1 = "abc";  // 1个对象 存在常量池
 String s2 = new String("abc");  //2个对象  "abc"在常量池  new的对象在堆区(堆区存abc的副本) s2指向堆区
 String s3="hello";
 String s4="hello";
 String s5=new String("hello");
 String s6=new String("hello");
 System.out.println(s3==s4);         //true
 System.out.println(s3.equals(s4));  //true
 System.out.println(s5==s6);         //false
 System.out.println(s5.equals(s6));  //true
 System.out.println(s3==s5);         //false
 System.out.println(s3.equals(s5));  //true
 //常量有优化机制,变量没有
 String a1="abcd";
 String a2="ab"+"cd";       // 常量优化机制   "abcd"
 System.out.println(a1==a2);//比较地址true
 String a3="ab";
 String a4=a3+"cd";          //没有优化机制,如同new一个String
 System.out.println(a3==a4);//比较地址 false
}
复制代码




常用的成员方法

方法声明 功能介绍
String toString() 返回字符串本身,重写Object toString()方法
byte[] getBytes() 将当前字符串内容转换为byte数组并返回,先将字符串拆分为字符,再将字符转byte
char[] toCharArray() 用于将当前字符串内容转换为char数组并返回
char charAt(int index) 方法charAt用于返回字符串指定位置的字符。
int length() 返回字符串字符序列的长度
boolean isEmpty() 判断字符串是否为空
int compareTo(String anotherString) 用于比较调用对象和参数对象的大小关系
int compareToIgnoreCase(String str) 不考虑大小写,也就是'a'和'A'是相等的关系
String concat(String str) 用于实现字符串的拼接
boolean contains(CharSequence s) 用于判断当前字符串是否包含参数指定的内容,String实现类CharSequence接口
String toLowerCase() 返回字符串的小写形式 //常量 转换后不会改变原值
String toUpperCase() 返回字符串的大写形式
String trim() 返回去掉前导和后继空白的字符串
boolean startsWith(String prefix) 判断字符串是否以参数字符串开头
boolean startsWith(String prefix, int toffset) boolean endsWith(String suffix)
boolean endsWith(String suffix) 判断字符串是否以参数字符串结尾
boolean equals(Object anObject) 用于比较字符串内容是否相等并返回
int hashCode() 获取调用对象的哈希码值
boolean equalsIgnoreCase(String anotherString) 用于比较字符串内容是否相等并返回,不考虑大小写, 如:'A'和'a'是相等
int indexOf(int ch) 用于返回当前字符串中参数ch指定的字符第一次出现的下标
int indexOf(int ch, int fromIndex) 用于从fromIndex位置开始查找ch指定的字符
int indexOf(String str) 在字符串中检索str返回其第一次出现的位置,若找不到 返回-1,正向查找
int indexOf(String str, int fromIndex) 表示从字符串的fromIndex位置开始检索str第一次出现 的位置
int lastIndexOf(int ch) 用于返回参数ch指定的字符最后一次出现的下标
int lastIndexOf(int ch, int fromIndex) 用于从fromIndex位置开始查找ch指定字符出现的下标
int lastIndexOf(String str) 返回str指定字符串最后一次出现的下标 ,反向查找
int lastIndexOf(String str, int fromIndex) 用于从fromIndex位置开始反向搜索的第一次出现的下 标。
String substring(int beginIndex, int endIndex) 返回字符串中从**下标beginIndex(包括)开始到 endIndex(不包括)**结束的子字符串
String substring(int beginIndex) 返回字符串中从下标beginIndex(包括)开始到字符串结尾 的子字符串





正则表达式的概念


正则表达式本质就是一个“规则字符串”,可以用于对字符串数据的格式进行验证,以及匹配、查 找、替换等操作。该字符串通常使用^运算符作为开头标志,使用$运算符作为结尾标志,当然也可以省略。



正则表达式的规则


正则表达式 说明
[abc] 可以出现a、b、c中任意一个字符
[^abc] 可以出现任何字符,除了a、b、c的任意字符
[a-z] 可以出现a、b、c、……、z中的任意一个字符
[a-zA-Z0-9] 可以出现az、AZ、0~9中任意一个字符
. 任意一个字符(通常不包含换行符)
\d 任意一个数字字符,相当于[0-9]
\D 任意一个非数字字符
\s 空白字符,相当于[\t\n\x0B\f\r]
\S 非空白字符
\w 任意一个单词字符,相当于[a-zA-Z_0-9]
\W 任意一个非单词字符
X? 表示X可以出现一次或一次也没有,也就是0 ~ 1次
X* 表示X可以出现零次或多次,也就是0 ~ n次
X+ 表示X可以出现一次或多次,也就是1 ~ n次
X{n} 表示X可以出现恰好 n 次
X{n,} 表示X可以出现至少 n 次,也就是>=n次
X{n,m} 表示X可以出现至少 n 次,但是不超过 m 次,也就是>=n并且<=m次

用 () 进行分组,无实际意义



正则表达式相关的方法


方法名称 方法说明
boolean matches(String regex) 判断当前正在调用的字符串是否匹配参数指定的正则表达式规则。
String[] split(String regex) 参数regex为正则表达式,以regex所表示的字符串为分隔 符,将字符串拆分成字符串数组
String replace(char oldChar, char newChar) 使用参数newChar替换此字符串中出现的所有参数 oldChar
String replaceFirst(String regex, String replacement) 替换此字符串匹配给定的正则表达式的第一个子字符串
String replaceAll(String regex, String replacement) 将字符串中匹配正则表达式regex的字符串替换成replacement




可变字符串类


基本概念


  • 由于String类描述的字符串内容是个常量不可改变,当需要在Java代码中描述大量类似的字符串 时,只能单独申请和存储,此时会造成内存空间的浪费。
  • 为了解决上述问题,可以使用java.lang.StringBuilder类和java.lang.StringBuffer类来描述字符序 列可以改变的字符串,如:"ab"。
  • StringBuffer类是从jdk1.0开始存在,属于线程安全的类,因此效率比较低。
  • StringBuilder类是从jdk1.5开始存在,属于非线程安全的类,效率比较高。



StringBuilder类常用的构造方法


方法名称 功能介绍
StringBuilder() 使用无参方式构造对象,容量为16
StringBuilder(int capacity) 根据参数指定的容量来构造对象,容量为参数指定大小
StringBuilder(String str) 根据参数指定的字符串来构造对象,容量为:16+字符串长度



StringBuilder类常用的成员方法
方法名称 功能介绍
int capacity() 用于返回调用对象的容量
int length() 用于返回字符串的长度,也就是字符的个数
StringBuilder insert(int offset, String str) 插入字符串并返回调用对象的引用,就是自己
StringBuilder append(String str) 追加字符串
StringBuilder deleteCharAt(int index) 将当前字符串中下标为index位置的单个字符 删除
StringBuilder delete(int start,int end) 删除字符串
StringBuilder replace(int start,int end, String str) 替换字符串
StringBuilder reverse() 字符串反转
StringBuilder setCharAt(int index,char char) 修改下标为index的字符为char


注意 作为参数传递的话,方法内部String不会改变其值,StringBuffer和StringBuilder会改变其值



返回值的设计


  • StringBuilder的很多方法的返回值均为StringBuilder类型。这些方法的返回语句均为:return this


  • 这些方法在对StringBuilder所封装的字符序列进行改变后又返回了该对象的引用。基于这样设计的目的在于可以连续调用



扩容算法源码分析


  • *当字符串的长度超过了字符串对象的初始容量时,该字符串对象会自动扩容,默认扩容算法是:原始容量 2+2


  • 底层采用byte数组来存放所有的字符内容




相关文章
|
13天前
|
存储 算法 Java
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
本文详解自旋锁的概念、优缺点、使用场景及Java实现。关注【mikechen的互联网架构】,10年+BAT架构经验倾囊相授。
大厂面试高频:什么是自旋锁?Java 实现自旋锁的原理?
|
13天前
|
Java
Java之CountDownLatch原理浅析
本文介绍了Java并发工具类`CountDownLatch`的使用方法、原理及其与`Thread.join()`的区别。`CountDownLatch`通过构造函数接收一个整数参数作为计数器,调用`countDown`方法减少计数,`await`方法会阻塞当前线程,直到计数为零。文章还详细解析了其内部机制,包括初始化、`countDown`和`await`方法的工作原理,并给出了一个游戏加载场景的示例代码。
Java之CountDownLatch原理浅析
|
15天前
|
Java 索引 容器
Java ArrayList扩容的原理
Java 的 `ArrayList` 是基于数组实现的动态集合。初始时,`ArrayList` 底层创建一个空数组 `elementData`,并设置 `size` 为 0。当首次添加元素时,会调用 `grow` 方法将数组扩容至默认容量 10。之后每次添加元素时,如果当前数组已满,则会再次调用 `grow` 方法进行扩容。扩容规则为:首次扩容至 10,后续扩容至原数组长度的 1.5 倍或根据实际需求扩容。例如,当需要一次性添加 100 个元素时,会直接扩容至 110 而不是 15。
Java ArrayList扩容的原理
|
4天前
|
安全 Java 开发者
Java 多线程并发控制:深入理解与实战应用
《Java多线程并发控制:深入理解与实战应用》一书详细解析了Java多线程编程的核心概念、并发控制技术及其实战技巧,适合Java开发者深入学习和实践参考。
|
13天前
|
分布式计算 Java API
Java 8引入了流处理和函数式编程两大新特性
Java 8引入了流处理和函数式编程两大新特性。流处理提供了一种声明式的数据处理方式,使代码更简洁易读;函数式编程通过Lambda表达式和函数式接口,简化了代码书写,提高了灵活性。此外,Java 8还引入了Optional类、新的日期时间API等,进一步增强了编程能力。这些新特性使开发者能够编写更高效、更清晰的代码。
27 4
|
21天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
40 2
|
21天前
|
算法 Java 数据库连接
Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性
本文详细介绍了Java连接池技术,从基础概念出发,解析了连接池的工作原理及其重要性。连接池通过复用数据库连接,显著提升了应用的性能和稳定性。文章还展示了使用HikariCP连接池的示例代码,帮助读者更好地理解和应用这一技术。
34 1
|
存储 Java
【Java 虚拟机原理】线程栈 | 栈帧 | 局部变量表 | 反汇编字节码文件 | Java 虚拟机指令手册 | 程序计数器
【Java 虚拟机原理】线程栈 | 栈帧 | 局部变量表 | 反汇编字节码文件 | Java 虚拟机指令手册 | 程序计数器
126 0
【Java 虚拟机原理】线程栈 | 栈帧 | 局部变量表 | 反汇编字节码文件 | Java 虚拟机指令手册 | 程序计数器
|
5天前
|
Java 开发者
Java多线程编程中的常见误区与最佳实践####
本文深入剖析了Java多线程编程中开发者常遇到的几个典型误区,如对`start()`与`run()`方法的混淆使用、忽视线程安全问题、错误处理未同步的共享变量等,并针对这些问题提出了具体的解决方案和最佳实践。通过实例代码对比,直观展示了正确与错误的实现方式,旨在帮助读者构建更加健壮、高效的多线程应用程序。 ####
|
4天前
|
Java 开发者
Java多线程编程的艺术与实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的技术文档,本文以实战为导向,通过生动的实例和详尽的代码解析,引领读者领略多线程编程的魅力,掌握其在提升应用性能、优化资源利用方面的关键作用。无论你是Java初学者还是有一定经验的开发者,本文都将为你打开多线程编程的新视角。 ####

热门文章

最新文章

下一篇
无影云桌面