既然说字符串就是一个对象,那么有两个问题需要解释
只要是字符串,就是一个对象
字符串就是一个java.lang.String的对象,里面也可以包含三个部分
成员变量,成员方法,构造方法
1.对象肯定有一个类与之对应,那么字符串对应的类是谁: String
2.为什么String这个类,不需要导包就能直接使用
a.要使用的目标类和当前类位于同一个包下
b.要使用的目标类。位于java.lang包下,但是不包含子包内容
3.既然字符串是对象,为什么直接打印出来就是内容呢?(我们都知道栈中的变量 保存的是堆中的地址值)
打印Println方法逻辑:
a.如果是字符串类型,那么直接显示内容
b.如果不是字符串类型,那么就想办法转换成为字符串,然后在显示
一般的对象都是使用"类型信息+@+地址值"作为字符串内容的
Student stu3=new Student();
System.out.println(stu3);
字符串常见的2+1 种方式(两种构造方法一种直接赋值)
package com.xgg.test;
/*
* 字符串常见的2+1 种方式(两种构造方法一种直接赋值)
* 常用的2种构造方法
* public String (char [] array);参数是一个字符串数组,根据字符数组的内容来创建一个字符串
* public String (char [] array,int offset,int count) 根据字符数组的一部分来创建一个字符串
* 参数offset代表一个数组当中的起始索引,从0 开始
* 参数count 代表取用多少个字符
*
* 直接赋值双引号也是一个字符串对象
* String str ="Hello";
*/
public class DemoStringInit {
public static void main(String[] args) {
// TODO Auto-generated method stub
char [] array={'H','e','l','l','o'};
//根据字符数组来创建字符串
//类名称 对象名 = new 类名称(构造方法)
String str=new String(array);
System.out.println(str);//Hello
System.out.println("=================");//Hello
//根据字符数组的一部分来创建一个字符串
String str1=new String(array,2,2);
System.out.println(str1);//ll
//如果指定的索引或者个数超出了合理范围,那么将会发生索引越界异常,错误写法
//String str2=new String(array,8,8);
//直接赋值
String str3 ="Hello";
System.out.println(str3);//Hello
}
}
字符串池的概念
package com.xgg.test;
/*
* 字符串是最常用的对象,所以在程序当中往往会出现很多个重复的字符串
* 为了节省内存,所以引入了“字符串池”的设计,可以重复利用字符串
*
* 关于字符串池的几点描述
* 1.字符串池是位于堆内存当中的一小块空间,用来保存若干个字符串的地址值
* 2.字符串池当中绝对不会出现重复的字符串对应的地址,保证字符串不重复
* 3.凡是直接双引号的字符串默认都在池中,而new出来的字符串默认不在池中
*
* 对于基本类型来说 == 是进行数据类容的比较,但是对于引用类型来说==是进行地址值的相同比较
* 如果是两个对象,那么地址值必然不同,如果地址值相同,那么必然是同一个对象
*/
public class DemoStringPool {
public static void main(String[] args) {
//字符串池当中绝对不会出现重复的字符串对应的地址,保证字符串不重复
// 凡是直接双引号的字符串默认都在池中,
String str1="Hello";
String str2="Hello";
//对于基本类型来说 == 是进行数据类容的比较,但是对于引用类型来说==是进行地址值的相同比较
System.out.println(str1==str2);//true
System.out.println("===================");
//而new出来的字符串默认不在池中
char [] array= {'H','e','l','l','o'};
String str3=new String(array);
String str4=new String(array);
System.out.println(str3);//Hello
System.out.println(str1==str3);//false 地址值不同
System.out.println(str3==str4);//false 地址值不同
}
}
这里我们需要注意的只有,当你直接使用双引号创建的字符串,它首先会在堆中开辟一个空间,地址为0x111,而这个地址会保存在字符串池当中,当再次用双引号创建相同数据的内容时,不会重新在堆中重新开辟一个空间,而是通过字符串池里保存的0x111这个地址去找到 堆中开辟空间的0x111这个地址的对象。而当你new 一个String的时候,地址不在字符串池中,尽管内容相同,但是地址不同,用==号 ,还是false;
字符串对象在内存当中一旦被创建,那么内容不可以被改变
package com.xgg.test;
/*
*字符串对象在内存当中一旦被创建,那么内容不可以被改变
*/
public class DemoStringEternal {
public static void main(String[] args) {
// TODO Auto-generated method stub
String str="Hello";
System.out.println(str);//Hello
str="World";
System.out.println(str);//World
String str1="Study";
str1+="Java";
System.out.println(str1);//StudyJava
}
}
如下图,详细介绍不介绍了,自己看 下面2 图
每当你感觉字符串变了的时候一定是创建了新的字符串
如何进行字符串内容的比较
package com.xgg.test;
/*
* 如何进行字符串内容的比较
* 如果使用==进行比较,那么进行的就是地址值的相同的判断
* 如果希望进行字符串内容的比较,则需要使用String当中的成员方法
* public boolean equals(Object obj)进行字符串内容的比较,严格区分大小写,
* 参数obj就是另一个对象(跟谁比)
* Object 也是一个类型,可以接收任何类型的数据
* 小技巧: 如果equals方法需要比较的两个字符串当中,有一个常量,那么常量放在equals的左边,
* 因为左边为null时 会报错 java.lang.NullPointerException 空指针异常
*
* public boolean equalsIgnoreCase(String str),进行字符串的内容比较,不区分大小写
*
* 直接写上的双引号就是字符串对象,所以用双引号点也能直接调用方法
*/
public class DemoStringEquals {
public static void main(String[] args) {
char [] array= {'a','b','c'};
String str1=new String(array);
String str2="abc";
String str3="Abc";
System.out.println(str1=str2);//false
//进行内容比较使用equlas严格区分大小写
System.out.println(str1.equals(str2));//true
//equals具有对称性 左右两边相换没关系
System.out.println(str2.equals(str1));//true
System.out.println(str1.equals(str3));//false
//进行内容比较使用equalsIgnoreCase不区分大小写
System.out.println(str1.equalsIgnoreCase(str3));//true
//
String str4=null;
String str5="xyz";
System.out.println(str4.equals("abc"));//报错 java.lang.NullPointerException
//所以有一个常量,那么常量放在equals的左边
System.out.println("abc".equals(str4));//false
}
}
将指定字符串的值进行替换操作
package com.xgg.test;
/*
* 如果希望将指定字符串的值进行替换操作,需要使用
* public String replace(CharSequence oldstr,CharSequence newstr)
* 将字符串当中出现的所有的oldstr部分替换成为指定的newstr
* 参数oldstr代表需要被替换的老字符串部分
* 参数newstr代表需要替换的新字符串部分
* 参数类型CharSequence现阶段就可以简单的认为就是String字符串 其实String类实现了CharSequence
* 注意字符串的内容是不会发生改变的,所以replace方法的返回值结果是一个新的字符串
*/
public class DemoStringReplace {
public static void main(String[] args) {
// TODO Auto-generated method stub
String str1="How do you do";
String str2 =str1.replace("o", "*");
System.out.println(str2);//H*w d* y*u d*
//注意字符串的内容是不会发生改变的,所以replace方法的返回值结果是一个新的字符串
System.out.println(str1);//How do you do
String str3="LOL打的这么菜,你大爷的,会不会玩啊!";
String str4=str3.replace("你大爷", "***");
System.out.println(str4);
}
}
将字符串按照指定的标记切分成若干段
package com.xgg.String.test;
/*
* 如果希望将字符串按照指定的标记切分成若干段,那么可以使用方法:
* public String[] split(String regex)
* 注意事项
* 现阶段强烈推荐不要使用英文句点作为分割的标记
* 因为英文句点在正则表达式中有特殊的含义
* 而参数regex其实就是一个正则表达式
* 如果一定要使用英文句点进行分割,切割的标记使用"\\."(现阶段的固定写法)
*/
public class DemoStringSplit {
public static void main(String[] args) {
// TODO Auto-generated method stub
String str="AAA,BBB,CCC,DD";
String [] array=str.split(",");
System.out.println("数组的长度:"+array.length);//4
for(int i=0;i<array.length;i++) {
System.out.println(array[i]);
}
System.out.println("==============");
String str1="aaa.bbb.ccc.ddd";
String [] array1=str1.split(".");
System.out.println("数组的长度:"+array1.length);//长度为0
for(int i=0;i<array1.length;i++) {
System.out.println(array1[i]);
}
}
}