Skip to content

常用类

String类及常用方法

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0
    //
}
  • 是一个 final 类,字符串的值在创建之后不能更改,同时说明类不能被继承
  • 当对字符串重新赋值的时候,实际上是新造了一个字符串,然后指向这个新的字符串
  • 字符串拼接也是新造了一个字符串,本质上是通过StringBuilder或者StringBuffer以及他们的 append 方法实现的
  • 当调用Stringreplace方法修改字符串内容时,也需要新造一个字符串
  • String对象的内容是放在一个char型数组里面的,数组也被final修饰
  • 通过字面量的方式(区别于new)给字符串赋值,此时字符串值放在字符串常量池中(在方法区里面)
  • 字符串常量池中是不会存储相同内容的字符串的

String实例化的方式

1、通过字面量直接复制;存放在方法区的字符串常量池里面

2、通过new+构造器;存放在堆里面

和基本数据类型的转换

  • 调用基本数据类型包装类的parsexx可以把字符串转为基本数据类型
  • 调用String类的valueOf方法可以把基本数据类型及其包装类转为字符串

和char[]的转换

  • 调用StringtoCharArray方法即可转为char型数组

  • char型数组作为参数传到String的构造函数就能得到对应的字符串

和字节数组(byte[])的转换

  • String → byte[]:调用StringgetBytes方法;可选传递字符集,不给定字符集则是一般是默认编码UTF-8。类似编码
  • byte[] → String:字节数组作为参数传到String的构造函数就能得到对应的字符串;也可以指定字符集。类似解码

面试题

1、String s1 = "abc"String s2 = new String("abc") 的区别?

  • 一个在方法区的字符串常量池里面,一个在堆空间
  • 内容都是一样的
public static void main(String[] args) {
    String s1 = "abc";
    String s2 = new String("abc");
    System.out.println(s1 == s2);
    System.out.println(s1.equals(s2));
}

输出:

false
true

2、String s2 = new String("abc")在内存中创建了几个对象?

两个:一个是堆空间中的new结构,另一个是char[]对应常量池中的数据"abc"

3、字符串拼接问题

image-20220824091802566

  • 常量和常量的连接,结果在常量池中

  • 只要其中一个是变量(不加final修饰),结果在堆中

  • 如果拼接的结果调用intern方法,则结果在常量池

4、函数调用

image-20220824093357632

函数调用的时候,基本数据类型传的是存储的数据,引用数据类型传的是地址

StringBufferStringBuilder

String:不可变的字符序列;底层使用char[]存储,加final修饰,调用new String()的时候默认容量是0

StringBuffer:可变的字符序列;大多数方法都使用synchronized关键字加锁,线程安全,效率低;底层使用char[]存储,不加final修饰,会多给16个容量;扩容时变为原来的2倍再加2,同时把原有数组的元素复制到新数组里面

StringBuilder:可变的字符序列;JDK 5新增,线程不安全,效率高;底层使用char[]存储,不加final修饰,会多给16个容量;扩容时变为原来的2倍再加2,同时把原有数组的元素复制到新数组里面

开发中建议直接指定容量,不然频繁扩容效率低。

StringBuffer(int capacity)或者StringBuilder(int capacity)

StringBufferStringBuilder常用方法

appenddeletereplaceinsertreverse

日期API

System

System类中的currentTimeMillis方法

Date

util包下的Date

1、两个构造器

Date():创建一个当前时间的Date对象

Date(long date):创建指定毫秒数的Date对象

2、两个方法

toString:显示当前的年月日时分秒

getTime:获取当前Date对象的时间戳(毫秒数)

sql包下的Date类对应数据库中的日期类型变量;平时不用这个

构造器:Date(long date)

sql包下的Date对象和util包下的Date对象转换:

  • sql.Dateutil.Date,直接转,子类对象赋给父类即可
  • 反过来就先要获取时间戳,然后把时间戳作为参数传到构造器。父类对象是不能直接强转成子类的
Date date1 = new Date();// util包
java.sql.Date date2 = new java.sql.Date(date1.getTime());

SimpleDateFormat

格式化(日期转字符串)

(1)按照默认方式格式化(不建议使用)

SimpleDateFormat sdf = new SimpleDateFormat();// 使用默认构造器

Date date = new Date();
System.out.println(date);

String format = sdf.format(date);
System.out.println(format);

/*
输出如下:
Wed Aug 24 20:30:35 CST 2022
22-8-24 下午8:30
*/

