创作不易,来个三连
目录
String类
1.声明
2、创建字符串
①创建字符串对象
②字符串的存储形式
③字符串对象在内存中的布局
3、连接字符串
①连接字符串
②连接其他类型
③ 面试题
4、获取字符串信息
①获取字符串长度
②字符串子串查找
③获取指定下标的字符
5、字符串操作方法
①获取子字符串
②去除空格
③字符串的替代
⑴ replace方法
⑵replaceAll
⑶replaceFirst
④字符串数值转化
⑤字符串子串拆分
⑥字符串大小写转换
⑦判断字符串的开始与结尾
⑧字符串比较
6、留给读者自行研究的题目
️️️
在C语言中,字符串不属于一个基本数据类型,C语言中的字符串只能使用字符数组或者字符类型的指针形式来存储,显然这只是一个组合型的数据组,由一个个字符组成。其中可以引用其标准库完成大多数字符串操作,但是这种与数据对象与操作分离的方式不符合java面向对象的特点。因此java专门设置了String类,java中字符串以对象的形式出现。
在java中,字符串必须被包含在一对英文半角双引号:""内。例如
"123456789" 、 "ABCEDF" 、 "hello!你好呀!" 、 ""
以上都是字符串常量,其中""为空字符串。
声明:使用以下语法
String str;
其中str为变量名,其命名只要遵从基本命名规则即可。String 为字符串类型,声明该变量为字符串类型。如果str为局部变量,那么他必须在声明的时候初始化。
java将字符串作为对象处理,因此可以像创建其他类对象一样来创建String对象:
String str = new String ( char a[ ] ) // char[] a 在语法上与 char a[] 等价
代码案例如下:
public class Main {
public static void main(String[] args) {
char a[] = {'a','b','c'};
char[] b = {'a','b','c'};
String strA = new String(a);
String strB = new String(b);
String strC = new String("good");
String strD = "hello";
String strE = new String(new char[]{'你', '好'});
System.out.println("strA的值为"+strA);
System.out.println("strB的值为"+strB);
System.out.println("strC的值为"+strC);
System.out.println("strD的值为"+strD);
System.out.println("strE的值为"+strE);
}
}
strA和strC的创建方式是等价的
其中:
String strE = new String(new char[]{'你', '好'});
如果将其改为:去掉new
String strE = new String( char[]{'你', '好'});
就会报错,因为他是一个没有声明的变量,这里的new就相当于给他申明为一个字符数组,否则无法识别。
同时,java中相连的字符串不能分开在两行中写,这种语法是错误的,如下:
String str = new String ("hello
world");
char a[]为字符串数组,当其传入的时候会自动调用构造方法,给对象的value传参,value的信息如下:
调用构造方法如下:
例如我们传入数组a
char a[] = {'a','b','c'};
所以本质上,字符串是以字符数组的形式存储的。
String strA = "abc";
String strB = "abc";
String strC = new String ("abc");
System.out.print ( strA == strB);
System.out.print ( strA == strC);
main函数里面新创建两个 strA 和 strB 对象,然后用 == 对其进行比较,因为他们都是引用的同一个字符串 "abc",所以结果为 true:
运算符" == " 比较的是两个字符串对象的引用地址,而不是字符串对象里面的内容,想要比较内容可以使用equals方法,这篇文章中有讲到,后面不在列出equals方法的使用。
http://t.csdn.cn/0OgX6http://t.csdn.cn/0OgX6
而strA和strC,strA是指向"abc",而strC在堆区重新new了一个"abc"对象,他和之前已经存在的abc字符串是两个不同的对象。
在strB去创建的时候,"abc"这个字符串被放入了堆区的内存池中,strA指向这个在strB创建之前的字符串,当strB去创建一个字符串对象的时候,程序会首先去内存池查看是否已经存在相同内容的字符串,如果存在,就将其指向已经存在的字符串,否则就会生成一个新的字符串对象》》:
对于一个字符串对象,我们可以使用 " + " 将其与 其他字符串对象 进行连接
代码如下:
public class Main {
public static void main(String[] args) {
String tem = "hello world";
String str1 = " ! hello java";
String exm = tem + str1;
System.out.println(exm);
tem += str1;
System.out.println(tem);
}
}
其中直接将 一个字符串对象 tem 和另外一个字符串对象str1 相加,然后赋值给 一个exm字符串对象,然后打印。 对tem进行 += str1 操作,然后打印:
运行结果如下:
我们在创建字符串这个内容里面提到过,字符串不能在两行写,但是有的时候字符串内容过长,为了便于观看又不得不分两行写。所以这个时候就可以使用 "+ "将两个其分为两个字符串然后相加:
String str = new String ("hello" +
" world " );
java中通过 " + "也可以让String字符串对象 和其他数据类型的数据进行连接,通过 + 会直接将其合并为字符串:
public class Main {
public static void main(String[] args) {
String tem = "hello world" + 0;
System.out.println(tem);
tem += true;
System.out.println(tem);
tem += 1.5F;
tem += 2.66;
System.out.println(tem);
tem += 'a';
System.out.println(tem);
tem = "xxxxxxx" + tem;
System.out.println(tem);
}
}
可以看到,一个字符串类型可以使用 " + " 或者" += " 将多个基本数据类型相连,组合成为一个新的字符串,无论是在其左端还是右端,都可以,其中浮点数后面的F(f),长整型后面的L(l)在和字符串进行加法的时候不会被加入到字符串当中。
对于相加的其他数据类型,也存在着括号优先级的问题。例如
public class Main {
public static void main(String[] args) {
System.out.println("hello world " + 123 + (1 + 2) +"i like java");
}
}
他会优先计算 圆括号中的 1 + 2 的内容,然后和字符串进行加法,结果如下:
但是圆括号内的内容计必须是可两个可以进行 + 运算的数据类型,例如:
public class Main {
public static void main(String[] args) {
System.out.println("hello world" + 1.265 + (0.123 + false) +" i love java! " );
}
}
字符串和别的基本数据类型的加法,极大地方便了我们去表示和描述一串有几个不同数据类型组合而成的数据。
(多选题)关于下面的一段代码,哪些说法是正确的?
public static void main(String[] args) {
String a = new String("myString");
String b = "myString";
String c = "my" + "String";
String d = c;
System.out.print(a == b);
System.out.print(a == c);
System.out.print(b == c);
System.out.print(b == d);
}
A .System.out.print(a == b)打印出来的是false
B .System.out.print(a == c)打印出来的是true
C .System.out.print(b == c)打印出来的是false
D .System.out.print(b == d)打印出来的是true
解析:
a为String构造方法,在堆区创建的对象
b为常量字符串,被放入了对区中的常量池
c为字符串的拼接,如果"+"两边为字符串变量或者一个为字符串常量,一个为变量,则会在底层将变量转化为StringBuilder然后通过append的方式追加,再将其通过toString方法转化为String字符串,最后通过构造方法new出这个String字符串对象。如果都为常量,由于java优化机制,拼接的结果会直接转向内存池,在内存池中查找是否具有相同内容的字符串,如果有则直接指向这个已经存在的具有相同内容的常量字符串,如c选项,c和b都是引用的同一个字符串常量。
d直接引用c对象的地址。此时b,c和d同时指向同一个字符串
因此答案为AD
对于一个字符串对象,我们要获取其信息的最直接方法就是打印方法:
System.out.println (str); // str为字符串对象或者一个字符串常量
通过打印函数可以很直观的看到字符串里面的内容,但是如果想要获取某一个下标的字符串,或者是其他的一些信息,该怎么处理呢?下面介绍几种字符串相关的操作(所有的字符串的出现都以str表示):
str.length();
用 str.length()的方法获取并返回一个int类型的数据以表示字符串的长度,案例如下:
public class Main {
public static void main(String[] args) {
String str = "hello world!";
int lenOfStr = str.length();
System.out.println("the length of str is "+ lenOfStr);
}
}
其长度就是字符串中的单个字符的个数。
java的String类提供了两种查找子字符串的方法:
str.indexOf(substr) ;
str.lastIndexOf(substr);
其中substr为str的子字符串,通过 str . 的形式来访问,例如:
⑴对于indexOf:
public class Main {
public static void main(String[] args) {
String str = "hello world";
int pos1 = str.indexOf("wo");
System.out.println("the value of pos1 is " + pos1);
int pos2 = str.indexOf("llo");
System.out.println("the value of pos2 is " + pos2);
int pos3 = str.indexOf("java");
System.out.println("the value of pos3 is " + pos3);
}
}
indexOf()方法返回找到的子字符串的首字符的下标。如果没有找的自返回: -1
⑵对于lastIndexOf:
与indexOf不同的是,lastIndexOf是从字符串的最后面(下标为str.length() -1 )开始查找,而indexOf是从字符串最前面( 下标为 0 )开始查找 。
public class Main {
public static void main(String[] args) {
String str = "hello world! hello java!";
int pos1 = str.lastIndexOf("hello");
System.out.println("the value of pos1 is " + pos1);
int pos2 = str.lastIndexOf("or");
System.out.println("the value of pos2 is " + pos2);
int pos3 = str.lastIndexOf("python");
System.out.println("the value of pos3 is " + pos3);
}
}
其结果如下:
如果没有找到,则返回: -1
那如果indexOf或者lastIndexOf里面传入空的字符串呢?
不妨看看以下代码案例:
public class Main {
public static void main(String[] args) {
String str = "hello world! hello java!";
System.out.println("the length of str is " + str.length());
int pos1 = str.indexOf("");
System.out.println("the value of pos1 is " + pos1);
int pos2 = str.lastIndexOf("");
System.out.println("the value of pos1 is " + pos2);
}
}
先计算出字符串str的长度,为24,然后对str对象使用indexOf查找,并传入空字符串,返回值用pos1接收,并输出其值。接着对str对象使用lastIndexOf查找,并传入空字符串,用pos2接收返回值,然后输出其值。
可以发现pos1的值为0,pos2的值刚好为字符串的长度。
使用 charAt(int pos);方法可以获取字符串指定下标的字符(返回值为char类型的字符)
其语法格式如下:
charAt( int pos); // pos 为传入下标值;
案例如下:
public class Main {
public static void main(String[] args) {
String str = "hello world! hello java!";
int pos = 1;
char retPos1 = str.charAt(pos);
System.out.println("the value of retPos1 is " + retPos1);
}
}
如果将其中的 1 改为 小于 0 或者是大于 str.length() -1 的值就会抛出:
StringIndexOutOfBoundsException异常
(除了字符串的查找操作,String类还提供了其他许多操作的字符串的方法)
查找子字符串的下标的方法我们已经介绍过,那么如何获取并返回接收某一个指定下标的字符串呢?
可以使用如下方法:
str.substring ( int beginIndex); // beginIndex为开始截取的位置
我们还是以"hello world! hello java!"这个字符串为例,案例如下:
public class Main {
public static void main(String[] args) {
String str = "hello world! hello java!";
int pos = 13;
String subStr = str.substring(pos);
System.out.println("the value of subStr is " + subStr);
}
}
pos = 13;刚好对应str中的第二个hello 的h的下标。
substring 是一个重载的方法,他有第二个参数,以表示要截取的终点:
substring ( int start , int end );
还是以"hello world! hello java!"这个字符串为例,如下:
public class Main {
public static void main(String[] args) {
String str = "hello world! hello java!";
int start = 6;
int end = 11;
String subStr = str.substring(start,end);
System.out.println("the value of subStr is " + subStr);
}
}
可以看到substring(int start , int end)这个重载的方法是左闭右开的,也就是他的截取范围为: [ start , end )
如果截取的传入数值start和end超过了字符串的表示范围,同样会发生:
StringIndexOutOfBoundsException异常
使用trim()方法返回一个去除前部空格和尾部空格的字符串的副本:
定义如下:
str. trim();
str为任意字符串对象。案例如下:
还是以"hello world! hello java!"为例,但是我们在其前面和尾部加上许多空格,然后对其使用trim方法并用tem引用接收,打印tem的值,案例如下:
public class Main {
public static void main(String[] args) {
String str = " hello world! hello java! ";
String tem = str.trim();
System.out.println(tem);
}
}
和python相似,java也有replace方法来替换掉字符串中的子字符串,其语法如下:
str.replace( char oldChar, char newChar);
同时还有replaceAll和replaceFirst方法
其中oldChar为你想要替换的字符,newChar是用于替换oldChar的字符。
(注意:这里的字符是区分大小写的)
对于String类的replace方法,同样发生了重载,其重载方法如下:
str.replace( String oldString , String newString);
其中oldString 为你想要替换的字符串,newString是用于替换oldString 的字符串。
代码案例如下:
public class Main {
public static void main(String[] args) {
String str = "hello world! hello java!";
String tem1 = str.replace('h','H');
String tem2 = str.replace("hello","HELLO");
System.out.println(tem1);
System.out.println(tem2);
}
}
String replaceAll ( String regex, String replacement );
对于replaceAll 如果传入的参数和replace是一样的话,则两者在功能上无区别。但是replaceAll的参数是regex,即基于正则表达式的替换,例如:
str.replaceAll( "\\d" , "*" );
把一个字符串str所有的数字字符都换成星号;
如果参数同replace一样的话,那么其功能也与replace相同,同时replaceFirst也是基于正则表达式的替换,只不过replaceFirst只替换第一次出现的目标值。
一个字符串如何转化为其他类型的数据呢?使用.valueOF( )方法,可以看到
其语法如下:
String str = String.valueOf ( int num等等数据 );
代码案例如下:
class Dog {
public String name;
public int age;
public Dog(int age,String name){
this.age = age;
this.name = name;
}
@Override
public String toString() {
return "Dog{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
public class Main {
public static void main(String[] args) {
int nums = 123;
String numsStr = String.valueOf(nums);
System.out.println(numsStr);
float fla = 3.14f;
String floatStr = String.valueOf(fla);
System.out.println(floatStr);
double dou = 3.122;
String douStr = String.valueOf(dou);
System.out.println(douStr);
boolean boo = false;
String booStr = String.valueOf(boo);
System.out.println(booStr);
char ch = 'c';
String chStr = String.valueOf(ch);
System.out.println(chStr);
char[] charArray = {'a','b','c'};
String charArrayStr = String.valueOf(charArray);
System.out.println(charArrayStr);
char[] charArray2 = {'j','a','v','a'};
String charArray2Str = String.valueOf(charArray2,1,3);
System.out.println(charArray2Str);
Dog dog = new Dog(5,"旺旺");
String objStr = String.valueOf(dog);
System.out.println(objStr);
}
}
其中方法:valueOf( char[ ] arr , int offset , int count );意为,截取从下标offset开始,往后的count个字符的片段,然后转化成字符串,如上面的例子,java:
valueOf( 'j','a','v','a' , 1 , 3 );
打印其返回值的结果为 : "ava";
方法 :valueOf( Object obj ); Object类为所有类的父类,可以参考我的一篇文章
java类和对象:继承、多态、接口、抽象类http://t.csdn.cn/vc917这个地方传入其他类的对象的实例发生向上转型。
由于一个类它具有很多不同的参数类型,例如int,double,String,等等,所以不能单纯的直接使用valueOf方法,首先还需要在传入的这个类中重写toString()方法:
在python中存在着一种特殊的拆分字符串的方法为split,在使用的时候尤其方便。在Java中同样提供了类似的方法:split()方法,如下
代码案例如下:
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
String str = "hello world! hello java!";
String[] strArrays = str.split(" ");
for (int i = 0; i < strArrays.length; i++) {
System.out.println(strArrays[i]);
}
}
}
该方法将字符串以给定的字符串为分割标志,对原字符串进行分割,然后返回一个字符串的子串数组,里面存放的是被分割的字符串的子串。
其后面还有一个可选参数 limit,它的作用是限制子串的最大数量,例如在上面的代码中,添加limit的参数,将其赋值为 limit = 2 ,打印其结果为:
使用语法:
str.toUpperCase();
str.toLowerCase();
toUpperCase可以将小写的字母转化为大写,已经是大写字母或者是非字母字符的则原封不动。
toLowerCase可以将大写的字母转化为小写,已经是小写字母或者是非字母字符的则原封不动。
str.startWith( String prefix ); // prefix 为前缀字符串
str.endWith ( String suffix ); // suffix为后缀字符串
这两个方法用来判断字符串是否以 字符串prefix为str的前缀 。或者字符串 suffix是否为str的后缀。它们的返回值都为boolean类型,需要使用boolean类型的变量接收。
代码案例:
public class Main {
public static void main(String[] args) {
String str = "hello world! hello java!";
boolean prefixStr1 = str.startsWith("hello");
boolean prefixStr2 = str.startsWith("java");
boolean suffixStr1 = str.endsWith("!");
boolean suffixStr2 = str.endsWith("java");
System.out.println("hello 是否为 str的前缀" + prefixStr1);
System.out.println("java 是否为 str的前缀"+ prefixStr2);
System.out.println("! 是否为 str的后缀" + suffixStr1);
System.out.println("java 是否为str的后缀" + suffixStr2);
}
}
compareTo()以字典顺序比较两个字符串,该比较方法是基于字符串中各个编码的unicode的值的。其比较规则和c语言的memcpy类似,从下标为0的字符开始逐个比较,如果比较的字符相同则比较下一个字符,如果一直比较到尾字符都是相等的,那么两个字符串进行compareTo方法比较的返回值就为0,否则期间如果str 的字符的Unicode编码值大于 其比较的字符串,则返回 1 ,小于则返回 -1 。
public class Main {
public static void main(String[] args) {
String str = "123";
String strCompare1 = "123";
String strCompare2 = "124";
String strCompare3 = "111";
System.out.println("str\"123 \" 和 字符串\"123\"比较 " + str.compareTo(strCompare1));
System.out.println("str\"123 \" 和 字符串\"124\"比较 " + str.compareTo(strCompare2));
System.out.println("str\"123 \" 和 字符串\"111\"比较 " + str.compareTo(strCompare3));
}
}
为了更好的掌握这些知识,建议去做一下这些LeetCode和牛客网上的题目,代码永远都不能只是停留在理论上,实践,亲自去敲,去使用这些方法才是最有学习效率的方法。
387. 字符串中的第一个唯一字符 - 力扣(LeetCode)https://leetcode.cn/problems/first-unique-character-in-a-string/字符串最后一个单词的长度_牛客题霸_牛客网【牛客题霸】收集各企业高频校招笔面试题目,配有官方题解,在线进行百度阿里腾讯网易等互联网名企笔试面试模拟考试练习,和牛人一起讨论经典试题,全面提升你的技术能力https://www.nowcoder.com/practice/8c949ea5f36f422594b306a2300315da125. 验证回文串 - 力扣(LeetCode)https://leetcode.cn/problems/valid-palindrome/
创作不易,来个三连