吴波老师课堂笔记:
String类:
String是一个类,属于引用数据类型 默认为null , JVM对String类做了一个特殊的处理, 可以把String像基本数据类型一样使用使用
一 String类的两种实例化方式
1 直接赋值 String str=”hello”;
2 通过 构造方法赋值 String str=new String(“hello”);
首先要了解两种实例化方式的区别 先做一个字符串比较的案例 观察一样
范例: 实现字符串比较
public static void main(String[] args) {
String str="hello";
String str1=new String("hello");
String str3=str1;
System.out.println(str1==str); // false
System.out.println(str==str3); //false
System.out.println(str3==str); //false } |
通过分析可以发现,== 比较的是内存的地址, 如果想要比较字符串的内容,则可以使用String类为用户提供的一个方法 equals()方法
而equals()方法实际上是Object类提供的,一下为Object类提供的equals方法代码
public boolean equals(Object obj) { return (this == obj); } |
默认的equals()方法比较的还是地址,如果想要比较内容则 比较的类需要覆写equals方法,而String类正是覆写了Object类中的equals方法
public boolean equals(Object anObject) { if (this == anObject) { // 当前自己对象和传进来的对象进行比较 return true; } if (anObject instanceof String) { // 和我是同一个类型的 String anotherString = (String)anObject; 所有的类都是Object类的子类 int n = value.length; if (n == anotherString.value.length) { char v1[] = value; char v2[] = anotherString.value; int i = 0; while (n-- != 0) { if (v1[i] != v2[i]) return false; i++; } return true; } } return false; }
|
在程序中没有数据类型为String的概念,String类里面实际上操作的是字符数组,由于是字符串数组则字符串的内容不可改变
由于== 比较的是地址,所以在进行字符串内容的判断上使用equals()方法
public static void main(String[] args) { String str="hello"; String str1=new String("hello");
String str3=str1;
System.out.println(str1.equals(str)); // true
System.out.println(str.equals(str3)); //true
System.out.println(str3.equals(str1)); //true } |
观察字符串常量池概念
public class StringDemo {
public static void main(String[] args) { String str1="hello";
String str2="hello";
String str3="hello";
System.out.println(str1==str2); //true
System.out.println(str2==str3); //true
System.out.println(str3==str1); //true } } |
通过以上的代码分析,发现结果都为true ,在String 直接赋值的情况下,则存在字符串常量池,赋值之后 String的内容会自动进入到字符串常量池 接下来的对象在进行赋值的时候会先去判断字符串常量池中是否存在相同的内容,如果存在则不创建直接引用
两种实例化方式的区别?
1 直接赋值 赋值的内容会自动进入到字符串常量池, 只开辟一块空间
2 通过构造方法赋值 : 其中一块是垃圾空间,不会自动进入到字符串常量池, 开辟了两块空间
如果想要 通过构造方法实例化的String进入到字符串常量池 则可以手动调用intern方法
String str2=new String("hello").intern(); |
字符串内容 就是String类的匿名对象 。
String类的常用方法(掌握常用方法)
构造方法:
1 public String(char value[]); 要求给定一个char数组 把char数组变为字符串
public static void main(String[] args) {
char[] strarry=new char[] {'h','e','l','l','o'};
System.out.println(new String(strarry)); } |
2 public String(char value[], int offset, int count) 根据指定长度转换字符数组为字符串
3 public String(byte bytes[]) 把byte数组变为字符串
public static void main(String[] args) {
byte[] arry="hello".getBytes(); //把字符串变为字节数组
for(int i=0;i<arry.length;i++) {
System.out.println(arry[i]); }
System.out.println(new String(arry));
} |
普通方法:
1 获取字符串的长度
public int length();
2 判断字符串的长度是否为空
public boolean isEmpty();
3 给定指定索引 反回指定索引的字符
给定一个字符串 去掉字符串的左右空格
public char charAt(int index)
把给定的字符串转换为字节数组
4public byte[] getBytes(String charsetName);
5 字符串内容比较
public boolean equals(Object anObject);
6 判断字符串是否以某个字符串开始
public boolean startsWith(String prefix)
6 判断字符串是否以某个字符串结尾
public boolean endsWith(String suffix);
7给定指定字符串,反回该字符串的下标位置, 如果找不到该字符串反回-1
public int indexOf(String ch);
8 查找指定字符串,从后往前找 反回该字符的下标,找不到返回-1
public int lastIndexOf(String str);
9 截取字符串
public String substring(int beginIndex);
10 按照范围截取字符缓
public String substring(int beginIndex, int endIndex);
练习: 截取身份证号中的生日
110211198802066418
String str="110211198802066418";
System.out.println(str.substring(6,14)); |
练习:给定一个图片的文件名称 张三.jpg 小帅ssdsds.via 隔壁老王.jpg
public static void main(String[] args) {
String str="张三ddd.jpg"; int index=str.lastIndexOf("."); System.out.println(str.substring(0,index));
} |
12把字符串变为字符数组
public char[] toCharArray();
public static void main(String[] args) {
char[] array="hello world".toCharArray();
for(int i=0;i<array.length;i++) {
System.out.println(array[i]); }
} |
练习 给定一个字符串 把小写字母变为大写字母
public static void main(String[] args) { char[] array="hello world".toCharArray(); //字符串变为字符数组
for(int i=0;i<array.length;i++) {
array[i]-=32; //编码减少32位 }
//将字符数组变为字符串
String str=new String(array); //通过构造方法把字符数组变为字符串
System.out.println(str); //直接输出转换过后的字符串 } |
练习: 判断给定的字符串 是否全部由数字组成(0 ~9)
public static void main(String[] args) { String str="hello world";
String str1="123";
System.out.println(isNumber(str)); //false
System.out.println(isNumber(str1)); //true }
public static boolean isNumber(String str) {
char[] arry=str.toCharArray(); //1 把字符串变为字符数组
for(int i=0;i<arry.length;i++) {
if(arry[i]<'0'||arry[i]>'9') {
return false; } } return true; } |
练习: 实现字符串的反转
Hello olleh
h e l l o int l=0 ,r =arry.length-1;
L r while(l<r){交换}
package org.string;
public class StringDemo2 {
public static void main(String[] args) { String str=reString("hello"); System.out.println(str); }
public static String reString(String str) {
// 1 转换为字符数组
char[] array=str.toCharArray();
//2 定义两个下标 l r
int l=0, r=array.length-1;
while(l<r) {
swap(array,l++,r--); }
return new String(array); }
/** * 进行内容的交换 * @param array * @param left * @param right */ public static void swap(char[] array, int left, int right) {
char temp=array[left];
array[left]=array[right];
array[right]=temp; } }
|
1 左右的空格要去掉 不许使用trim(); charAt();
2 每个单词中间的空格去掉只剩一个
大小写转换
1 把字符串变为小写字母
public String toLowerCase() ;
2 字符串变为大写字母
public String toUpperCase() ;
public static void main(String[] args) { String str="hello java"; System.out.println(str.toUpperCase()); String str1="HELLO JAVA"; System.out.println(str.toLowerCase());
} |
去掉空格:
去掉左右空格
public String trim();
public static void main(String[] args) { String str=" babalala "; System.out.println("【"+str+"】"); System.out.println("【"+str.trim()+"】");
} |
public native String intern(); ? 谁实现的 native关键字代表调用本地方法库
JVM 实现 多个版本 linux windows unix macos 最终要牵扯到内存 本地系统函数去分配
字符串连接:
字符串连接, String str+=hello 没有区别
public String concat(String str);
忽略大小写比较
equalsIgnoreCase(String str);
字符串的分割:
主要针对正则表达式的支持,表达语法
public String[] split(String regex);(了解)
public static void main(String[] args) {
String str="hello,world,java,hadoop";
String [] array=str.split(",");
for(int i=0;i<array.length;i++) {
System.out.print(array[i]+"、"); } } |
总结:
String类特点:
1 两种实例化方式的区别?
直接赋值 String str=”hello”
构造方法赋值 String str=new String(“hello”)
直接赋值 只开辟一块空间,会自动进入到字符串常量池
构造方法赋值: 开辟了两个空间其中一块是垃圾空间,不会自动进入到字符串常量池 但是可以通过调用intern方法手动进入常量池
2 字符串的常量就为String类的匿名对象 “hello”.equals()方法验证
3 字符串内容一旦声明则不可改变 ,改变只是String 类 的引用(原因底层使用的数组,数组的长度不可改变)
Final 类 不能被继承 变量 不能被修改(常量) 方法(不能被覆写)
面试题:以上内容为面试题
作业:
验证 email 是否合法
给定的字符串 必须存在 . 和 @ @必须在 .之前 就合法
public static void fun2(String str) {
int index1 = str.indexOf("@");
int index2 = str.indexOf(".");
if (index1 != -1 && index2 != -1 && index1 < index2) {
System.out.println("email 是合法的。");
} else
System.out.println("email 是不合法的。");
}
单词反转:
思路 the sky is blue
l r
StringBuilder blue+” ”is+” ”+sky+” ”+”the” ;
String 是引用类型,String str1 = new String 和 String str= “ abc”的区别: new 会新申请一片内存空间。
== ------------------- 比较的是内存的地址。
boolean equals()------------比较的是字符串是否相等。
1.String 类方法的使用
需求:
已知String str = "this is a text";
1.将str中的单词单独获取出来
2.将str中的text替换为practice
3.在text前面插入一个easy
4.将每个单词的首字母改为大写
public static void main(String[] args) {
String newstr = " ";// 用来放拆分后,重组并更新的str
String str = "this is a text";
String[] arr = str.split(" ");//遇空格切割单词,放到数组中
for (String s : arr) {
System.out.println(s); //输出各个单词
char ch = s.charAt(0); //提取每个单词第一个字母
char newch = (char) (ch - 32); //转换成大写字母
//这个替换实现不准确
String s1 = s.replace(s.charAt(1), newch); //用大写替换每个单词第一个字母
String s2 = s1.toString();//返回此对象本身,(本身已经是字符串)
s2 = s2 + " ";//在每个单词后加空格
newstr += s2; //单词+空格之后 连成一个带有空格的字符串
}
System.out.println(newstr);
//替换
String str1 = str.replace("text", "practice");
System.out.println(str1);
//插入
//要修改字符串时,只能用StringBuffer
StringBuffer strBuf = new StringBuffer(str);
strBuf.insert(strBuf.length() - "text".length(), "easy"); //offset,str
System.out.println(strBuf);
}
上面的实现替换每个单词首字母方法不对,最后一个单词的最后一个t也变成了T,待解。
offset ---- 偏移量,eg:offset=4,就是在当前字符串的长度为4之后,进行插入操作。
反转字符串:经典反转方法
public static String fun2(String str) {
char[] ch = str.toCharArray();
int left = 0;
int right = ch.length - 1;
while (left < right) {
char temp = ch[left];
ch[left] = ch[right];
ch[right] = temp;
left++;
right--;
}
String string = new String(ch);
return string;
}
StringBuffer类
字符串缓冲区:使用缓冲区操作字符串要比直接操作字符串效率高
String类一旦创建对象,它的值不允许修改,因为
StringBuffer可以修改。
public static void main(String[] args) {
StringBuffer sb1 = new StringBuffer("love");
StringBuffer sb2 = sb1.append("hello");
//区别于String类:面盆理论
System.out.println(sb1);
System.out.println(sb2);
System.out.println(sb1 == sb2); // true
sb1.append("java");
System.out.println(sb1);
System.out.println(sb2);
//方法链
sb1.append("java").append("java").append("java").append("java");
System.out.println(sb1);
System.out.println(sb2);
System.out.println(sb1 == sb2); //true
//插入
sb1.insert(2, "hhhhhhhh");
System.out.println(sb1);
}
sb1 和sb2 的值相等,因为对sb1操作,sb1 在内存中的值也随之改变了。