String相关知识(字符串常量池、String不可变性、String拼接、String和StringBuilder和StringBuffer区别、常用时间API、比较器)

字符串常量池

深入了解字符串常量池
字符串常量池中存在一个StringTable,是一个HashTable,key是根据String实例的值和长度计算生成的hash,value存放了对String实例的引用,注意,是引用,而不是实例,StringTable中只有引用

String的不可变性

很多人只答String的存值是用private final byte[] value,这样是不够的,因为只是引用型变量value指向的数组首地址被固定,不允许它指向其他地址,数组内的内容可以变呀。所以应当加上下述:

  • 首先,byte数组是private的,并且 String类没有对外提供修改这个数组的方法,所以它初始化之后外界没有有效的手段去改变它
  • 其次,String类被final修饰的,也就是不可继承,避免被他人继承后破坏
  • 最重要的是因为Java作者在String的所有方法里面,都很小心地避免去修改了byte数组中的数据,涉及到对byte数组中数据进行修改的操作全部都会重新创建一个String对象

为什么String设计成不可变的

  • 从内存角度,对于某个常量池中已有的字符串,多个引用变量指向它时,如果是可变的,改变一个就会导致其他引用值的错误,这是很危险的
  • String不可变保证了hashcode的相同,因此对于某些集合比如HashSet、HashMap等就可以直接比较hashcode而不是调用equals方法
  • 方便其他类的使用,如Set等
  • 不可变保证了线程安全,令String可以在多个线程间自由共享
    String常用方法
    String和StringBuilder和StringBuffer区别

String拼接

public class Test {
    public static void main(String[] args) {
        String s1 = "s1";
        String s2 = "s2";
        String s3 = "s1s2";
        String s4 = "s1" + "s2";
        String s5 = s1 + "s2";
        String s6 = "s1" + s2;
        System.out.println(s3 == s4);  // true
        System.out.println(s3 == s5);  // false
        System.out.println(s3 == s6);  // false
        System.out.println(s5 == s6);  // false
    }
}

intern案例

//案例1
public class Test {
    public static void main(String[] args) {
        String s1 = "s1";
        String s2 = s1 + "s2";
        String s3 = "s1s2";
        System.out.println(s2 == s2.intern());
    }
}
//案例2
public class Test {
    public static void main(String[] args) {
        String s1 = "s1";
        String s2 = s1 + "s2";
        System.out.println(s2 == s2.intern());
        String s3 = "s1s2";
    }
}

案例1图解
案例2图解

String和StringBuilder和StringBuffer区别

  • String:不可变字符序列
  • StringBuffer:线程安全的可变字符序列,内部使用同步方法,效率不如StringBuilder
  • StringBuilder:线程不安全的可变字符序列

常用时间API

JDK8之前

SimpleDateFormat

SimpleDateFormat date=new SimpleDateFormat("yyyy-mm-dd hh:mm:ss");
System.out.println(date.format(new Date()));//格式化DATE为字符串
System.out.println(date.parse("2022-03-16 15:06:00");//解析字符串为DATE

Calendar

Calendar calendar = Calendar.getInstance();
// 或者
calendar = new GregorianCalendar();
	
calendar.setTime(new Date());  // 根据Date设置calendar  
		
System.out.println(calendar.getTime()); // 获取Date
System.out.println(calendar.get(Calendar.DAY_OF_WEEK));//周几  
		// 注意,周日显示是1,周一是2,...,周六是7
System.out.println(calendar.get(Calendar.MONTH));//几月
		// 注意,从0开始,一月显示是0
calendar.add(Calendar.MINUTE, 1);  // 日期运算

Calendar不太好用:Calendar会有一个偏移量,容易弄乱,也无法保证线程安全
JDK8之后
LocalDate、LocalTime、LocalDateTime
初始化

LocalDate date = LocalDate.now();  // 2021-05-11
LocalTime time = LocalTime.now();  // 01:03:01.135762600
LocalDateTime dateTime = LocalDateTime.now();  // 2021-05-11T01:03:01.135762600
LocalDateTime dateTime = LocalDateTime.of(2020, 05, 20, 13, 14);  // 2020-05-20T13:14

获取时间

LocalDateTime dateTime = LocalDateTime.of(2020, 05, 20, 13, 14);
System.out.println(dateTime.getDayOfWeek());  // WEDNESDAY
System.out.println(dateTime.getDayOfWeek().getValue());  // 3
System.out.println(dateTime.getDayOfMonth());  // 20
System.out.println(dateTime.getDayOfYear());  // 141
System.out.println(dateTime.getMonth());  // May
System.out.println(dateTime.getMonthValue());  // 5

设置时间

LocalDateTime dateTime = LocalDateTime.of(2020, 05, 20, 13, 14);
System.out.println(dateTime);  // 2020-05-20T13:14
System.out.println(dateTime.withDayOfMonth(21));  // 2020-05-21T13:14
// 与Calendar不同,这里是直接返回一个新对象,体现了不可变性

时间运算

LocalDateTime dateTime = LocalDateTime.of(2020, 05, 20, 13, 14);
System.out.println(dateTime);  // 2020-05-20T13:14
System.out.println(dateTime.plusDays(1));  // 2020-05-21T13:14

Instant:瞬时(时间戳)
初始化:

Instant instant = Instant.now();  // UTC时间
System.out.println(instant);  // 2021-05-10T17:25:13.423739400Z
// 注意,我们是东八区,所以这里的值是我们的北京时间减8小时,是伦敦的本初子午线时间

可以按实际情况添加偏移量

Instant instant = Instant.now();
System.out.println(instant.atOffset(ZoneOffset.ofHours(8)));
// 2021-05-11T01:32:21.631253700+08:00

起始于1970年1月1日0时0分0秒的毫秒数及转换

Instant instant = Instant.now();
long millis = instant.toEpochMilli();
Instant instant1 = Instant.ofEpochMilli(millis);

DateTimeFormatter
转换

// 自带的枚举
LocalDateTime localDateTime = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
System.out.println(formatter.format(localDateTime));
// 2021-05-11T01:48:11.8582478

//----------------------------------------------------------------------------
// ofLocalizedDateTime
formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
System.out.println(formatter.format(localDateTime));
// 2021/5/11 上午1:48

formatter = DateTimeFormatter
    .ofLocalizedDateTime(FormatStyle.LONG)
    .withZone(ZoneOffset.ofHours(8));
System.out.println(formatter.format(localDateTime));
// 2021年5月11日 +08:00 上午1:49:47

//----------------------------------------------------------------------------
// 自定义
formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
System.out.println(formatter.format(localDateTime));
// 2021-05-11 01:55:19

// 解析
TemporalAccessor accessor = formatter.parse("2021-05-11 01:59:59");
System.out.println(accessor);
/* {HourOfAmPm=1, MinuteOfHour=59, SecondOfMinute=59, NanoOfSecond=0, MilliOfSecond=0, MicroOfSecond=0},ISO resolved to 2021-05-11
*/

比较器

comparable comparator

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值