String
String类是不可变类
String对象赋值后不能再修改,如果对字符串进行修改将会创建新的对象。
双引号赋值字符串时String s="abc"
,在编译期会将其放到方法区中的字符串常量池中,在运行时对字符串相加减会放到堆中(放之前会先验证方法区中是否含有相同的字符串,如果存在则把地址返回,如果不存在则先将字符串常量放到池中,然后再返回该对象的地址)。
String s="abc"
与String s=new String("abc")
public class StringTest01 {
public static void main(String[] args) {
String s1="abc";
String s2="abc";
String s3=new String("abc");
System.out.println("s1==s2,"+(s1==s2)); // true
System.out.println("s2==s3,"+(s2==s3)); // false
System.out.println("s2 equals s3,"+(s2.equals(s3))); //true
}
}
- 双引号赋值的字符串常量首先会在常量池中查找,如果存在就不再分配,如果不存在就分配。常量池中的数据是在编译期赋值的,即生成class文件时就把它放到常量池中,所以s1、s2都指向常量池中的同一个字符串“abc”。
- s3采用new的方式,new时存在双引号,所以也会首先在常量池中查找“abc”,如果存在就不再分配,如果不存在就分配。而new关键字会在堆中分配内存,所以堆中会创建一个对象并指向方法区中的“abc”。
- s1、s2与s3比较时必须用equals(String已经对equals方法进行了覆盖)
面试题
String s1=new String("cry");
String s2=new String("cry");
以上代码会创建几个对象? 三个
堆中2个,常量池中1个。
使用String时,不建议使用new关键字,因为new会创建两个对象
注意:堆区中是运行期分配的,常量池是编译期分配的。
String常用方法
- endsWith:判断字符串是否以指定的后缀结束
- startsWith:判断字符串是否以指定的前缀开始
- equals:字符串相等比较,不忽略大小写
- equalsIgnoreCase:字符串相等比较,忽略大小写
- indexOf:取得指定字符在字符串的位置
- lastIndexOf:返回最后一次字符串出现的位置
- length:返回字符串长度
- replaceAll:替换字符串中指定的内容
- split:根据指定的表达式拆分字符串
- substring:截字符
- trim:去掉前后空格
- valueOf:将其他类型转换成字符串
注意事项
String是不可变对象,在进行多个字符串衔接时会形成多个对象,容易造成内存溢出,存在大量的对象相加减时不建议使用String,建议使用StringBuffer或StringBulider。
StringBuffer和StringBuilder
StringBuffer
StringBuffer称为字符串缓冲区,工作原理为:预先申请一块内存存放字符序列,如果字符序列满了会重新改变缓存区的大小以容纳更多的字符序列。因此,StringBuffer是可变对象。
public class StringBufferTest {
public static void main(String[] args) {
StringBuffer stringBuffer=new StringBuffer();
for (int i = 0; i <100; i++) {
stringBuffer.append(i);
}
System.out.println(stringBuffer);
}
}
StringBuilder
用法与StringBuffer相同,StringBuilder和StringBuffer的区别在于:StringBuffer中所有方法都是同步的,是线程安全的,但速度慢。
- StringBuilder的速度快,但不是线程安全的。
- StringBuffer/StringBuilder可以看做可变长度字符串。
- StringBuffer/StringBuilder初始化容量16
- StringBuffer/StringBuilder是完成字符串拼接操作的,方法名:append
- StringBuffer是线程安全的。StringBuilder是非线程安全的。
- 频繁进行字符串拼接不建议使用“+”
包装类
基本类型的包装类主要提供了更多的实用操作,更容易处理基本类型。所有的包装类都是final修饰的,不能创建子类,包装类都是不可变对象。
基本类型 | 包装类 |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
boolean | Boolean |
char | Character |
除了boolean和character外,其他的包装类都有valueOf和parseXXX方法,xxxValue方法也比较常用。 |
Integer.valueOf()
Integer.parseInt("123")
Integer.parseInt("中文") //报错,NumberFormatException
JDK5.0之后,提供了自动装箱和拆箱。自动装箱即自动将基础类型转换为对象,自动拆箱即自动将对象转换为基础类型。
日期、数字类
- 常用的日期类有:
java.text.SimpleDateFormat;
java.util.Calendar;
java.util.Date;
public class DateTest {
public static void main(String[] args) throws Exception{
//取得系统当前时间 Sun May 08 19:41:43 CST 2022
Date today=new Date();
//格式化日期 2022-05-08 19:41:43
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Calendar cal=Calendar.getInstance();
//相互转换
Date d=new SimpleDateFormat("yyyy.MM.dd").parse("2022.04.08");
cal.setTime(d); //使用给的日期设置日历时间
System.out.println(cal.get(Calendar.DAY_OF_MONTH));
}
}
- 数字类
java.math.BigDecimal; // 数字格式化
java.text.DecimalFormat; // 精确计算,多用于财务数据
Enum
- 枚举是一种引用数据类型,使用的是enum关键字;
- 枚举变量之间用逗号隔开,且枚举变量最好用大写,多个单词之间使用“_"隔开(INT_SUM);
- 只需要类名.变量名就可以召唤枚举变量了,跟使用静态变量一样。
public enum Season {
SPRING,SUMMER,AUTUMN,WINTER
}
在定义有限的序列如星期、性别时,一般会通过静态变量的形式进行定义,这种形式在添加功能时不利于扩展和维护,枚举的实现可以简化这些操作。