一、String类
1.概述
1)字符串解读String s1 = "abc"
; s1
是一个类类型变量,"abc"
是一个对象。只要在""
里的,都是对象。字符串最大的特点在于,一旦初始化,就不可以改变。字符串,既是对象,又是常量。
示例:
String s1 = "abc";
s1 = "kk";
System.out.println(s1);
输出结果为:kk
变化的不是"abc"
这个对象,而是s1
这个引用;重新赋值后,s1
指向了"kk"
这个对象。
2)字符串创建方式的区别
高能:
String s1 = new "abc";
String s2 = new String("abc");
s1和s2的区别在于,s1有一个对象,s2有两个对象。s2中,new是一个对象,"abc"是一个对象。小扩展
字符串在内存中有常量池,该常量池是一个数组,用于存储'a','b','c'这样的字符;字符串由字符组成,如果常量池中有'a','b','c','d','e','f'这些字符,下次创建String s3 = "abf";的时候,虚拟机会到常量池中找到这三个字符,拼接起来。
3)String类的equals()方法String
类复写了Object
类中的equals()
方法,该方法用于判断字符串是否相同。
示例:
String s1 = new "abc";
String s2 = new String("abc");
System.out.println(s1.equals(s2));
输出:true
4)String的“==”操作符比较
示例代码:
class StringCompare {
public void main(String[] args) {
String s1 = "abc";
String s2 = new String("abc");
String s3 = "abc";
System.out.println(s1 == s2);
System.out.println(s1 == s3);
}
}
输出结果为:
false
true
字符串储存在常量池当中,当s1
创建的时候,"abc"
对象已经在内存中存在了;那么,当s3
创建的时候,如果常量池中已经有"abc"
字符串的字符,就不会再创建对象,而直接让s3
指向"abc"
这个对象。
2.String类中的方法
String类是用于描述字符串这个事物。其常见的方法有:
1)获取操作
1> 获取字符串长度:int length()
2> 获取指定位置上的字符:char charAt(int index)
3> 获取指定字符的位置有如下方法:
a.int indexOf(int ch):获取指定字符第一次出现的位置
b.int indexOf(int ch, int fromIndex):获取指定字符从fromIndex位置开始,第一次出现的位置
c.int indexOf(String str):获取子字符串第一次出现的位置,也可以用于判断字符串是否包含指定字符串
d.int indexOf(String str, int fromIndex):获取子字符串从fromIndex位置开始,第一次出现的位置
e.int lastIndexOf(char ch):反向查找指定字符
2)判断操作
1> 字符串中是否包含子字符串:boolean contains(CharSequence s)
2> 字符串是否长度为零:boolean isEmpty(String str)
3> 字符串是否以指定字符串开头:boolean startsWith(String str)
4> 字符串是否以指定字符串结尾:boolean endsWith(String str)
3)转换操作
1> 将字符数组转换成字符串:
>a.构造方法:
String(char[] ch):将字符数组转换成字符串
String(char[] ch, int offset, int count):将字符数组的一部分转换成字符串
b.静态方法:
static String copyValueOf(char[] ch):将字符数组转换为字符串
static String copyValueOf(char[] ch, int offset, int count):将字符数组的一部分转换成字符串
static String ValueOf(char[] ch) :将字符数组转换为字符串
2> 将字符串转换成字符数组:char[] toCharArray()
3> 将字节数组转换成字符串:
>String(byte[] ch)
String(byte[] ch, int offset, int count):将字节数组的一部分转换成字符串
4> 将字符串转换成字节数组:
byte[] getBytes()
注意:字符串和字节数组在转换过程中,可以指定编码表。
5> 将基本数据类型转换成字符串
>static String ValueOf(int)
static String ValueOf(double)
4)替换操作
1> 将子字符替换成目标字符:String replace(char oldChar, char newChar) //如果被替换数组不存在,返回原字符串
2> 将子字符串替换成目标字符串:String replace(CharSequence target, CharSequence replecement)
5)切割操作
1> 切割字符串:String[] split(Reg reg)
6)获取子串
1> 获取字符串中的子字符串:
String substring(int beginIndex)
String substring(int beginIndex, endIndex) //不存在的下标会出现字符串下标越界异常
7)去除空格,大小写转换,字符串比较大小
1> 字符串大小写转换
>String toUpperCase()
String toLowerCase()
2> 去除字符串两端多余空格:String trim()
3> 两个字符串比较大小:int compareTo(String string)
8)字符串方法代码示例:
package com.heisejiuhuche.String;
public class StringAPI {
private static String str = "abcaaddefggut";
public static void main(String[] args) {
// get();
// is();
trans();
replace();
split();
sub();
other();
}
private static void get() {
//获取长度
print(str.length());
//根据索引获取字符
//下标越界会产生异常
print(str.charAt(7));
//根据字符获取索引
//找不到目标字符返回-1
print(str.indexOf('a', 1));
//反向查找
print(str.lastIndexOf('e'));
}
private static void is() {
String str = "ExceptionTest.java";
//判断是否以Exception开头
print(str.startsWith("Exception"));
//判断是否以.java结尾
print(str.endsWith(".java"));
//判断是否包含Test
print(str.contains("Test"));
//判断长度是否为0
print(str.isEmpty());
}
private static void trans() {
char[] ch = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};
//字符数组转字符串
String str = new String(ch, 2, 3);
print(str);
String s1 = "zmsdjlfjxlk";
//字符串转字符串数组
char[] cha = s1.toCharArray();
for(int x = 0; x < cha.length; x++) {
print("ch= " + cha[x]);
}
}
private static void replace() {
String s1 = "hello java";
//替换目标字符
String s2 = s1.replace('a', 'n');
print(s2);
//替换目标字符串
String s3 = s1.replace("java", "world");
print(s3);
}
private static void split() {
String s1 = "zhangsan, lisi, wangwu";
//切割字符串
String[] arr = s1.split(",");
for(int x = 0; x < arr.length; x++) {
print(arr[x]);
}
}
private static void sub() {
String s1 = "abcdefg";
//获取子字符串
print(s1.substring(2));
print(s1.substring(2, 4));
}
private static void other() {
String s1 = " Hello Java ";
//转小写
print(s1.toUpperCase());
//转大写
print(s1.toLowerCase());
//去除两端空格
print(s1.trim());
String s2 = "acc";
String s3 = "aaa";
//字符串比较大小
print(s2.compareTo(s3));
}
private static void print(Object obj) {
System.out.println(obj);
}
}
3.String类练习
1)模拟trim()方法
写一个trim()
方法的模拟方法,去除字符串两端的空格,返回去除空格后的字符串。
示例代码:
package com.heisejiuhuche.String;
/**
* 模拟trim()方法,去除字符串两端空格
* @author jeremy
*
*/
public class StringTest1 {
public static void main(String[] args) {
String string = " abc def g hi ";
print("(" + string + ")");
string = myTrim(string);
print("(" + string + ")");
}
private static String myTrim(String string) {
int start = 0;
int end = string.length() - 1;
//如果从下标0开始的字符为空格,则继续往后检查,直到字符不为空格
while(start <= end && (string.charAt(start) == ' ')) {
start++;
}
//如果从字符串结尾开始检查,字符为空格,则继续倒序检查,直到字符不为空格
while(start <= end && (string.charAt(end) == ' ')) {
end--;
}
//返回院字符串的子字符串,注意end要+1,不然丢失最后一个字符
return string.substring(start, end + 1);
}
private static void print(Object obj) {
System.out.println(obj);
}
}
程序输出结果:
( abc def g hi )
(abc def g hi)
2)反转字符串
将任意字符串反转输出。
示例代码:
package com.heisejiuhuche.String;
public class StringTest2 {
public static void main(String[] args) {
String string = " abcd efg hi ";
print("(" + string + ")");
string = reverseString(string);
print("(" + string + ")");
}
/* 反转字符串 */
private static String reverseString(String string) {
char[] ch = string.toCharArray();
reverse(ch);
string = new String(ch);
return string;
}
/* 反转数组 */
private static void reverse(char[] ch) {
for(int start = 0, end = ch.length - 1; start < end; start++, end--) {
swap(ch, start, end);
}
}
/* 交换元素 */
private static void swap(char[] ch, int start, int end) {
char tmp = ch[start];
ch[start] = ch[end];
ch[end] = tmp;
}
private static void print(Object obj) {
System.out.println(obj);
}
}
程序输出结果:
( abcd efg hi )
( ih gfe dcba )
3)反转指定字符串
将任意字符串中的指定部分反转输出。
示例代码:
package com.heisejiuhuche.String;
public class StringTest3 {
public static void main(String[] args) {
String string = " abcd efg hi ";
print("(" + string + ")");
string = reverseString(string);
print("(" + string + ")");
}
/* 反转字符串 */
private static String reverseString(String string) {
return reverseString(string, 5, 9);
}
/* 反转指定字符串 */
private static String reverseString(String string, int start, int end) {
char[] ch = string.toCharArray();
reverse(ch, start, end);
string = new String(ch);
return string;
}
/* 反转数组 */
private static void reverse(char[] ch, int x, int y) {
for(int start = x, end = y - 1; start < end; start++, end--) {
swap(ch, start, end);
}
}
/* 交换元素 */
private static void swap(char[] ch, int start, int end) {
char tmp = ch[start];
ch[start] = ch[end];
ch[end] = tmp;
}
private static void print(Object obj) {
System.out.println(obj);
}
}
程序输出结果:
( abcd efg hi )
( abe dcfg hi )
4)获取一个字符串在另一个字符串中出现的次数
示例代码:
package com.heisejiuhuche.String;
public class StringTest4 {
public static void main(String[] args) {
String str = "kkabkkckkdkkefkkskkdddddkk";
System.out.println(getSubCount2(str, "kk"));
}
/* 方法一,使用indexOf(String str)方法 */
private static int getSubCount(String str, String key) {
int count = 0;
int index = 0;
/*在str中寻找key,能找到,就继续往后找,index记录每次找到key的下标
下标加上key的长度,就是剩下字符串的起始位置,截取剩下的字符串
然后在剩下的字符串里继续寻找key,直到indexOf()方法返回-1
最后返回count */
while((index = str.indexOf(key)) != -1) {
str = str.substring(index + key.length());
count++;
}
return count;
}
/*方法二,使用indexOf(String str, int fromIndex)方法,较高效
* index记录找到key的下标位置,加上key的长度,就是下一次应该开始寻找的下标
* 让indexOf()方法直接从这个位置开始寻找即可*/
private static int getSubCount2(String str, String key) {
int count = 0;
int index = 0;
while((index = str.indexOf(key, index)) != -1) {
index += key.length();
count++;
}
return count;
}
}
程序输出结果:
7
5)获取两个字符串中最大相同子串
在字符串"sdwrtuiohellojavacbsdwrtwtwhdfh"
;和"dsewrwhellojavadcwry"
;中,输出最大相同子串,即hellojava
。
示例代码:
package com.heisejiuhuche.String;
/**
* 1.先确定较短的字符串;在长字符串中搜索整个较短的字符串;
* 2.如果没有匹配,就将较短的字符串长度-1;
* 3.长度-1之后的较短字符串有两种情况,末尾减少一个字符,和首部减少一个字符的情况;
* 4.用substring()方法得到这两个字符串;这个过程,就是先取0到较短字符串长度-1的子串
* 再取首尾下标都自增1之后的子串;
* 5.以此类推,如果这两个子串还是没有在较长字符串中找到匹配,就将较短字符串的长度-2;
* 6.再通过取子串的过程,得到3个子串(0到较短的长度-2,然后下标自增,即1到较短的长度-1,
* 然后下标再自增,即2到较短的长度),直到尾部下标等于较短字符串长度为止;
* 7.每次截取字符串,都判断这个子串是否能在较长字符串中匹配;
* 8.外层循环控制循环次数(循环较短字符串的长度次),内循环控制每次要截取的子串个数,并进行匹配
* 匹配上,返回该子串,匹配不上返回空字符串
* @author jeremy
*
*/
public class StringTest5 {
public static void main(String[] args) {
String s1 = "sdwrtuiohellojavacbsdwrtwtwhdfh";
String s2 = "dsewrwhellojavadcwry";
System.out.println(getMaxSubString(s2, s1));
}
private static String getMaxSubString(String s1, String s2) {
String longer;
String shorter;
//如果s1长于s2,longer等于s1
longer = (s1.length() > s2.length()) ? s1 : s2;
//如果longer等于s1,那么s2较短
shorter = (longer == s1) ? s2 : s1;
for(int x = 0; x < shorter.length(); x++) {
for(int y = 0, z = shorter.length() - x; z != shorter.length() + 1; y++, z++) {
String tmp = shorter.substring(y, z);
if(longer.contains(tmp)) {
return tmp;
}
}
}
return "";
}
}
程序运行结果:
hellojava
二、StringBuffer类
1.定义StringBuffer
是一个字符串缓冲区,是一个容器。
2.StringBuffer的特点
1)长度可变;
2)可以用于对字符串进行修改;
2)可以直接操作多个数据类型;
3)最终通过toString()
方法输出字符串
3.StringBuffer的功能
1> 存储功能
-StringBuffer append()
:将指定的数据作为参数添加到已有数据的结尾处
示例代码:
StringBuffer sb = new StringBuffer();
sb.append("3").append("sdjfkd").append(sdjfkd);
代码输出:3sdjfkdsdjfkd
高能:
连续调用append()方法的现象叫做方法调用链;因为append()方法返回一个StringBuffer对象,对象还能调用本类方法。
-StringBuffer insert(int offset, String str)
:在指定位置插入字符串
示例代码:
StringBuffer sb = new StringBuffer();
sb.append("3").append("sdjfkd").append(true);
sb.insert(1, "qq");
代码输出:3qqsdjfkdsdjfkd
注意:
如果插入的下标不存在,会出现字符串下标越界异常。
2> 删除功能
-StringBuffer delete(int start, int end)
:删除从start
开始到end
(不包含)技术的字符串
示例代码:
StringBuffer sb = new StringBuffer("abcde");
sb.delete(1, 3);
代码输出:ade
-StringBuffer deleteCharAt(int index)
:删除指定位置的字符串
示例代码:
StringBuffer sb = new StringBuffer("abcde");
sb.deleteCharAt(2);
代码输出:abde
3> 获取功能
-char charAt(int index):通过下标获取字符
-int indexOf(String str):获取目标字符串出现的第一个位置
-int lastIndexOf(String str):反向查找目标字符串出现的第一个位置
-int length():获取字符串长度
-String substring(int start, int end):获取子串
4> 修改功能
-StringBuffer replace(int start, int end, String str)
:将从start
开始到end
(不包含)结束的字符串替换为目标字符串
示例代码:
StringBuffer sb = new StringBuffer("abcde");
sb.replace(1, 4, "java");
代码输出:ajavae
-void setCharAt(int index, char ch)
:将下标所在字符替换成目标字符
示例代码:
StringBuffer sb = new StringBuffer("abcde");
sb.setCharAt(2, 'k');
代码输出:abkde
-StringBuffer reverse()
:反转字符串
-void getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
:将缓冲区中的指定数据存储到指定数组的指定位置
示例代码:
StringBuffer sb = new StringBuffer("abcdef");
char[] ch = new char[6];
sb.getChars(1, 4, ch, 1);
for(int x = 0; x < ch.length; x++) {
System.out.println(ch[x]);
}
代码输出:
ch[0] =
ch[1] = b
ch[2] = c
ch[3] = d
ch[4] =
ch[5] =
三、StringBuilder类
1.定义StringBuilder
是一个可变的字符序列,与StringBuffer
功能相同,是StringBuffer
的一个简易替换。
2.与StringBuffer的区别StringBuffer
是线程同步的,而StringBuilder
不同步,其在多线程情况下会出现安全问题。
3.开发建议StringBuilder
始于JDK5.0,叫StringBuffer
而言是一个更新的类。JDK的升级无外乎提升效率,简化代码,提高安全性。StringBuilder
的出现提高了代码运行效率。实际开发中,建议使用StringBuilder
;需要同步的时候,由开发者自行加锁,解锁。
四、基本数据类型包装类
1.定义
Java视一切为对象,包括基本数据类型。八种基本数据类型对应着八种基本数据类型的包装类。包装类中定义了一些列操作基本数据类型的方法和属性,便于开发者使用。
2.包装类的意义
一个int型的数据,有自己的取值范围,有自己的表现形式,这些相当于是int类型数据的属性;如何将一个int型数据转换为其他进制的表现形式,只有int类型数据自己最清楚。如果将int类型数据封装为类,在类中定义进制转换的方法,这样操作int类型数据就会很方便。
3.包装类的应用
包装类通常用于基本数据类型和字符串之间做转换。
1)基本数据类型转换成字符串
示例代码:
Integer.toString(34);//将34整数转换为字符串34`
2)字符串转换成基本数据类型
示例代码:
Integer.parseInt("34");//将字符串34转换为整数34注意:
-包装类Character没有parse方法,因为其本身就是字符;
-在字符串转换为基本数据类型时,传入了字符,会出现数字格式异常
3)字符串进制表现形式转换成十进制数
示例代码:
Integer.parseInt("110", 2);//将字符串110作为二进制数转为十进制整数,结果为6
Integer.parseInt("3c", 16)//结果为60小扩展
将字符串"123"转换成int类型数据的另一种方法:
Integer i = new Integer("123");
int num = i.intValue();//非静态方法
4)数字比较:int compareTo(Integer anotherInteger)
4.包装类新特性
1)JDK5.0版本之后,基本数据类型引入了自动装箱,自动拆箱的概念,以简化代码。
示例代码:
Integer x = new Integer(4);//这行代码相当于
Integer x = 4;//自动装箱,4是Integer对象
x += 2;//可以直接进行运算,先将x自动拆箱,变为int类型,再进行运算,最后将和自动装箱
注意:
-自动拆箱的原理是,先执行了x.intValue();得到x的int类型数据,再进行运算;
-如果声明x为Integer引用,其值可以被赋为空(null);此时如果再进行算数运算,会出现空指针异常;因为自动拆箱时,需要调用intValue()方法,而x = null;程序出错前方高能:Integer取值范围(面试用)
示例代码:
Integer m = 128;
Integer n = 128;
System.out.println("m == n: " + (m == n));代码输出:false
示例代码:
Integer a = 127;
Integer b = 127;
System.out.println("a == b: " + (a == b));代码输出:true
因为a和b指向同一个Integer对象。当数值在byte范围内时,如果该数值已经存在,包装类新特性就不会再开辟新的内存空间。