Java之常用类
Java之常用类
创作不易,希望各位看官点赞收藏.
1、 字符串类
1.1、String类
String类:代表字符串,一个使用 " ",包裹的字符串。
- String类是一个final修饰的类,不可以被其它类继承。
- String的底层使用
final char[]
数组来存放的,所以String具有不可变性。 - 实现了Serializable接口,支持序列化。
- 实现了Comparable接口,支持比较字符串大小。
public final class String implements java.io.Serializable, Comparable<String>, CharSequence { private final char value[]; // 字符数组存放字符,不可以改变 private int hash; // 默认是0}
String实例方式:
- 字面量定义。
- 通过new String()实例对象,构造方法有字符字面量、char数组、byte数组、StringBuffer、StringBuilder重载。
字符串字面量:直接使用 " " 包裹的字符串,不是通过new创建的String对象成为字符串字面量。
public static void main(String[] args) { String s1 = "Hello"; String s2 = "World"; String s3 = "Hello"; String s4 = new String("Hello"); System.out.println(s1==s3); // true System.out.println(s1==s2); // false System.out.println(s1==s4); // false}
==
是比较地址值,而字符串字面量在方法区不能重复,只能存在一个,如果一个String使用了字符串字面量先去方法区找有无相同的字符串,有就是使用同一个字符串,没有就在方法区中创建一个字符串字面量。所以s1和s3都是引用了方法区中同一个"Hello"就相等,而s4是通过new的String对象存在对当中,所以不相等。
面试题一:
String s = new String("Hello");
创建了几个对象?
如果常量池中没有 “Hello”,那就是创建了两个对象,一个是堆中String对象,另一个是方法区中字符串字面量对象;如果常量池中有 “Hello” 那么就只创建了一个对象,只有堆中的对象,但是还是引用了常量池的字符串常量。
面试题二:
public static void main(String[] args) { String s1 = "Hello"; String s2 = " World"; String s3 = "Hello World"; String s4 = "Hello"+" World"; String s5 = s1 + " World"; String s6 = "Hello" + s2; String s7 = s1+s2; String s8 = s4.intern(); System.out.println(s3==s4); // true System.out.println(s3==s5); // false System.out.println(s3==s6); // false System.out.println(s3==s7); // false System.out.println(s3==s8); // true}
结论:
- 字面量与字面量拼接,结果还是在常量池中,并且是同一个。
- 只要字符拼接中有任何一个是一个变量,那么结果是在堆当中。
- 如果凭拼接的结果使用 intern() 方法,返回值就在常量池中。
面试题三:
public class Demo03 { static String str = "你好"; static char[] ch = {'a','b','c','d'}; public static void test(String str,char[] ch){ str = "再见"; // 值传递,str是一个引用副本,但是由于字符串的不可变性,外部的str依然不变 ch[0] = 'x'; // ch与外部的ch引用同一个地址,这个改变了外面的也改变了 } public static void main(String[] args) { test(str,ch); System.out.println(str); // 你好 System.out.println(ch); // xbcd }}
String 常用方法:
String replace(CharSequencd old,CharSequencd new); // 使用new的字符串替换字符串中的old字符串String replace(String regex,String new); // 使用new替换字符串中满足regex正则表达式的所有字符boolean matches(String regex); // 字符串是否与regex这个正则表达式匹配,如果匹配返回true,不匹配返回falseString[] split(String regex); // 按照regex这个正则表达式切割字符串,返回是一个切割好的字符串数组
String 与 byte 数组之间的相互转换:
编码:将看得懂的转换成看不懂的过程,例如将String转换成byte。
解码:将看不懂的转换成看得懂的过程,例如将byte转换成String。
// 将String-->byteString str = "你好中国";byte[] bytes = str.getBytes(); // 使用默认的编码格式进行编码,一般是UTF-8System.out.println(Arrays.toString(bytes));bytes = str.getBytes("gbk"); // 指定一个编码格式System.out.println(Arrays.toString(bytes));// 将byte-->StringString s = new String(bytes); // 使用默认字符集进行解码,因为上面使用gbk编码,这是使用utf-8解码,就产生了乱码,输出����й�System.out.println(s);s = new String(bytes, "gbk");System.out.println(s); // 你好中国
如果编码的格式与解码的格式不一样,会导致乱码问题,所以一定要注意使用的是哪个字符集。
1.2、StringBuffer、StringBuilder类
String、StringBuffer、StringBuilder三者的区别:
String: 不可变的字符串,底层使用final char[]数组存放数据StringBuffer:可变字符串,线程安全但是效率降低了,底层使用char[]数组存放数据StringBuilder:可变字符串,线程不安全效率高,底层使用char[]数组存放数据
StringBuffer源码分析:
// 构建StringBuffer对象public StringBuffer() { // 无参构造器,底层声明了一个长度为16的char数组 super(16);}public StringBuffer(int capacity) { // 可以指定char数组的容量及buffer的存放的最长数据长度 super(capacity);}public StringBuffer(CharSequence seq) { // 创建一个长度为 参数字符串长度+16 的一个char数组 this(seq.length() + 16); // 调用第二个构造器 append(seq);}
当向StringBuffer中添加字符串,实际就是向底层的char数组中添加数据。
StringBuffer扩容机制:
将char扩容成一个新长度(增加一倍+2)的数组,原数据直接拷贝。
// minimumCapacity 是添加字符串后的最小需要长度private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code if (minimumCapacity - value.length > 0) { value = Arrays.copyOf(value,newCapacity(minimumCapacity)); // 进行扩容 }}// 扩容方法private int newCapacity(int minCapacity) { // 将当前字符长度增加1倍+2,返回一个新的长度 int newCapacity = (value.length << 1) + 2; if (newCapacity - minCapacity < 0) { newCapacity = minCapacity; } return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity < 0) ? hugeCapacity(minCapacity) : newCapacity;}
2、时间日期类
2.1、Date类
Date: 表示一个准确到毫秒的时间,这个是是JDK8之前表示时间的类,很多方法已经不再使用了,主要包含两个构造器和两个方法还在使用。
public Date() { // 创建一个当前系统时间 this(System.currentTimeMillis());}public Date(long date) { // 创建一个从1970年1月1日午夜0点后一个毫秒时间的一个日期 fastTime = date;}public long getTime() { // 返回这个日期时间的时间撮,返回值是long类型 return getTimeImpl();}public String toString() { // 返回字符串,默认是 EEE MMM dd HH:mm:ss zzz yyyy格式}public static void main(String[] args) { Date date = new Date(); System.out.println(date.getTime()); // 1652356460877 System.out.println(date); // Thu May 12 19:54:20 CST 2022 date = new Date(1000000000L); System.out.println(date.getTime()); // 1000000000 System.out.println(date); // Mon Jan 12 21:46:40 CST 1970}
java.sql.Date:表示数据库中的时间类,继承至java.util.Date这个类,所以拥有之前的所有方法,但是toString输出的是一个yyyy-MM-dd格式的日期。并且只有毫秒作为参数构造器。
java.sql.Date date1 = new java.sql.Date(10000000000L);System.out.println(date1); // 1970-04-27
2.2、SimpleDateFormat类
用于格式化和解析Date日期时间类,将日期类格式化成指定的格式的字符串或者将指定字符串解析成一个日期对象。
public static void main(String[] args) throws ParseException { String format = "yyyy-MM-dd hh:mm:ss"; // 日期的格式 // 可以使用无参构造器,这样就是用默认的格式 SimpleDateFormat sdf = new SimpleDateFormat(format); Date date = new Date(); // 格式化,将日期格式成对应格式字符串 String dateStr = sdf.format(date); System.out.println(dateStr); // 2022-05-15 10:38:41 // 解析,将对应格式字符串解析成日期对象 Date date1 = sdf.parse(dateStr); System.out.println(date1); // Sun May 15 10:38:41 CST 2022}
2.3、Calendar类
// Calendar 类用于表示日历public static void main(String[] args) { // Calendar是一个抽象类,不能实例化,通常有两种方式创建对象 // 1.创建子类GregorianCalendar对象,不常用 // GregorianCalendar calendar = new GregorianCalendar(); // 2.调用getInstance这个静态方法,但是实质还是创建的GregorianCalendar对象 Calendar calendar = Calendar.getInstance(); // 常用方法 // get(filed):通过传递在Calendar中属性,获取对应的值 System.out.println(calendar.get(Calendar.DAY_OF_YEAR)); // 这是这一年的几天 System.out.println(calendar.get(Calendar.DAY_OF_WEEK)); // 新期,1表示星期日,后面依次增加1 System.out.println(calendar.get(Calendar.MONTH)); // 月份,0-11依次表示1-12月 // set(filed);设置某个属性值,没有返回值,直接修改对象属性 calendar.set(Calendar.DAY_OF_WEEK,2); // 设置为星期一 System.out.println(calendar.get(Calendar.DAY_OF_WEEK)); // add(filed):某个属性值增加多少 calendar.add(Calendar.DAY_OF_WEEK,-10); // 可以设置为负数,这样就是减少 System.out.println(calendar.get(Calendar.DAY_OF_WEEK)); // 将日历转换成date对象 Date date = calendar.getTime(); System.out.println(date); // 将date对象转换成calendar对象 Date date1 = new Date(1000000000000L); calendar.setTime(date1); System.out.println(calendar.get(Calendar.DAY_OF_WEEK));}
2.4、JDK8.0新日期类
LocalDate:表示日期,有年、月、日。
LocalTime:表示时间,有时、分、秒、毫秒。
LocalDateTime:表示日期时间,有年、月、日、时、分、秒、毫秒。
// 实例化对象public static void main(String[] args) { // 实例化对象 // 方式1:通过静态方法now()实例对象 LocalDate localDate = LocalDate.now(); LocalTime localTime = LocalTime.now(); LocalDateTime localDateTime = LocalDateTime.now(); // 方式2:通过静态方法of实例化对象,参数需要年月日,参数必须符合年月日规则,不然会报错 LocalDate localDate1 = LocalDate.of(1000, 2, 10); // 时分秒参数也需要合法,时0-23,分0-59,秒0-59 LocalTime localTime1 = LocalTime.of(23, 59, 59); // 参数可以是年月日时分秒,也可以时对应的localDate和localTime LocalDateTime localDateTime1 = LocalDateTime.of(localDate1,localTime1);}
// 返回新期几,返回值是一个DayOfWeek枚举类,可以通过getValue()获取一个1-7的数字System.out.println(localDate.getDayOfWeek()); System.out.println(localDate.getDayOfMonth()); // 这一个月中的第几天System.out.println(localDate.getDayOfYear()); // 返回这一年的第几天System.out.println(localDate.getMonth()); // 获取月份,返回值是一个Month枚举类System.out.println(localDate.getMonthValue()); // 获取月份System.out.println(localDate.getYear()); // 获取年份
// 设置日期的相关属性,不可变性LocalDate localDate2 = localDate.withMonth(11); // 注意这个方法不修改原来的对象,而是返回一个新的对象LocalDate localDate3 = localDate.withYear(1000);System.out.println(localDate2);System.out.println(localDate3);
// 修改属性值// 将当前日期增加一周,可以为负数,相当于是减LocalDate localDate4 = localDate.plusWeeks(-1);System.out.println(localDate4);LocalDate localDate5 = localDate.plusDays(-100); // 加100天System.out.println(localDate5);LocalDate localDate6 = localDate.minusDays(100); // 减少100天System.out.println(localDate6);
这三个类都可以使用上面对应属性的方法,没有全部说完。
Instant:表示时间线上的瞬时点,提过机器视图,不提供人类处理人类意义上的时间。
public static void main(String[] args) { // now()静态方法实例化Instant对象 Instant instant = Instant.now(); System.out.println(instant); // 2022-05-15T10:06:27.255Z // 但是由于时区不同,需要修改到本地时区,修改到东八区 OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8)); System.out.println(offsetDateTime); // 获取对应instant的毫秒数,距离1970.1.1 long l = instant.toEpochMilli(); System.out.println(l); // 除了通过now来创建一个instant对象,也可以通过毫秒数创建 Instant instant1 = Instant.ofEpochMilli(l); System.out.println(instant1);}
2.5、DateTimeFormatter 类
用于格式化、解析时间,类似于SimpleDateFormat类。
public static void main(String[] args) { // 实例化对象方式一:通过静态属性,已经定义了格式,需要什么样的格式直接使用即可 DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; // 本地格式方式创建对象,通过ofLocalizedDate方法,参数是一个枚举,指定格式 DateTimeFormatter dateTimeFormatter1 = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG); // 上面两种方式不常用,通常使用自定义格式,参数需要一个格式 DateTimeFormatter dateTimeFormatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"); // 格式化 LocalDateTime localDateTime = LocalDateTime.now(); // 将localdate、localtime、localdatetime格式化成指定的格式,格式内容必须与创建指定格式相匹配 String str1 = dateTimeFormatter.format(localDateTime); System.out.println(str1); // 2022-05-15T18:42:44.828 // 解析,返回的是一个TemporalAccessor,这是一个日期的父类,使用多态,已经是一个时间类了,可以强转成自己需要的类 TemporalAccessor parse = dateTimeFormatter.parse("2022-05-15T18:42:44.828"); System.out.println(parse);}
3、Comparable 接口
一个类实现Comparable接口,并重写compareTo(obj)方法,返回值是一个int,如果当前对象大于参数,返回正数;如果小于返回负数,等于返回0。这是自然排序,所有对象可以使用这种排序方式,sort()中使用这种排序方式来排序。
public class Student implements Comparable<Student>{ String name; int age; public Student(String name, int age) { this.name = name; this.age = age; } @Override public int compareTo(Student o) { if (this==o){ return 0; }else{ return this.age - o.age; } }}
4、Comparator 接口
也是一个排序接口,这是定制排序规则,如果一个类中没有实现Comparable接口或者定制的Comparable排序规则不符合当前业务的排序要求,可以重新定制一个排序规则。
public class ComparatorTest implements Comparator<Student> { // 重写compare方法 @Override public int compare(Student o1, Student o2) { // 正数o1大于o2 // 负数o1小于o2 // 0 o1等于o2 return o1.age-o2.age; }}
public static void main(String[] args) { Student[] students = new Student[5]; students[0] = new Student("张三", 19); students[1] = new Student("李四", 14); students[2] = new Student("李四", 23); students[3] = new Student("李四", 1); students[4] = new Student("李四", 53); // 需要将ComparatorTest这个类作为参数来自定义排序规则 Arrays.sort(students,new ComparatorTest());}
5、System 类
public static void main(String[] args) { long l = System.currentTimeMillis(); // 获取一个时间戳 System.out.println(l); // System.exit(0); // 程序结束,参数:0正常退出,非0,错误退出 // getProperty()参数是一个字符串,获取系统相关信息 String version = System.getProperty("java.version");// 获取系统的java版本 System.out.println(version);}