v String类:
String是final的类,因此不能继承,因此不能有子类。
双引号引起来的,都是String类的一个具体对象。
Strings = new String(); 用法等价于 String s = “”; 但意义不相同。
! 例题:
String s1 = new String(“abc”);
String s2 = “abc”;
请问s1与s2有什么区别?
答:s1在内存中有两个对象(s1本身和常量池中的字符串“abc”),s2在内存中只有一个对象。
String类 一旦被初始化就不可以被改变。
String类复写了equals方法,判断字符串内容是否相同。
v String对象的存储
字符串是常量,一旦创建不能被修改。
字符串在程序中经常使用,虚拟机会将其缓存在String池中。
了解 String s= “abc” 和 String s = new String(“abc”) 的区别。
v String类的构造函数
String(byte[] bytes)
通过指定字节数组构建字符串。
String(byte[] bytes,int offset, int length)
通过指定字节数组、数组元素偏移量和元素个数构建字符串。
String(byte[] bytes,String charsetName)
通过指定字节数组和指定码表构建字符串。
String(byte[] bytes,int offset, int length,String charsetName)
通过指定字节数组、数组元素偏移量、元素个数和指定码表构建字符串。
String(char[] value)
通过指定字符数组构建字符串。
String(char[] value,int offset, int count)
通过指定字符数组、数组元素偏移量和元素个数构建字符串。
String(StringBuffer buffer)
通过指定StringBuffer构建字符串。
String(StringBuilder builder)
通过指定StringBuffer构建字符串。
JDK1.5新特性:基本数据类型装箱,这使得int等基本数据类型能够作为实际参数,传递给形式参数。
v String类的常用方法
--1.字符串查找操作:
char charAt(int index)
查找指定位置的字符,返回某一位置上的字符,下标从0开始
当访问到字符串中不存在的脚标时,StringIndexOutOfException异常。
int length()
获取数组的长度,有多少个字符就返回几
intindexOf(int ch)
返回ch在字符串中首次出现的位置,脚标从0开始。没找到返回-1。
intindexOf(int ch, int fromIndex)
从fromIndex开始,查找ch在字符串中存在的位置
int indexOf(String str)
判断字符串出现的位置
intlastIndexOf(int ch)
方向索引,从右向左查找ch出现的第一个字符的下标
--2.字符串判断:
booleanstartWith(String str)
判断是否以指定字符串开始
booleanendWith(String str)
判断是否以指定字符串结束
booleanisEmpty()
判断字符串是否为空,其实就是判断length()
booleancontains(CharSequence)
字符串是否包含某一子串
CharSequence是String、StringBuffer等的父类
indexOf()也可以判断是否包含子串
booleanequals(String)
判断字符串内容是否相等
booleanequalsIgnoreCase(String)
忽略大小写的比较内容是否相等
--3.字符串转换
staticString copyValueOf(char[])
将字符数组转换为字符串(String的构造函数就能实现String(char[]) String(char[],offset, count) )
staticString copyValueOf(char[], offset, count)
将字符数组转换为字符串,offset开始,取count个字符
staticString valueOf(char[])
将字符数组转换为字符串
3+"" 等价于 String.valueOf(3)
char[]toCharArray()
将字符串转换成字节数组。
字节数组也是一样的,只不过将char换成byte就行。
--4.字符串替换
String replace(CharSequence target,CharSequence replacement)
替换字符串,返回的结果是替换后的字符串,可是原字符串不改变。
也可以只替换单个字符。
--5.字符串切割
String substring(intbeginIndex, int endIndex)
截取子字符串,从beginIndex位置开始到endIndex,包含beginIndex,不包含endIndex
String substring(intbeginIndex)
截取子字符串,从beginIndex到结尾
如果角标不存在,会抛出角标越界异常
String[] split(String regex)
按指定的字符串将原串进行分割,得到字符串数组
例:
String s = "haisdh,jdfhj, jaofh";
String[] array = s.split(",");
--6.大小写转换、去除空格、比较
String toUpperCase()
转大写
String toLowerCase()
转小写
String trim()
去除空格,只去除开头结尾的空格,要去掉全部空格用replaceAll()方法。
int compareTo(StringanotherString)
按字典顺序比较两个字符串
返回0 两字符串相等
返回整数 this字符串 > anotherString
返回整数anotherString > this字符串
Ø 字符串练习
设计一个方法, 获取一个已知文件名的扩展名.
Person.java的扩展名是.java,Person.java.txt的扩展名是.txt
设计一个方法, 查找一个字符串中子字符串出现的所有位置.
“xxxabcxxxabcxxx”中abc出现了2次,索引位置是3和9
查找一个字符串中出现最多的字符.
“hello world”中L出现了3次
设计方法,使用System.in.read()读取一行.
循环读取一个字节,读取到\r\n结束。考虑中文问题
已知一个字符串. 设计一个方法, 可以从这个字符串中打印n个字节. 但不能打印出半个中文.
短信一次发送字节140个,如果超过140字节就会分为两条。这时如果第140个字节是中文的前半,那么第一条短信应该发送139字节。
查找两个字符串中最大相同子串.
“abc”和“bcd”的最大相同子串是”bc”
“xyzabcdefxyz”和“xxxabcdefooo”的最大相同子串是”abcdef”
ØStringBuffer类
StringBuffer是字符串缓冲区,是一个容器(不管你添加,减少,容器还是不变,StringBuffer还是不变)
特点:
①长度可变
②可以操作多个数据类型
③toString()方法转换成String类型
C create
R read
U update
D delete
StringBuffer append()
将指定数据作为参数添加到已有数据的结尾处。
返回值是对象本身,这一点与String有着本质的区别。
StringBuffer insert(index, 数据)
将数据插入到index位置
StringBuffer delete(startIndex, endIndex)
删除从startIndex到endIndex位置的字符,包含头不含尾
StringBuffer deleteCharAt(index)
删除指定位置的字符
char charAt(int index)
获取指定位置的字符
int indexOf(String str)
获取指定字符串在StringBuffer的位置,没有返回-1
int lastIndexOf(String str)
获取从前到后,第一次出现指定字符串的角标
String subString(int start, int end)
String subString(int start)
获得子串,不过注意返回的是String类型
StringBuffer replace(int start, int end, String str)
将从start到end的子串改为str
void setCharAt(int index, char ch)
将index位置的字符替换成ch
StringBuffer reverse()
将缓冲字符串反转。(注意String类提供 没有这个方法)
void getChars(int srcBegin, int srcEnd, char[] dst, intdstBegin)
将缓冲字符串从srcBegin到srcEnd的字符转换成char数组存入dst数组从dstBegin的位置。访问到不存在角标要出现越界。
ØStringBuilder类
StringBuilder完全兼容StringBuffer的API,不同之处在于:
StringBuffer是线程安全的,StringBuilder是线程不安全的
StringBuilder效率高,如果不涉及到线程同步问题,建议使用StringBuffer。实际上也可以自己加锁,实现线程同步问题。StringBuilder是为了提高效率。
所以以后建议使用StringBuilder。
v --JDK的升级主要是围绕着三个部分
1.提高效率
2.简化书写
3.提高安全性
Ø基本数据类型包装类
为什么要有包装类?
包装类提供了一系列常数,方便我们使用,比如数据类型能存放的最大值、最小值。
包装类提供一些方法,方便我们使用。
--基本数据类型对应的包装类:
byte Byte
short Short
int Integer
long Long
char Charactor
boolean Boolean
float Float
double Double
--包装类最常用的功能:基本数据类型与字符串类型之间的转换:
基本数据类型转成字符串:
Integer.toString(10)
""+基本数据类型
字符串转换成基本数据类型:
Integer.parseInt("123"); //注意:如果格式不对,会抛出NumberFormatException。
注意:Charactor没有转换成字符串的方法。
下面还有一种转换方式(这种是非静态的,需要依赖对象):
Integer i =new Integer("123");
int num = i.intValue();
--十进制转换为其它进制:
Integer.toBinaryString(8); //按二进制输出
Integer.toHexString(60); //按十六进制输出
Integer.toOctalString(67); //按八进制输出
--其他进制转换为十进制:
Integer.parseInt("345",int 进制);
注意格式,否则NumberFormatException。
v 基本数据类型的包装类的新特性:
JDK1.5版本以后出现的新特性:
自动装箱:
Integer x = 4; //引用类型变量指向的是对象。
自动拆箱:
Integer y = 4+ y; //y先自动拆箱变成int型,然后与4相加,然后进行装箱,赋值给y。
自动拆箱是调用的intValue()方法,请看下面的例子:
Integer x = null;
x = x + 4;
运行时,抛出异常NullPointerException,因为x = x + 4;相当于x= x.intValue() + 4; x对象为空,自然NullPointerException()。
请看下面的例子:
Integera = 100; Integer b = 100; //a,b指向同一空间
System.out.println("a== b :: " + (a==b));
Integerx = 128; Integer y = 128; //x,y指向不同空间
System.out.println("a== b :: " + (x==y));
JDK1.5新特性,对于在byte范围之内的数值,如果该数值存在,则不会在开辟新的空间。
自己做的练习:
/*
1.模拟trim()方法,去除字符串两端的空格
*/
public static String myTrim(String str)
{
int start = 0; //非空格开始的字符角标,初始化为0
int end = str.length()-1; //从后向前非空格的字符角标
while(start<=end && str.charAt(start)==' ') //查找第一个非空格的字符的角标
start++;
while(start<=end && str.charAt(end)==' ') //从后向前第一个非空格的字符角标
end--;
return str.substring(start, end+1); //因为substring()是取前不取后,所以end+1
}
/*
2.1.将字符串反转
思路:
①将字符串转换成字符数组
②将字符数组反转
③将数组转换成字符串
*/
public static String reverseString(String str)
{
// char[] chArray = str.toCharArray();
// int length = chArray.length;
// for(int i = 0; i < length/2; i++)
// {
// swap(chArray, i, length-1-i);
// }
// return String.copyValueOf(chArray);
//我们应该做到尽可能的代码复用,所以直接调用已经实现的方法,而不是重新写上面这些重复的代码
return reverseString(str, 0, str.length());
}
/*
2.2.将字符串从某开始位置到某结束位置的子串反转,返回子串反转的整个字符串
思路:
①将字符串转换成字符数组
②将字符数组反转
③将数组转换成字符串
*/
public static String reverseString(String str, int startIndex, int endIndex)
{
char[] chArray = str.toCharArray();
for(int i = startIndex; i < (endIndex+startIndex)/2; i++)
{
endIndex--;
swap(chArray, i, endIndex);
}
return String.copyValueOf(chArray);
}
//交换两个字符的值
private static void swap(char[] chArray, int x, int y)
{
chArray[x] ^= chArray[y];
chArray[y] ^= chArray[x];
chArray[x] ^= chArray[y];
}
/*
Error,这样不行,实际参数是char类型的,传递的是变量本身的值
(Java中只有值传递,就是说是一个副本,如果是引用类型的话,通过这个副本中的值就可以找到相应的元素地址,从而改变元素),
传递的值其实是一个副本,改变的也是这个副本
?????为什么用Charactor也不行?什么原因???
*/
// private static void swap(Character ch1, Character ch2) //交换两个字符
// {
//// ch1 ^= ch2; //^=不能用于Charactor类型
//// ch2 ^= ch1;
//// ch1 ^= ch2;
//
// Character tmp;
// tmp = ch1;
// ch1 = ch2;
// ch2 = tmp;
// }
/*
3.1.统计一个字符串在另一个字符串中出现的次数,方法一
*/
public static int getSubCount(String str, String string) //统计str在string中出现的次数
{
int count = 0; //计数器
int i = 0; //子串在父串的位置
while((i = string.indexOf(str, i)) != -1) //只要返回的不是-1就表示剩下的字符串中还有子串,并将结果赋值给i
{
i++; //从下一个位置开始查找是否还有子串,i++是getSubCount(kk, kkk)得到2,如果getSubCount(kk, kkk)得到1,就应该是i+=str.length();个人觉得应该等于2,具体的根据需求呗
count++; //计数器加一
}
return count; //返回结果
}
/*
3.2.统计一个字符串在另一个字符串中出现的次数,方法二
*/
public static int getSubCount2(String str, String string) //统计str在string中出现的次数
{
int count = 0; //计数器
int i = 0; //子串在父串的位置
while((i = string.indexOf(str)) != -1)
{
string = string.substring(i+1); //getSubCount(kk, kkk)得到2,如果getSubCount(kk, kkk)得到1,就应该是string.substring(i+str.length());个人觉得应该等于2,具体的根据需求呗
count++;
}
return count; //返回结果
}
/*
4.获得两个字符串中最大相同子串,返回子串
步骤:
①用较小的字符串按长度递减的方式(注意:长度一样的子串有很多)得到子串
②另一个字符串中是否包含该子串
*/
public static String maxSubString(String str1, String str2)
{
String strLong = str1; //长串
String strShort = str2; //短串
String subStr = str2; //子串
if(str1.length() < str2.length())
{
strLong = str2;
strShort = str2;
subStr = str1;
}
for(int i = subStr.length(); i >= 0 && !strLong.contains(subStr); i--) //子串长度
{
for (int j = 0; j < strShort.length()-i; j++)
{
subStr = strShort.substring(j, j+i+1); //获得子串,注意subString是取前不取尾,所以加1
if (strLong.contains(subStr)) //如果包含该字串
{
break;
}
}
}
return subStr;
}
public static void deleteTest()
{
StringBuffer sb = new StringBuffer("hello world!!!");
sb.delete(0,sb.length()); //清空缓冲区
System.out.println(sb);
sb = new StringBuffer("hello world!!!");
sb.deleteCharAt(3); //删除指定位置的字符
System.out.println(sb);
sb = new StringBuffer("hello world!!!");
sb.delete(3,7); //第一个参数超过上限会抛异常StringIndexOutOfBoundsException,第二个超出了就截到末尾,当endIndex<startIndex时会抛异常,StringIndexOutOfBoundsException
System.out.println(sb);
sb = new StringBuffer("hello world!!!");
sb.delete(3,100); //不会抛异常,删除从3到末尾的字符
System.out.println(sb);
sb = new StringBuffer("hello world!!!");
sb.delete(5,4); //角标越界
System.out.println(sb);
sb = new StringBuffer("hello world!!!");
sb.delete(30,100); //抛异常StringIndexOutOfBoundsException,角标越界
System.out.println(sb);
}
/*
2.StringBuffer insert(index, 数据)方法,在缓冲字符串中插入字符串
*/
public static void insertTest()
{
StringBuffer sb2 = new StringBuffer("hello world!!!");
sb2.insert(3, "哈哈哈"); //在第三个位置插入字符串“哈哈哈”,结果是“hel哈哈哈lo world!!!”
System.out.println(sb2);
}
/*
1.StringBuffer的append方法,StringBuffer本身是可变的,区别与String
*/
public static void appendTest()
{
StringBuffer sb = new StringBuffer();
StringBuffer sb1 = sb.append("StringBuffer哈哈"); //StringBuffer append():在末尾添加东西(这个东西可以是任何基础类型,String类型)
System.out.println("sb == sb1 :: " + (sb==sb1));
System.out.println(sb);
System.out.println(sb1);
String s = new String("String");
String s1 = s.substring(1); //String经过subString后返回的另一个字符串,本身不变
System.out.println("s == s1 :: " + (s==s1));
System.out.println(s);
System.out.println(s1);
}