(2)按照指定方式格式化(建议使用

Date date = new Date();
System.out.println(date);

SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
String format1 = sdf1.format(date);
System.out.println(format1);

/*
Wed Aug 24 20:46:38 CST 2022
2022-08-24 08:46:38
*/

大写M代表月份,小写m代表分钟

大写H代表24小时制,小写12小时制

解析(字符串转日期)

SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Date date1 = sdf1.parse("2022-08-24 09:46:38");// 要求字符串必须符合上面定义的格式
System.out.println(date1);

/*
Wed Aug 24 09:46:38 CST 2022
*/

练习:

1、把字符串转为sql包下的Date类型

SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd");
Date date1 = sdf1.parse("2022-08-24");// util包下的Date
java.sql.Date date2 = new java.sql.Date(date1.getTime());

Calendar

是一个抽象类

实例化方法

1、创建其子类GregorianCalendar的对象

2、调用本身的getInstance静态方法

常用方法

getsetgetTimesetTime

calendar.get(Calendar.DAY_OF_MONTH);// 这个月的第几天(获取其他信息可以调用其他常量)
set(Calendar.DAY_OF_MONTH, 22);// 指定今天是这个月的第22天
getTime();// 得到一个java.util.Date对象
setTime(Date date);// Date转日历类

JDK8中新日期API

都在java.time包下面放着,常用的是基础包和format包

JDK8之前想用可以导入joda-time包

LocalDateLocalTimeLocalDateTime

类被final修饰,都是不可变的

LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();

System.out.println(localDate);
System.out.println(localTime);
System.out.println(localDateTime);

/*
2022-08-24
21:31:59.353
2022-08-24T21:31:59.353
*/

localDateTime用的多一点

Instant

Instant instant = Instant.now();// utc时间
System.out.println(instant);// 2022-08-24T13:46:42.561Z

OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
System.out.println(offsetDateTime);// 2022-08-24T21:46:42.561+08:00

instant.toEpochMilli();// 获取时间戳

Instant instant1 = Instant.ofEpochMilli(instant.toEpochMilli());
System.out.println(instant1);// 2022-08-24T13:46:42.561Z, 同instant

DateTimeFormatter

public final class DateTimeFormatter {
    //...
}

final修饰,不可变类,线程安全

格式化或者解析时间

三种格式化方式:

1、预定义的标准格式。如:ISO_LOCAL_DATEISO_LOCAL_TIMEISO_LOCAL_DATE_TIME

2、本地化相关格式。如:ofLocalizedDateTime(FormatStyle.LONG)

3、自定义格式(常用)。如:ofPattern("yyyy-MM-dd hh:mm:ss")

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss");
// 格式化
String date = formatter.format(LocalDateTime.now());
System.out.println(date);// 2022-08-25 08:34:41

// 解析
TemporalAccessor accessor = formatter.parse("2022-08-25 08:34:41");
System.out.println(accessor);// {SecondOfMinute=41, MinuteOfHour=34, MicroOfSecond=0, MilliOfSecond=0, NanoOfSecond=0, HourOfAmPm=8},ISO resolved to 2022-08-25

Java比较器(重要)

让普通的Java对象比较大小

正常的Java对象只能使用等于和不等于,不能使用 >或者<比大小

Comparable接口

自然排序;类需要实现Comparable接口,重写compareTo方法

public int compareTo(T o);

重写规则:

1、如果当前对象this大于形参对象obj,则返回正整数;

2、如果当前对象this小于形参对象obj,则返回负整数;

3、如果当前对象this等于形参对象obj,则返回零。

Comparator接口

定制排序,按照用户自定义的规则排序;

临时性的比较,需要的时候指定一下

如果类本身没有实现Comparable接口或者实现的Comparable接口不符合业务需求,可以使用Comparator接口定制排序规则

重写compare方法

int compare(T o1, T o2);

举例:

String[] arr = new String[]{"AA","CC","KK","MM","GG","JJ","DD"};
Arrays.sort(arr,new Comparator(){

    //按照字符串从大到小的顺序排列
    @Override
    public int compare(Object o1, Object o2) {
        if(o1 instanceof String && o2 instanceof  String){
            String s1 = (String) o1;
            String s2 = (String) o2;
            return -s1.compareTo(s2);
        }
        //                return 0;
        throw new RuntimeException("输入的数据类型不一致");
    }
});