【字符串本质】:char[ ]数组
分类:1)不可变字符串;2)可变字符串;
——定义不可变字符串:String str = “ABC”; (不可变的主要原因是char数组用final修饰了)
——可变字符串:1)StringBuilder;2)StringBuffer
【字符串的创建】:1)直接赋值: String str = “ABC”;
——变量str指向了方法区常量池中的内容。
2)通过构造器来创建:String str2 = new String(“ABCD”);
——先到方法区常量池中看一下有没有存在该字符串常量,有的话就不会创建新的地址,堆内存中直接引用常量池中的内容,再把str2指向堆内存;如果没有,就会创建一个字符串常量,放到常量池当中。但只要使用了new,就会创建一个对象。
总结:对于通过String构造器来new一个(创建)字符串:
String str = new String(“ABCD”)
步骤:
- 在堆里开辟一个空间,即创建对象0x0001;
- 方法区常量池中没有"ABCD",故在其中创建一个"ABCD常量";
- 堆内存中的对象引用方法区中的常量值
- 把堆中的地址赋值给str
——面试题:创建了两个对象!:一个是方法区常量池中的“ABCD”对象,另一个是new调用构造器在堆内存中创建的对象。
比较两个字符串是否相等:
1) == :比较内存地址;
2)object中定义的equal()方法——str1.equal(str2) :逐个判断内部字符是否相等。
一、字符串首字母大写:
字符串转为大写:str.toUpperCase();
字符串转为小写:str.toLowerCase();
截取字符串的一部分:str.substring(beginIndex,endIndex);
获取字符串中下标为 i 的字符:str.charAt(i); :从0开始算。
获取子字符串str2在字符串str1中第一次出现的位置:str1.indexof(str2)
获取子字符串str2在字符串str1中最后一次出现的位置:str1.lastIndexof(str2)
字符串比较:str1.equals(str2)
忽略字符串大小写的比较:str1.equalsIgnoreCase(str2)
字符串反转:str.reverse()
//把单词首字母变成大写
/*思路:(1)获取第一个字母;(2)把获取的第一个字母变成大写;
(3)将后面的字母与其拼接
*/
import java.util.*;
public class StringDemo
{
public static void main(String[] args)
{
String name = "mysql";
String res = name.substring(0,1);//顾名思义,即子字符串:从字符串的第0到第1个字母截取。
res = res.toUpperCase();//转为大写
System.out.println(res);//输出大写的首字母
String last = name.substring(1);//即截取第1个字符以后的字符
System.out.println(res+last);//拼接并输出整个字符串
}
}
二、判断字符串是否为空
空字符串:String str = null;表示还没有初始化,没有分配内存空间
String str = “”;已经创建对象,分配了内存,内容为空。
——运用replace()方法来替换字符串中的空格。
——运用trim()方法可去除字符串首尾空格。
import java.util.*;
public class StringDemo
{
public static void main(String[] args)
{
//1、判断字符串是否为空
String str1 = "";
String str2 = null;
String str3 = " ";
if(str1 !=null && !"".equals(str1))//equals只比较内容,
{
System.out.println("不为空");//!"":不为空
}else
{
System.out.println("为空");//null和""为空
}
//2、去除字符串首尾空格
String s = " my sql ";
System.out.println("去除首尾空格前长度:" + s.length());
s = s.trim();//可以去掉首尾空格,无法去掉中间的
System.out.println("去除首尾空格后长度:" + s.length());
//3、去掉所有空格
s = s.replace(" ","");//用一个新字符来代替老字符:replace(oldchar,newchar)
System.out.println("去除所有空格后:" + s);
System.out.println("去除所有空格后长度:" + s.length());
}
}
运行结果:
判断字符串是否为空的程序可整理为如下:
import java.util.*;
public class StringDemo
{
/*
*设计一个方法,
*给一个字符串判断是否为空,
*空则返回false,不空就true
*/
static boolean hasLength(String str)//写一个方法,static方法里只能调用static方法
{
/*
if(str !=null && !"".equals(str.trim()))
//equals只比较内容,用trim()去掉字符串首尾空格后,与非空字符串!""比较
{
return true;//不为空
}
//一个方法当中有return后,所在方法会立即停止执行,无需else
return false;//为空
*/
//或者以上方法体内干脆改为“
return str !=null && !"".equals(str.trim());
}
public static void main(String[] args)
{
//判断字符串是否为空
String str1 = "";
String str2 = null;
String str3 = " ";
System.out.println(hasLength(str3));
}
}
将上述程序封装为类,便于使用:
(1)工具类:
package 字符串;
public class StringUtils {//Utils代表工具类
/*
*设计一个方法,
*给一个字符串判断是否为空,
*空则返回false,不空就true
*/
//私有化工具类,不让外界来new这个类的对象
private StringUtils() {
}
static boolean hasLength(String str)//写一个方法,static方法里只能调用static方法
{
return str !=null && !"".equals(str.trim());
}
}
(2)调用同一个包中的工具类:
package 字符串;
public class StringDemo {
public static void main(String[] args) {
String str1 = "asd";
System.out.println(StringUtils.hasLength(str1));//空为false,非空为true
}
}
三、字符串编译优化
带“”的都是直接量,编译时直接会优化好,拼接到一起。
public class ListError
{
public static void main(String[] args)
{
String a = "ABCD";//基本类型,数值类型
String b = "A"+ "B"+"C"+"D";
String c ="AB"+"CD";
String d = new String("ABCD");
String temp ="AB";
String e = temp +"CD";
System.out.println(a == b);//输出true:
//对于b,带“”的都是直接量,编译时直接会优化好,变成“ABCD”
System.out.println(a == c);//输出true:同理。
System.out.println(a == d);//输出false:
//d的地址指向堆内存,a的地址指向方法区常量池,肯定不相等。
System.out.println(a == e);//输出false
}
}
四、可变字符串StringBuffer和StringBuilder类
(1)StringBuilder(非线程安全,因为没有加锁!但是效率更高)
——字符串可变原因:本质是char类型数组,容量默认16,用capacity传入,超过16会扩容,第一次扩容变成16*2+2
import java.util.*;
public class StringBuilderDemo
{
public static void main(String[] args)
{
StringBuilder sb = new StringBuilder();//创建可变字符串,初始容量为16,超过会自动扩容
//StringBuilder sb1= new StringBuilder();
//输出可变字符串的容量
System.out.println(sb.capacity());
sb.append("abcdefg").append(123);//其内部是Object类型,可放入任意类型
System.out.println(sb);
sb.append(9876543);
System.out.println(sb);
System.out.println(sb.capacity());//超过16个字符,自动扩容到16*2+2=34
//删除字符串中指定下标的字符
sb.deleteCharAt(2);
System.out.println(sb);
//可变字符串转不可变
String s = sb.toString();//toString是把对象转为字符串形式输出,sb对象内部就是字符串
//字符串反转
System.out.println(sb.reverse());
}
}
(2)StringBuffer(加了锁,线程安全,但是synchronized导致效率变低)