1.String

  1. 真正存放值的是String类中的private final byte[] value;
  2. 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;

  1. <a name="JSZFP"></a>
  2. ## 1.String不同的创建方式区别
  3. ![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)
  4. <a name="UYOTP"></a>
  5. # 2.StringBuffer
  6. 1. 继承至**AbstractStringBuilder**,本身**不能被继承**,数据存放在AbstractStringBuilder的byte[] value中,不再是final类型,值存放在堆中,所以可变,
  7. 1. StringBuffer的默认长度为**16**
  8. 1. 当字符串对象 String str=null时,使用append(str)追加对象不会发生错误,但是new StringBuffer(str)则会空指针异常
  9. 1. **多线程安全**
  10. ```java
  11. String d=Null;
  12. StringBuffer aa = new StringBuffer();
  13. aa.append(d); //通过
  14. System.out.println(aa.length());
  15. new StringBuffer(str) //报空指针异常

以上代码不会报错,且长度为4,因为在源码中,当传入的字符串对象为空时,生成一个值为“null”的数组

  1. private AbstractStringBuilder appendNull() {
  2. ensureCapacityInternal(count + 4);
  3. int count = this.count;
  4. byte[] val = this.value;
  5. if (isLatin1()) {
  6. val[count++] = 'n';
  7. val[count++] = 'u';
  8. val[count++] = 'l';
  9. val[count++] = 'l';
  10. } else {
  11. count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
  12. }
  13. this.count = count;
  14. return this;
  15. }

3.StringBuilder

  1. 线程不安全
  2. 继承至AbstractStringBuilder,本身不能被继承,数据存放在AbstractStringBuilder的byte[] value中,不再是final类型,值存放在堆中,所以可变,(与StringBuffer相同)
  3. 单线程时,优先使用,比StringBuffer快

    4.大数

    1. BigIntegerBigDecimal,两者都是在底层以字符串的方式存储数据,所以长度与精度可以无限
    2. BigInteger是大整形数,BigDecimal是高精度浮点数
    3. BigIntegerBigDecimal都需要一个同类型的变量作为另外的参与运算的条件,加减乘除等也必须调用相对应的方法,而不是直接使用计算符号
    4. BigDecimal的除法当除不尽或者为0时,可能抛出异常,可以用重载的除法解决

      1. BigDecimal bigDecimal = new BigDecimal("122.12324546766543211");
      2. //参与运算的条件也必须是相同的类型
      3. BigDecimal bigDecimal1 = new BigDecimal("1.1");
      4. //重载的除法,第二个参数表示保留的精度为被除数的精度,就不会有除不尽的问题了
      5. BigDecimal divide = bigDecimal.divide(bigDecimal1, RoundingMode.CEILING);
      6. System.out.println(divide);

      5.日期

      1.第一代日期类

    5. Date,精确到毫秒

    6. SimpleDateFormat,格式和解析日期的类,创建对象时传入指定的格式字符串,就可将date转为指定的格式了。

      2.第二代日期类

    7. Calendar日历类,抽象类

    8. 使用Calendar.getInstance()获取实例,通过实例对象.get()等方式,获得各个属性

      1. Calendar instance = Calendar.getInstance();
      2. System.out.println(instance.get(Calendar.MONTH));

      3.第三代日期类

      前两代日期类都存在问题:

    9. 日期应该是不可变的

    10. Date年份是从1900开始,月份从0开始
    11. 格式化只对Date有用,Canlendar不行
    12. 线程不安全,且不能处理闰秒(每隔2天,多出1秒)

      LocalDate、LocalTime、LocalDateTime

  4. 时间日期类

  5. 可以格式化日期
    1. //使用静态方法生成当前时间
    2. LocalDateTime now = LocalDateTime.now();
    3. //获取时间和日期值
    4. System.out.println(now.getYear());
    5. System.out.println(now.getMonthValue());
    6. System.out.println(now.getSecond());
    7. //格式化
    8. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH : mm: ss");
    9. //对localdatetime格式化
    10. String format = formatter.format(now);
    11. //格式化后的日期
    12. System.out.println(format);
    可以对日期和时间进行运算
    1. //增加天数
    2. LocalDateTime localDateTime = now.plusDays(2);
    3. //减少天数
    4. LocalDateTime localDateTime1 = now.minusDays(1);

    Instant时间戳

    类似于Date类 ,提供和Date相互转换的方式
    1. //生成instant对象
    2. Instant now = Instant.now();
    3. //instant转date
    4. Date from = Date.from(now);
    5. System.out.println(from);
    6. //date转instant
    7. Instant instant = from.toInstant();
    8. System.out.println(instant);