1.String
- 真正存放值的是String类中的private final byte[] value;
- value地址不可更改,但是因为是一个数组,所以其内部值其实是可以更改的,但是因为String并没有提供让其数组内部元素更改的方法,所以String整体仍然是不可变的 :::danger 字符串常量相加,看池,变量相加,是在堆里面 ::: ```java //会被编译器在底层优化为String str=”ab”; 实际上只创建了一个对象 String str=”a”+”b”;
String a = “a”; String b = “b”; //ab直接指向常量池,c是通过创建一个stringbuilder对象,随后通过append将a,b添加进去,再new了 //一个String返回,所以c是指向堆的,堆中value数组指向常量池 String c = a + b;
<a name="JSZFP"></a>
## 1.String不同的创建方式区别
![image.png](https://cdn.nlark.com/yuque/0/2022/png/25654866/1652066006907-7902396e-ca17-4b3d-bd0d-0d5851b81d3c.png#clientId=udda16ec2-27c9-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=370&id=u13d0cc22&margin=%5Bobject%20Object%5D&name=image.png&originHeight=620&originWidth=1165&originalType=binary&ratio=1&rotation=0&showTitle=false&size=272909&status=done&style=none&taskId=uf44bdb19-15e9-4b86-8388-40736a5c17c&title=&width=695)
<a name="UYOTP"></a>
# 2.StringBuffer
1. 继承至**AbstractStringBuilder**,本身**不能被继承**,数据存放在AbstractStringBuilder的byte[] value中,不再是final类型,值存放在堆中,所以可变,
1. StringBuffer的默认长度为**16**
1. 当字符串对象 String str=null时,使用append(str)追加对象不会发生错误,但是new StringBuffer(str)则会空指针异常
1. **多线程安全**
```java
String d=Null;
StringBuffer aa = new StringBuffer();
aa.append(d); //通过
System.out.println(aa.length());
new StringBuffer(str) //报空指针异常
以上代码不会报错,且长度为4,因为在源码中,当传入的字符串对象为空时,生成一个值为“null”的数组
private AbstractStringBuilder appendNull() {
ensureCapacityInternal(count + 4);
int count = this.count;
byte[] val = this.value;
if (isLatin1()) {
val[count++] = 'n';
val[count++] = 'u';
val[count++] = 'l';
val[count++] = 'l';
} else {
count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
}
this.count = count;
return this;
}
3.StringBuilder
- 线程不安全
- 继承至AbstractStringBuilder,本身不能被继承,数据存放在AbstractStringBuilder的byte[] value中,不再是final类型,值存放在堆中,所以可变,(与StringBuffer相同)
-
4.大数
- BigInteger和BigDecimal,两者都是在底层以字符串的方式存储数据,所以长度与精度可以无限
- BigInteger是大整形数,BigDecimal是高精度浮点数
- BigInteger和BigDecimal都需要一个同类型的变量作为另外的参与运算的条件,加减乘除等也必须调用相对应的方法,而不是直接使用计算符号
BigDecimal的除法当除不尽或者为0时,可能抛出异常,可以用重载的除法解决
BigDecimal bigDecimal = new BigDecimal("122.12324546766543211");
//参与运算的条件也必须是相同的类型
BigDecimal bigDecimal1 = new BigDecimal("1.1");
//重载的除法,第二个参数表示保留的精度为被除数的精度,就不会有除不尽的问题了
BigDecimal divide = bigDecimal.divide(bigDecimal1, RoundingMode.CEILING);
System.out.println(divide);
5.日期
1.第一代日期类
Date,精确到毫秒
SimpleDateFormat,格式和解析日期的类,创建对象时传入指定的格式字符串,就可将date转为指定的格式了。
2.第二代日期类
Calendar日历类,抽象类
使用Calendar.getInstance()获取实例,通过实例对象.get()等方式,获得各个属性
Calendar instance = Calendar.getInstance();
System.out.println(instance.get(Calendar.MONTH));
3.第三代日期类
前两代日期类都存在问题:
日期应该是不可变的
- Date年份是从1900开始,月份从0开始
- 格式化只对Date有用,Canlendar不行
- 线程不安全,且不能处理闰秒(每隔2天,多出1秒)
LocalDate、LocalTime、LocalDateTime
时间日期类
- 可以格式化日期
可以对日期和时间进行运算//使用静态方法生成当前时间
LocalDateTime now = LocalDateTime.now();
//获取时间和日期值
System.out.println(now.getYear());
System.out.println(now.getMonthValue());
System.out.println(now.getSecond());
//格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH : mm: ss");
//对localdatetime格式化
String format = formatter.format(now);
//格式化后的日期
System.out.println(format);
//增加天数
LocalDateTime localDateTime = now.plusDays(2);
//减少天数
LocalDateTime localDateTime1 = now.minusDays(1);
Instant时间戳
类似于Date类 ,提供和Date相互转换的方式//生成instant对象
Instant now = Instant.now();
//instant转date
Date from = Date.from(now);
System.out.println(from);
//date转instant
Instant instant = from.toInstant();
System.out.println(instant);