1.String类
1.1 String类的两种实例化方式
- 直接赋值
String str = "hello"
- 通过构造方法实例化String类
String str = new String("hello")
1.2 字符串相等比较(内容)
public boolean equals(String anotherString);
成员方法,需要通过对象调用
例:
str1.equals(str2);
看代码:
public class Test{
public static void main(String[] args){
String str1 = "hello";
String str2 = new String("hello");
System.out.println(str1 == str2);
System.out.println(str1.equals(str2));
}
}
输出结果:
false
true
这里就体现出equals()方法的作用了,str1 == str2这判断的是这两个字符串的地址是否相同,因为str2用了new,重新开辟了一个新空间,所以和str1的地址肯定是不相同的;但equals()比较的是两个字符串的内容,str1和str2内容相同,所以返回true。
看图:
1.3字符串常量是String的匿名对象
例:"hello".equals(str2);
这里有一个坑,如果我们使用:str.equals(“hello”),有可能会出现nullPointException(空指针异常)报错,因为str可能是一个空字符串。
所以记住,以后在开发中,如果要判断用户输入的字符串是否等同于特定字符串,一定要将字符串(String常量)写在前面。
1.4 对象池(对象数组)
我们先来看一段代码吧:
public class Test{
public static void main(String[] args){
String str1 = "hello";
String str2 = "hello";
System.out.println(str1 == str2);
}
}
我们先来猜猜这个的返回值吧。肯定好多人都认为它返回的是false吧,但不是的,为了让你们相信,直接上图吧。
没错,它返回的就算true。
肯定有疑问了吧,上边不是说了str1 == str2比较的是地址吗?它两地址怎么会相等。
那是因为JVM底层会自动维护一个字符串的对象池,如果采用直接赋值的形式进行String的对象实例化 (这里要特别注意,如果使用了new,str1 == str2 )肯定是false,因为new就会开辟一个新空间,地址肯定不相等,这个对象会自动保存在这个对象池中。如果下次继续使用直接赋值的形式声明String类,这个时候,如果对象池中已经有了第二次声明的这个内容,则会直接引用,不会创建新的空间(所以str1的地址等于str2的地址);如果没有,则开辟新的堆空间后,再将其保存在对象池中供下次使用。
再画图解释一下吧:
1.5 字符串常量不可变更
字符串一旦定义后不可改变。因为字符串的底层实现就算字符数组,我们都知道,数组最大的一个缺陷就算它的长度是固定的,所以定义字符串的常量时,它的内容不可改变。
我们来看看这段代码:
public class Test{
public static void main(String[] args){
String str = "hello";
System.out.println(str+"world");
}
}
它的输出结果如下:
我们发现hello和world连接在了一起,不是说字符串内容一旦定义就不能改变吗?
其实这里并没有改变字符串内容,变的是字符串对象。我们来看实际的过程图;
说这个的目的何在呢?
因为改变的是对象的引用,前边的“hello”和"world"都成了垃圾空间,如果一直+下去,垃圾空间将会特别大。
1.6 字符与字符数组的相互转换
a. 将字符数组转为字符串
public String(char[] value)
public String (char[] value, int offest, int count)//offest表示从数组的哪个位置开始,count表示将count个字符转为字符串
例:
public class Test{
public static void main(String[] args){
char[] arr = {'h','e','l','l','o','w','o','r','l','d'};
String str1 = new String(arr);
String str2 = new String(arr, 5, 5);
System.out.println(str1);
System.out.println(str2);
}
}
b. 将字符串转为单个字符
public char charAt(int index)
例:
public class Test{
public static void main(String[] args){
String str = "hello world";
char c = str.charAt(4);
System.out.println(c);
}
}
c. 将字符串变为字符数组
public char[] toCharArray()
例:
public class Test{
public static void main(String[] args){
String str = "hello world";
char[] arr = str.toCharArray();
System.out.println(arr.length);
}
}
1.7 字节(byte)与字符串
a. 将字节数组转为字符串
public String(byte[] value)
public String(byte[] value, int offest, int count)
b.将字符串转为字节数组
public byte[] getBytes()
例:
public class Test{
public static void main(String[] args){
String str = "hello world";
byte[] data = str.getBytes();
for(int i = 0; i < data.length; i++){
System.out.print(data[i]+"、");
}
System.out.println();
//将字节数组转换为字符串
System.out.println(new String(data));
}
}
1.8 字符串比较
a. 不区分大小写相等比较
public boolean equalsIgnoreCase(String anotherString)
例:
public class Test{
public static void main(String[] args){
String str1 = "hello world";
String str2 = "Hello World";
System.out.println(str1.equalsIgnoreCase(str2));
}
}
b. 比较两个字符串大小
public int compareTo(String anotherString)
- 返回大于0:表示大于比较对象
- 返回等于0:表示两者相等
- 返回小于0:表示小于比较对象
例:
public class Test{
public static void main(String[] args){
String str1 = "hello world";
String str2 = "Hello World";
System.out.println(str1.compareTo(str2));
}
}
1.9 字符串查找
public boolean contains(String str):判断str在本字符串中是否存在
例:
public class Test{
public static void main(String[] args){
String str = "hello world";
System.out.println(str.contains("ld"));
}
}
2.public boolean startsWith(String str):判断是否以指定字符串开头
例:
public class Test{
public static void main(String[] args){
String str = "hello world";
System.out.println(str.startsWith("e"));
}
}
3. public boolean startsWith(String str, int index):判断指定位置是否以指定字符串开头
例:
public class Test{
public static void main(String[] args){
String str = "hello world";
System.out.println(str.startsWith("w", 6));
}
}
4. public boolean endsWith(String str):判断是否以指定字符串结尾
例:
public class Test{
public static void main(String[] args){
String str = "hello world";
System.out.println(str.endsWith("d"));
}
}
1.10 字符串替换
public String replaceAll(String regex, String replacement):替换所有指定内容
例:
public class Test{
public static void main(String[] args){
String str = "hello world";
System.out.println(str.replaceAll("l", "_"));
}
}
2. public String replaceFirst(String regex, String replacement):替换首个指定内容
例:
public class Test{
public static void main(String[] args){
String str = "hello world";
System.out.println(str.replaceFirst("l", "_"));
}
}
1.11 字符串拆分
3. public String[] split(String regex):将字符串按照指定格式全部拆分
例:
public class Test{
public static void main(String[] args){
String str = "hello world";
String[] result = str.split(" ");//按照空格拆分
for(String s: result){
System.out.println(s);
}
}
}
4. public String[] split(String regex, int limit):将字符串按照指定格式部分拆分,数组长度为limit
例:
public class Test{
public static void main(String[] args){
String str = "hello world haha";
String[] result = str.split(" ", 2);
for(String s: result){
System.out.println(s);
}
}
}
1.12 字符串截取
5. public String substring(int beginIndex):从指定位置开始截取到字符串结尾
例:
public class Test{
public static void main(String[] args){
String str = "hello world haha";
System.out.println(str.substring(3));
}
}
6. public String substring(int beginIndex, int endIndex):截取部分
例:
public class Test{
public static void main(String[] args){
String str = "hello world haha";
System.out.println(str.substring(3, 9));
}
}
1.13 String类的其他方法
a. 去掉左右空格
public String trim()
例:
public class Test{
public static void main(String[] args){
String str = " hello world haha ";
System.out.println(str.trim());
}
}
b. 字符串转大小写
public String toUpperCase()
public String toLowerCase()
例:
public class Test{
public static void main(String[] args){
String str = "hello world";
String str1 = "HELLO";
System.out.println(str.toUpperCase());
System.out.println(str1.toLowerCase());
}
}
c. 判断字符串是否为空(只能判断是否为空字符串而不是null)
public boolean isEmpty()
例:
public class Test{
public static void main(String[] args){
String str = "";
System.out.println(str.isEmpty());
}
}
1.14 两只sb(StringBuffer()、StringBuilder())----方便字符串的修改(前边说过String是不能修改字符串的)
a. 字符串修改
public StringBuffer append(各种数据类型)
例:
public class Test{
public static void main(String[] args){
StringBuffer sb = new StringBuffer();
sb.append("hello").append("world");
fun(sb);
System.out.println(sb);
}
public static void fun(StringBuffer s){
s.append("\n").append("Calm");
}
}
b. StringBuffer与String的相互转换
(1)String转成StringBuffer
调用StringBuffer的构造方法或append()方法
(2)StringBuffer转为String
调用toStrig()方法
c. 字符串反转
public StringBuffer reverse()
例:
public class Test{
public static void main(String[] args){
StringBuffer sb = new StringBuffer();
sb.append("hello").append("world");
System.out.println(sb.reverse());
}
}
d. 删除指定范围的数据
public StringBuffer delete(int start, int end)
例:
public class Test{
public static void main(String[] args){
StringBuffer sb = new StringBuffer();
sb.append("hello").append("world");
System.out.println(sb.delete(2, 5));
}
}
e. 插入数据
public StringBuffer insert(int offest, 各种数据类型)
例:
public class Test{
public static void main(String[] args){
StringBuffer sb = new StringBuffer();
sb.append("hello").append("world");
System.out.println(sb.insert(2, "你好"));
}
}
总结
String、StringBuffer、StringBuilder的区别:
- String的内容不可以修改,而两只sb可修改内容(append)
- StringBuffer采用同步处理,线程安全,效率较低
- StringBuilder采用异步处理,线程不安全,效率较高。
例:
String s = "hello";
System.out.println(s+"world");
底层会将String自动转换为StringBuilder。
2.Object类-----接收除基本类型所有的类的对象
Object是java默认提供的类
java中,除了Object类,所有的类都存在继承关系,默认会继承Object父类,所有类(除了8大基本类型(byte、short、int、long、float、double、char、boolean))对象都可以通过Object类进行接收。
2.1 取得对象信息-----toString()
直接使用对象的输出,默认输出一个地址编码,但如果输出的是String对象,此时会输出字符串的内容而不是地址,这是因为String覆写了Object的toString()方法。
System.out.println():系统输出默认会调用对象的toString(),也就算说,一旦出现System.out.println(),其实就算调用了toString(),输出的是toString()里的东西。
例:
class Person{
private int age;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
}
public class Test{
public static void main(String[] args){
Person person = new Person(18,"张三");
System.out.println(person);
}
}
从输出结果可以看出,输出的是一个地址编码,这个地址就算Person类的地址。
现在我们想要输出年龄和姓名的话,就需要覆写它的toString()方法。
看代码:
class Person{
private int age;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
}
public class Test{
public static void main(String[] args){
Person person = new Person(18,"张三");
System.out.println(person);
}
}
我们现在再来看看输出结果:
如果我们不想输出地址,而要输出本类信息,就需要在子类中覆写toString()方法。
2.2 对象比较-----equals()
String类对象的比较使用的是equals()方法,实际上,String类的equals()也是覆写了Object类的equals()方法。
例:
class Person{
private int age;
private String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
@Override
public String toString() {
return "Person{" +
"age=" + age +
", name='" + name + '\'' +
'}';
}
@Override
public boolean equals(Object obj){
if(obj == null){
return false;
}
if(this == obj){
return true;
}
//如果obj不是Person类对象
if(!(obj instanceof Person)){
return false;
}
//向下转型,比较属性值
Person per = (Person) obj;
return (this.age == per.age) && (this.name.equals(per.name));
}
}
public class Test{
public static void main(String[] args){
Person person1 = new Person(18,"张三");
Person person2 = new Person(18,"张三");
System.out.println(person1.equals(person2));
}
}
2.3 接收引用数据类型
Object可以接收所有引用类型,包括:类、数组、接口。
public class Test{
public static void main(String[] args){
//Object接收数组对象,发生向上转型
Object obj = new int[]{1, 4, 2, 7};
//向下转型,需要强转
int[] data = (int[]) obj;
for(int i : data){
System.out.print(i+"、");
}
}
}
3. 包装类
包装类就算将基本类型封装到类中。
自己实现一个包装类:
class IntDemo{
private int num;
public IntDemo(int num){
this.num = num;
}
public int intValue(){
return this.num;
}
}
public class Test{
public static void main(String[] args){
//子类对象向上转型
Object obj = new IntDemo(78);
//向下转型
IntDemo data = (IntDemo) obj;
//取出里面的基本数据类型操作
System.out.println(data.intValue());
}
}
IntDemo实际上就算int类型的包装类,使用intValue()就可以实现将基本类型变为对象的需求。
3.1 分类
a. 对象型包装类(Object的直接子类):Boolean(boolean)、Character(char)
b. 数值型包装类(Number的直接子类),存在数值转换异常:Byte(byte)、Integer(int)、Short(short)、Long(long)、Double(double)、Float(float)
3.2 装箱与拆箱-----基本数据类型与相应包装类的数据处理
装箱:将基本数据类型变为包装类对象,利用每个包装类提供的构造方法实现包装。
Integer num = new Integer(19);
拆箱:将包装类中包装的基本类型值取出来,利用Number类提供的xxValue()方法实现拆箱处理。
int data = num.intValue();
在JDK1.5之后提供了自动拆装箱处理机制。
//自动装箱
Integer num = 34;
//自动拆箱
System.out.println(--num * 2);
包装类对象之间的值比较依然要使用equals()方法
我们下来看一段代码,就知道为什么要这样了。
public class Test{
public static void main(String[] args){
Integer num1 = new Integer(20);
Integer num2 = new Integer(20);
System.out.println(num1 == num2);
System.out.println(num1 == new Integer(20));
System.out.println(num1.equals(new Integer(20)));
}
}
至于原因,在上边String类里已经解释的很清楚了。这里有两个new,没new一次就会在堆空间里开辟一个新空间,所以num1和num2的地址不同。
public class Test{
public static void main(String[] args){
Integer num1 = new Integer(20);
Integer num2 = 20;
Integer num3 = 200;
Integer num4 = 200;
Integer num5 = 56;
Integer num6 = 56;
System.out.println(num1 == num2);
System.out.println(num3 == num4);
System.out.println(num5 == num6);
}
}
为什么会出现上边这种现象呢?
那是因为对于Integer来说,如果它的对象值在-128~127之间的直接赋值,Integer对象在Integer常量池产生,会复用已有对象,这个区间内的Integer值可以直接使用==判断。除此之外,所有的数据都会在堆上产生,并不会复用已有对象。
3.3 字符串与基本类型的转换
- 将字符串转为基本类型(静态方法)
调用各个包装类.parsexx(String str)
例:
public class Test{
public static void main(String[] args){
String str = "123";
System.out.println(Integer.parseInt(str));
}
}
但如果123后边还有字符串类型的字符的话,转换就会出错:
2. 基本类型变为字符串
a. “”+基本类型,会产生垃圾空间
b. 使用Sting类的valueOf(基本类型),此方法不会产生垃圾空间
public class Test{
public static void main(String[] args){
int num = 100;
String str = String.valueOf(num);
System.out.println(str.length());
}
}