String类
/*String x = "java" + "test"; // 等同于:String x = "javatest";
在编译阶段就完成了字符串拼接
* 使用 + 进行拼接的生成的新的字符串不会被放到字符串常量池中。(+两边至少有一个是变量。)
*
* 当 + 两边都是字符串字面量的时候,编译器会进行自动优化。在编译阶段进行拼接。
// 如果这个字符串使用比较频繁,希望将其加入到字符串常量池中,怎么办?
String s5 = s3.intern();
字符串的常用方法
char charAt(int index); 返回索引处的char值
int length(); 获取字符串长度
boolean isEmpty(); 判断字符串是否为空字符串,如果length()是0就是空字符串。
boolean equals(Object anObject); 判断两个字符串是否相等。
boolean equalsIgnoreCase(String anotherString); 判断两个字符串是否相等,忽略大小写。
boolean contains(CharSequence s); 判断当前字符串中是否包含某个子字符串
boolean startsWith(String prefix); 判断当前字符串是否以某个字符串开头
boolean endsWith(String suffix); 判断当前字符串是否以某个字符串结尾
int compareTo(String anotherString); 两个字符串按照字典顺序比较大小
int compareToIgnoreCase(String str); 两个字符串按照字典顺序比较大小,比较时忽略大小写
int indexOf(String str); 获取当前字符串中str字符串的第一次出现处的下标。
int indexOf(String str, int fromIndex); 从当前字符串的fromIndex下标开始往右搜索,获取当前字符串中str字符串的第一次出现处的下标。
int lastIndexOf(String str); 获取当前字符串中str字符串的最后一次出现处的下标。
int lastIndexOf(String str, int fromIndex); 从当前字符串的fromIndex下标开始往左搜索,获取当前字符串中str字符串的最后一次出现处的下标。
byte[] getBytes(); 将字符串转换成字节数组。其实就是对字符串进行编码。默认按照系统默认字符集。
byte[] getBytes(String charsetName); 将字符串按照指定字符集的方式进行编码。
byte[] getBytes(Charset charset);
char[] toCharArray(); 将字符串转换字符数组。
String toLowerCase(); 转小写
String toUpperCase(); 转大写
String concat(String str); 进行字符串的拼接操作。和 + 的区别?
- + 既可以进行求和,也可以进行字符串的拼接,底层拼接时会创建StringBuilder对象进行拼接。+ 拼接null时不会出现空指针异常。
- concat方法参数只能时字符串类型,拼接时不会创建StringBuilder对象,拼接完成后返回一个新的String对象。拼接null会出现空指针异常。
- + 使用较多。如果进行大量字符串拼接,这两个都不合适。
String substring(int beginIndex); 从指定下标beginIndex开始截取子字符串
String substring(int beginIndex, int endIndex);
String trim(); 去除字符串前后空白(只能去除ASCII码中的空格和制表符)
String strip(); 去除字符串前后空白(支持所有的编码形式的空白,可以将全角空格去除,\u3000是全角空格,Java11新增)
String stripLeading(); 去除前空白
String stripTrailing(); 去除后空白
String toString();
String intern(); 获取字符串常量池中的字符串,如果常量池中没有,则将字符串加入常量池并返回。
- byte[] bytes = {97,98,99,100}; String s = new String(bytes);
- String s2 = s.intern(); // 将字符串 “abcd”放入字符串常量池并返回常量池中的字符串 “abcd”
static String join(CharSequence d, CharSequence... elements); 将多个字符串以某个分隔符连接(Java8新增)
static String join(CharSequence delimiter, Iterable<? extends CharSequence> elements);
static String valueOf(boolean b); 以下所有的静态方法valueOf作用是将非字符串类型的数据转换为字符串形式。
static String valueOf(char c);
static String valueOf(char[] data);
static String valueOf(char[] data, int offset, int count);
static String valueOf(double d);
static String valueOf(float f);
static String valueOf(int i);
static String valueOf(long l);
static String valueOf(Object obj);
正则表达式
String replace(CharSequence target, CharSequence replacement);将当前字符串中所有的target替换成replacement,返回一个新的字符串。
String replaceAll(String regex, String replacement);将当前字符串中所有符合正则表达式的regex替换成replacement。
String[] split(String regex);将当前字符串以某个正则表达式表示的子字符串进行分割,返回一个字符串数组。boolean matches(String regex);判断当前字符串是否符合正则表达式regex。
@Test
public void test7(){
String s1 = "ab";
final String s2 = "b";
String s3 = "a" + s2;
// 和这个一样了。
//String s3 = "a" + "b";
System.out.println(s1 == s3);
}
@Test
public void test8(){
String s1 = "ab";
final String s2 = getB();
String s3 = "a" + s2;
System.out.println(s1 == s3); // false
}
public String getB(){
return "b";
}
StringBuffer与StringBuilder
- StringBuffer是线程安全的,StringBuilder效率更高
- 默认初始化容量16
- 扩容策略:从当前容量开始,每次扩容为原来的2倍再加上2
StringBuffer和StringBuilder常用方法
StringBuilder append(Type data);
StringBuilder delete(int start, int end);
StringBuilder deleteCharAt(int index);
StringBuilder insert(int offset, String str);
StringBuilder replace(int start, int end, String str)
StringBuilder reverse();//反转
void setCharAt(int index, char ch);
void setLength(int newLength);
char charAt(int index);
int indexOf(String str);
int indexOf(String str, int fromIndex);
int lastIndexOf(String str);
int lastIndexOf(String str, int fromIndex);
int length();
String substring(int start);
String substring(int start, int end);
String toString();
包装类
Integer的常用方法
static int compare(int x, int y); 比较大小
static int max(int a, int b); 最大值
static int min(int a, int b); 最小值
static int parseInt(String s); 将字符串数字转换成数字类型。其它包装类也有这个方法:Double.parseDouble(String s)
static String toBinaryString(int i); 获取数字二进制的字符串表示形式
static String toHexString(int i); 获取数字十六进制的字符串表示形式
static String toOctalString(int i); 获取数字八进制的字符串表示形式
int compareTo(Integer anotherInteger); 比较大小,可见实现了Comparable接口
boolean equals(Object obj); 包装类已经重写了equals()方法。
String toString(); 包装类已经重写了toString()方法。
int intValue(); 将包装类拆箱为基本数据类型
static String toString(int i); 将基本数据类型转换成字符串
static Integer valueOf(int i); 将基本数据类型转换成Integer
static Integer valueOf(String s) 将字符串转换成Integer(这个字符串必须是数字字符串才行,不然出现NumberFormatException)
整数型常量池
[-128 ~ 127] Java为这个区间的Integer对象创建了整数型常量池。
也就是说如果整数没有超出范围的话,直接从整数型常量池获取Integer对象。
以下是一个面试题:请说出它的输出结果:
Integer x = 128;
Integer y = 128;
System.out.println(x == y); // false
Integer a = 127;
Integer b = 127;
System.out.println(a == b); // true
大数字
整数
常用构造方法:BigInteger(String val)
BigInteger add(BigInteger val); 求和
BigInteger subtract(BigInteger val); 相减
BigInteger multiply(BigInteger val); 乘积
BigInteger divide(BigInteger val); 商
int compareTo(BigInteger val); 比较
BigInteger abs(); 绝对值
BigInteger max(BigInteger val); 最大值
BigInteger min(BigInteger val); 最小值
BigInteger pow(int exponent); 次幂
BigInteger sqrt(); 平方根
浮点数
构造方法:BigDecimal(String val)
常用方法:
BigDecimal add(BigDecimal augend); 求和
BigDecimal subtract(BigDecimal subtrahend); 相减
BigDecimal multiply(BigDecimal multiplicand); 乘积
BigDecimal divide(BigDecimal divisor); 商
BigDecimal max(BigDecimal val); 最大值
BigDecimal min(BigDecimal val); 最小值
BigDecimal movePointLeft(int n); 向左移动小数点
BigDecimal movePointRight(int n); 向右移动小数点
数字格式化
// 创建一个数字格式化对象
DecimalFormat df = new DecimalFormat("###,###.##");
// 格式化
String s = df.format(12345678.123);
System.out.println(s); // "12,345,678.12"
// 保留四位小数,要求不够补0
DecimalFormat df2 = new DecimalFormat("###,###.0000");
String s2 = df2.format(12345678.123);
System.out.println(s2); // "12,345,678.1230"
有时我们需要将数字以某种格式展示,在java中如何格式化呢?
java.text.DecimalFormat 类是专门用来对数字进行格式的。
常用数字格式:
###,###.## // 三个数字为一组,组和组之间使用逗号隔开,保留两位小数
###,###.0000 // 三个数字为一组,组和组之间使用逗号隔开,保留4位小数,不够补0
构造方法:DecimalFormat(String pattern)
常用方法:String format(数字);
日期处理
相关API
日期相关API
long l = System.currentTimeMillis(); // 获取自1970年1月1日0时0分0秒到系统当前时间的总毫秒数。
java.util.Date 日期类
构造方法:Date()
构造方法:Date(long 毫秒)
java.util.SimpleDateFormat 日期格式化类
日期转换成字符串(java.util.Date -> java.lang.String)
字符串转换成日期(java.lang.String -> java.util.Date)
java.util.Calendar 日历类
获取当前时间的日历对象:Calendar c = Calendar.getInstance();
获取日历中的某部分:int year = c.get(Calendar.YEAR);
Calendar.YEAR 获取年份 Calendar.MONTH 获取月份,0表示1月,1表示2月,...,11表示12月
Calendar.DAY_OF_MONTH 获取本月的第几天 Calendar.DAY_OF_YEAR 获取本年的第几天
Calendar.HOUR_OF_DAY 小时,24小时制 Calendar.HOUR 小时,12小时制
Calendar.MINUTE 获取分钟 Calendar.SECOND 获取秒
Calendar.MILLISECOND 获取毫秒 Calendar.DAY_OF_WEEK 获取星期几,1表示星期日,...,7表示星期六
java.util.Calendar 日历类
日历的set方法:设置日历
calendar.set(Calendar.YEAR, 2023);
calendar.set(2008, Calendar.SEPTEMBER,8);
日历的add方法(日历中各个部分的加减):
calendar.add(Calendar.YEAR, 1);
日历对象的setTime()让日历关联具体的时间
calendar.setTime(new Date());
日历对象的getTime()方法获取日历的具体时间:
Date time = calendar.getTime();
// java.util.Date ---> java.lang.String
// 获取系统当前时间
Date now = new Date();
// 格式化
//SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
//SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
//SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yy");
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
// 调用format方法完成格式化
String str = sdf.format(now);
System.out.println(str);
// java.lang.String ---> java.util.Date
// 日期字符串
String strDate = "2008-08-08 08:08:08 888";
// 创建日期格式化对象
SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
// 解析:将字符串String转换成Date
Date date = sdf2.parse(strDate);
System.out.println(date);
package com.powernode.javase.datetest;
import java.util.Calendar;
/**
* java.util.Calendar 日历类
*/
public class CalendarTest01 {
public static final int I1 = 1;
public static final int I2 = 2;
public static final int I3 = 3;
/**
* 当num==1的时候...
* 当num==2的时候...
* 当num==3的时候...
* @param num
*/
public static void m(int num){
}
public static void main(String[] args) {
m(CalendarTest01.I3);
// 获取当前时间的日历对象(调用一个静态方法)
Calendar calendar = Calendar.getInstance();
System.out.println(calendar);
// 获取日历中年
//int year = calendar.get(1);
int year = calendar.get(Calendar.YEAR);
System.out.println(year);
// 获取日历中月
int month = calendar.get(Calendar.MONTH);
System.out.println(month); // 0-11 表示一年中的12个月。
// 获取日历中的日
int day = calendar.get(Calendar.DAY_OF_MONTH);
System.out.println(day);
/*
Calendar.YEAR 获取年份
Calendar.MONTH 获取月份,0表示1月,1表示2月,...,11表示12月
Calendar.DAY_OF_MONTH 获取本月的第几天
Calendar.DAY_OF_YEAR 获取本年的第几天
Calendar.DAY_OF_WEEK 获取星期几,1表示星期日,...,7表示星期六
Calendar.HOUR_OF_DAY 小时,24小时制
Calendar.HOUR 小时,12小时制
Calendar.MINUTE 获取分钟
Calendar.SECOND 获取秒
Calendar.MILLISECOND 获取毫秒
*/
}
}
package com.powernode.javase.datetest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
public class CalendarTest02 {
public static void main(String[] args) throws ParseException {
// 获取系统当前时间的日历
Calendar cal = Calendar.getInstance();
// 设置该日历的年是2008年
cal.set(Calendar.YEAR, 2008);
//cal.set(Calendar.MONTH, 10);
// 获取日历的年月日信息
System.out.println(cal.get(Calendar.YEAR) + "年" + (cal.get(Calendar.MONTH) + 1) + "月" + cal.get(Calendar.DAY_OF_MONTH) + "日");
// 设置日历是2008年8月8日 8时8分8秒的日历
cal.set(2008, Calendar.AUGUST,8,8,8,8);
// 获取日历的年月日信息
System.out.println(cal.get(Calendar.YEAR) + "年" + (cal.get(Calendar.MONTH) + 1) + "月" + cal.get(Calendar.DAY_OF_MONTH) + "日");
// 年加1
//cal.add(Calendar.YEAR, 2);
cal.add(Calendar.YEAR, -2);
// 获取日历的年月日信息
System.out.println(cal.get(Calendar.YEAR) + "年" + (cal.get(Calendar.MONTH) + 1) + "月" + cal.get(Calendar.DAY_OF_MONTH) + "日");
// 获取一个2008年5月12日 15:30:30的Date
String strDate = "2008-05-12 15:30:30";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = sdf.parse(strDate);
cal.setTime(date);
// 获取这个日历的小时和分
System.out.println(cal.get(Calendar.HOUR_OF_DAY));
System.out.println(cal.get(Calendar.MINUTE));
// 获取日历代表的日期
cal.set(Calendar.SECOND, 56); // 修改日历中的秒
Date time = cal.getTime();
String s = sdf.format(time);
System.out.println(s);
}
}
Java8的新日期API
传统的日期API存在线程安全问题,Java8又提供了一套全新的日期API
java.time.LocalDate、java.time.LocalTime、java.time.LocalDateTime 日期、时间、日期时间
java.time.Instant 时间戳信息
java.time.Duration 计算两个时间对象之间的时间间隔,精度为纳秒
java.time.Period 计算两个日期之间的时间间隔,以年、月、日为单位。
java.time.temporal.TemporalAdjusters 提供了一些方法用于方便的进行日期时间调整
java.time.format.DateTimeFormatter 用于进行日期时间格式化和解析
LocalDate日期、LocalTime时间、LocalDateTime日期时间
获取当前时间(精确到纳秒,1秒=1000毫秒,1毫秒=1000微秒,1微秒=1000纳秒)
LocalDateTime now = LocalDateTime.now();
获取指定日期时间
LocalDateTime ldt = LocalDateTime.of(2008,8,8,8,8,8,8); // 获取指定的日期时间
加日期和加时间
LocalDateTime localDateTime = ldt.plusYears(1).plusMonths(1).plusDays(1).plusHours(1).plusMinutes(1).plusSeconds(1).plusNanos(1);
减日期和减时间
LocalDateTime localDateTime = ldt.minusYears(1).minusMonths(1).minusDays(1).minusHours(1).minusMinutes(1).minusSeconds(1).minusNanos(1);
获取年月日时分秒
int year = now.getYear(); // 年 int month = now.getMonth().getValue(); // 月
int dayOfMonth = now.getDayOfMonth(); // 一个月的第几天 int dayOfWeek = now.getDayOfWeek().getValue(); // 一个周第几天
int dayOfYear = now.getDayOfYear(); // 一年的第几天 int hour = now.getHour(); // 时
int minute = now.getMinute(); // 分 int second = now.getSecond(); // 秒
int nano = now.getNano(); // 纳秒
Instant 时间戳(获取1970年1月1日 0时0分0秒到某个时间的时间戳)
获取系统当前时间(UTC:全球标准时间)
Instant instant = Instant.now();
获取时间戳
long epochMilli = instant.toEpochMilli();
Duration 计算时间间隔
计算两个时间相差时间间隔
LocalDateTime now1 = LocalDateTime.of(2008,8,8,8,8,8);
LocalDateTime now2 = LocalDateTime.of(2009,9,9,9,9,9);
Duration between = Duration.between(now1, now2);
// 两个时间差多少个小时
System.out.println(between.toHours());
// 两个时间差多少天
System.out.println(between.toDays());
Period 计算日期间隔
计算两个日期间隔
LocalDate now1 = LocalDate.of(2007,7,7);
LocalDate now2 = LocalDate.of(2008,8,8);
Period between = Period.between(now1, now2);
// 相差年数
System.out.println(between.getYears());
// 相差月数
System.out.println(between.getMonths());
// 相差天数
System.out.println(between.getDays());
TemporalAdjusters 时间矫正器
LocalDateTime now = LocalDateTime.now(); // 获取系统当前时间
now.with(TemporalAdjusters.firstDayOfMonth()); // 当前月的第一天
now.with(TemporalAdjusters.firstDayOfNextYear()); // 下一年的第一天
now.with(TemporalAdjusters.lastDayOfYear()); // 本年最后一天
now.with(TemporalAdjusters.lastDayOfMonth()); // 本月最后一天
now.with(TemporalAdjusters.next(DayOfWeek.MONDAY)); // 下周一
DateTimeFormatter 日期格式化
日期格式化 (LocalDateTime --> String)
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String s = dtf.format(now);
将字符串转换成日期(String --> LocalDateTime)
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime = LocalDateTime.parse("2008-08-08 08:08:08", dtf);
System.out.println(localDateTime);
Math
static int abs(int a); 绝对值
static double ceil(double a); 向上取整
static double floor(double a); 向下取整
static int max(int a, int b); 最大值
static int min(int a, int b); 最小值
static double random(); 随机数[0.0, 1.0) int num = (int)(Math.random() * 100);可以获取[0-100)的随机数
static long round(double a); 四舍五入
static double sqrt(double a); 平方根
static double pow(double a, double b); a的b次幂
枚举
通过反编译(javap)可以看到:
所有枚举类型默认继承java.lang.Enum,因此枚举类型无法继承其他类。
所有的枚举类型都被final修饰,所以枚举类型是无法继承的
所有的枚举值都是常量
所有的枚举类型中都有一个values数组(可以通过values()获取所有枚举值并遍历)
// 获取所有的枚举值,遍历
Color[] colors = Color.values();
for(Color color : colors){
System.out.println(color);
}
枚举的高级用法
普通类中可以编写的元素,枚举类型中也可以编写。
静态代码块,构造代码块
实例方法,静态方法
实例变量,静态变量
枚举类中的构造方法是私有化的(默认就是私有化的,只能在本类中调用)
构造方法调用时不能用new。直接使用“枚举值(实参);”调用。
每一个枚举值相当于枚举类型的实例。
枚举类型中如果编写了其他代码,必须要有枚举值,枚举值的定义要放到最上面,
最后一个枚举值的分号不能省略。
枚举类因为默认继承了java.lang.Enum,因此不能再继承其他类,但可以实现接口。
第一种实现方式:在枚举类中实现。
第二种实现方式:让每一个枚举值实现接口。
public interface Eatable {
void eat();
}
/**
* 季节枚举
*
* 枚举高级用法,语法点:
* 1. 如果一个枚举类型中定义了普通类的东西,必须指定枚举值。
* 2. 枚举值的定义只能出现在类体的最上面。
* 3. 所有枚举值后面必须有“;”结尾。
*/
public enum Season implements Eatable{
// 定义了有参数的构造方法之后
// 通过以下代码来调用构造方法
// 注意枚举类的构造方法不能使用new来调用。
// 并且枚举类的构造方法只能在本类中调用。
SPRING("春季", "春意盎然"){
@Override
public void eat(){
System.out.println("春季吃苹果");
}
},
SUMMER("夏季", "天太闷热"){
@Override
public void eat(){
System.out.println("夏季吃西瓜");
}
},
AUTUMN("秋季", "秋高气爽"){
@Override
public void eat(){
System.out.println("秋季吃苹果");
}
},
WINTER("冬季", "白雪皑皑"){
@Override
public void eat(){
System.out.println("冬季吃苹果");
}
};
// 提供属性
private final String name;
private final String desc;
public String getName() {
return name;
}
public String getDesc() {
return desc;
}
// 对于枚举类型来说,里面可以定义什么呢?普通类中可以定义的,枚举类型也可以。
// 静态代码块 构造代码块
// 静态方法,实例方法
// 静态变量,实例变量
/*// 静态代码块
static {
System.out.println("枚举类型Season的静态代码块执行了");
}
// 构造代码块
{
System.out.println("构造代码块执行了");
}
// 静态变量
public final static int A = 10;
// 实例变量
private final int b = 20;
// 静态方法
public static int getA(){
return A;
}
// 实例方法
public int getB(){
return b;
}*/
// 枚举类型也可以定义构造方法
// 构造方法是私有的。
Season(String name, String desc) {
this.name = name;
this.desc = desc;
}
/*@Override
public void eat(){
System.out.println("吃啥都行!");
}*/
}
public class SeasonTest {
public static void main(String[] args) {
Season season = get();
switch (season) {
case SPRING -> System.out.println(Season.SPRING.getDesc());
case SUMMER -> System.out.println(Season.SUMMER.getDesc());
case AUTUMN -> System.out.println(Season.AUTUMN.getDesc());
case WINTER -> System.out.println(Season.WINTER.getDesc());
}
// 遍历
Season[] seasons = Season.values();
for(Season s : seasons){
System.out.println(s.getName() + "-->" + s.getDesc());
s.eat();
}
}
public static Season get(){
return Season.SUMMER;
}
}
Random
常用构造方法:
Random()
常用方法:
int nextInt(); 获取一个int类型取值范围内的随机int数
int nextInt(int bound); 获取[0,bound)区间的随机数
double nextDouble(); 获取[0.0, 1.0)的随机数。
System
常用属性:
static final PrintStream err 标准错误输出流(System.err.println(“错误信息”);输出红色字体)
static final InputStream in 标准输入流
static final PrintStream out 标准输出流
常用方法:
static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length); 数组拷贝
static void exit(int status); 退出虚拟机
static void gc(); 建议启动垃圾回收器
static long currentTimeMillis(); 获取自1970-01-01 00:00:00 000到系统当前时间的总毫秒数
static long nanoTime(); 获取自1970年1月1日0时0分0秒以来,当前时间的纳秒数
static Map<String,String> getenv(); 获取当前系统的环境变量,例如Path,JAVA_HOME,CLASSPATH等。
static Properties getProperties(); 获取当前系统的属性。
static String getProperty(String key); 通过key获取指定的系统属性。
UUID
UUID
UUID(通用唯一标识符)是一种软件构建的标准,用来生成具有唯一性的ID。
UUID具有以下特点:
UUID可以在分布式系统中生成唯一的标识符,避免因为主键冲突等问题带来的麻烦。
UUID具有足够的唯一性,重复的概率相当低。UUID使用的是128位数字,除了传统的16进制表示之外(32位的16进制表示),还有基于62进制的表示,可以更加简洁紧凑。
UUID生成时不需要依赖任何中央控制器或数据库服务器,可以在本地方便、快速地生成唯一标识符。
UUID生成后可以被许多编程语言支持并方便地转化为字符串表示形式,适用于多种应用场景。
在Java开发中,UUID的使用是非常普遍的。它可以用于生成数据表主键、场景标识、链路追踪、缓存Key等。使用UUID可以方便地避免主键、缓存Key等因冲突而产生的问题,同时能够实现多种功能,例如追踪、缓存、日志记录等。
Java中的java.util.UUID类提供对UUID的支持
生成UUID:static UUID randomUUID();
将UUID转换为字符串:String toString();