Java 常用类总结(SE基础)
本篇博客对java常用类相关知识进行了归纳总结,比较详细,适用于学习和复习。
1. 字符串相关的类
1.1 String
String是一个
final类,代表不可变的字符序列。不可被继承。
String对象的字符内容是存储在一个字节数组
byte[]中。JDK1.8中存储的是
char[]注意区别。
String
实现了Serializable
接口,支持序列化- 实现了
Comparable
接口,表示可以比较大小 - 通过字面量的方式(区别于
new
)给一个String
赋值,此时的字符串值在字符串常量池中(和方法区在同一个地方) - 当
String
进行连接操作、重新赋值、replace()
等操作时,会重新指定内存区域赋值,不使用原有的value
进行赋值
String str = "hello"; //字面量赋值 String s1 = new String();//本质上为,this.value = new byte[0] String s2 = new String(String str); //放一个String类型的参数 String s3 = new String(byte[] a); String s3 = new String(byte[] a,int off,int length);//构造方法,放char[]也是可以的
考虑如下代码:
String s1 = "javaEE"; String s2 = "javaEE"; String s3 = new String("javaEE"); String s4 = new String("javaEE");
这里,
s1==s2为
true,
s1==s3,
s1==s4,
s3==s4均为
false
原因如下:
实际上,通过构造方法来构造
String会指向
value,而
value再去指向字符串常量。
即
String s3 = new String("javaEE");在内存中创建了两个对象:一个是堆中的
value结构,一个是常量池中的字符串数据。
intern()
返回字符串对象的规范表示。 这里会返回一个字符串常量。内存空间在常量池中。
另外,有一个关于形参实参方面的需要注意:
public class StringTest { String str = new String("hello"); char[]ch = {'t','e','s','t'}; public void change(String str,char ch[]){ str = "hello,world"; ch[0]='b'; } public static void main(String[] args) { StringTest st = new StringTest(); st.change(st.str, st.ch); System.out.println(st.str); System.out.println(st.ch); } }
这里的结果为:"hello" /n "best"
类似于C语言中,根据指针进行交换两个指针中的内容,值传递过程中,实际参数的值传入形参,形成副本,方法结束后形参消失,实际参数值并没有改变。
另外还有一点需要注意:
String str = null; //这个指针指向null,并没有实例化 System.out.println(str);//输出”null“ System.out.println(str.length());//异常
1.2 String的常用方法
将
String的常用方法总结如下(未总结的请自己查阅):
同时还需要注意的一些方法如下,重要程度依次降低,但仍需掌握:
注意:上表下部的4个
int方法如果未找到,返回的均为-1
再举例一些方法(一些可能不太常用的):
String regex一般都用正则表达式表示
String转换为基本数据类型或包装类
调用包装类的静态方法:对应的类型,如要转
int,调用
Integer.parseInt(str)
基本数据类型、包装类转为String
调用
String重载的
valueOf(xxx)
另外
int num = 100; String str = num+""; //存在变量才会返回堆中,如果常量相加则会返回常量池
这样也可以转换为
String,但是需要注意,该类型是在堆中生成了
value数组,和
new String的方式类似。
String与char[], byte[]的相互转换
String-->
char[]:调用
String.toCharArray即返回了一个
char[]
char[]或byte[] --> String:直接调用构造器
String-->
byte[]:调用
String.getBytes即返回了一个
byte[],使用默认的字符集(例如"gbk、utf-8"等)进行转换。
getBytes(Charset charset)使用给定的
charset将该
String编码为字节序列,将结果存储到新的字节数组中。不同的编码方式返回的可能不同。
1.3 StringBuffer与StringBuilder
String与
StringBuffer, StringBuilder之间的异同?
String:不可变的字符序列,注意理解不可变性
StringBuffer: 56c 可变的字符序列,线程安全,效率较低(都是同步方法)
StringBuilder:jdk5.0新增,可变的字符序列,线程不安全,效率高
final byte[] value //String中的 byte[] value //StringBuffer和StringBuilder中的
StringBuffer
String str = new String();// new char[0] String str1 = new String("abc");//new char[] {'a','b','c'}; StringBuffer sb = new StringBuffer();//new char[16] 初始容量为16 sb.append('a');// value[0]='a';依次进行 StringBuffer sb1 = new StringBuffer("abc");//new char["abc".length()+16] System.out.println(sb.length()); //return的是count,每append操作count+=len,这里为1,并不是value.length
接下来看
StringBuffer的扩容机制
简述:一般情况下,若容量不够的时候,扩充为原来容量的2倍+2,同时将原有数组的元素复制到新数组中
JDK15中,源码已经改变,为:
private int newCapacity(int minCapacity) { int oldLength = value.length; int newLength = minCapacity << coder; int growth = newLength - oldLength; int length = ArraysSupport.newLength(oldLength, growth, oldLength + (2 << coder)); if (length == Integer.MAX_VALUE) 56c { throw new OutOfMemoryError("Required length exceeds implementation limit"); } return length >> coder; }
ArraysSupport.newLength这里就是比较
growth和
oldLength + (2 << coder)谁大,大者加上
oldLength(这样就成了2倍+2)。这里coder原始值为0,我只看了
append相关源码,
coder值并没有变,其他源码没有看,注意可能发生改变。
JDK1.8中是直接进行移位操作+2的,现版本已更新。
StringBuffer常用方法
StringBuilder的API与之相同,只是线程不安全,没有保证同步。
2. 日期时间
2.1 JDK8之前的日期时间
java.lang.System中的
static long currentTimeMillis()返回当前时间与1970年1月1日00:00:00之间的时间差(以毫秒为单位)。适用于计算时间差。(时间戳)
计算世界时间的主要标准有:
UTC,
GMT,
CST
java.util.Date
java.sql中也有一个
Date类,是java.util.Date的子类
表示特定的时间,精确到毫秒
两个构造器的使用:
构造器一: 创建一个当前时间的
Date对象
Date date = new Date(); System.out.println(date);//sout自带.toString,输出:Mon Apr 26 01:16:00 CST 2021 System.out.println(date.getTime());//返回当前date对象对应的时间戳 //Date中的无参构造源码 public Date() { this(System.currentTimeMillis()); }
构造器二: 创建了一个指定时间的
Date对象
Date date1 = new Date(1619371381884L); //随便找了个时间戳 System.out.println(date1);
构造器的其余方法均已过时,不建议使用。
java.sql.Date对应的是数据库中的日期时间类,一般在数据库交互时使用
java.sql.Date date2 = new java.sql.Date(1619371381884L); //2021-04-26 System.out.println(date2);
该类没有无参构造。输出形式不同。
两种
Date互转:
Date date3 = (Date)date2; //子类转父类 System.out.println(date3); java.sql.Date date4 = new java.sql.Date(new Date().getTime()); //父类转子类,不能强制类型转换ad0
java.text.SimpleDateFormat
允许进行格式化:日期-->文本,解析:文本-->日期
格式化:
解析:
Date parse(String text, ParsePosition pos)从字符串中解析文本以产生一个
Date。
pattern举例如下图:
demo1默认模式:
SimpleDateFormat sdf = new SimpleDateFormat(); Date date = new Date(); String format = sdf.format(date); System.out.println(date); //Mon Apr 26 02:38:11 CST 2021 System.out.println(format); //2021/4/26 上午2:38 //解析过程 String str = "2021/4/16 上午12:38"; //格式有要求 Date date1 = sdf.parse(str); System.out.println(date1); //Fri Apr 16 00:38:00 CST 2021
使用指定模式:
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy,MM,dd HH:mm:ss aaa"); String str2 = sdf1.format(date); System.out.println(str2); //2021,04,26 02:47:22 上午 //解析的话也需要按这种模式进行,正常模式通常为”yyyy-MM-dd hh:mm:ss“ String str3 ="2021,04,26 02:47:22 上午"; Date date2 = sdf1.parse(str3); System.out.println(date2); //Mon Apr 26 02:47:22 CST 2021
Calendar
Calendar是一个抽象类,主要用于完成日期字段之间的相互操作。
Calendar提供了一种类方法
getInstance,用于获取此类型的一般有用的对象。
Calendar的
getInstance方法返回一个
Calendar对象,其日历字段已使用当前日期和时间进行初始化:
Calendar rightNow = Calendar.getInstance();调用了它的子类GregorianCalendar的构造器Calendar calendar = Calendar.getInstance(); System.out.println(calendar.getClass());//class java.util.GregorianCalendar
Calendar对象可以产生实现特定语言和日历风格的日期时间格式化所需的所有日历字段值(例如日语 - 公历,日语 - 繁体)。
Calendar定义某些日历字段返回的值的范围及其含义。 例如,日历系统第一个月的值为
MONTH == JANUARY为所有日历。 其他值由具体的子类定义,如
ERA。 有关详细信息,请参阅各个实体文档和子类文档。
常用方法:
void set(int field, int v 1044 alue)将给定的日历字段设置为给定的值。
void add(int field, int amount)根据日历的规则,将指定的时间量添加或减去给定的日历字段。
final Date getTime()返回一个
Date表示此物体
Calendar的时间值
void setTime(Date date)使用给定的
Date设置此日历的时间
demo如下:
Calendar calendar = Calendar.getInstance(); //get int i = calendar.get(Calendar.DAY_OF_MONTH); System.out.println(i);//获取这个月的第几天,本实例为26,当前时间4/26 System.out.println(calendar.get(Calendar.DAY_OF_YEAR));//类似上一个 //set calendar.set(Calendar.DAY_OF_MONTH,12); int j = calendar.get(Calendar.DAY_OF_MONTH); //12,改变了 System.out.println(j); //add calendar.add(Calendar.DAY_OF_MONTH,3); j = calendar.get(Calendar.DAY_OF_MONTH); //15,还是改变,增加3天 System.out.println(j); //getTime Date date = calendar.getTime(); //Thu Apr 15 03:10:28 CST 2021,返回时间戳 System.out.println(date); //setTime:Date --> Calendar calendar.setTime(date);//直接操作当前对象 int days = calendar.get(Calendar.DAY_OF_MONTH); //15 System.out.println(days);
获取月份时,一月是0;获取星期几时,周日是1
2.2 JDK8中的日期时间
因为之前的类具有4个问题:
- 可变性:例如
Calendar
的set
,它们都是可变的 - 偏移性:
Date
中的年份都是从1900开始,月份从0开始,如果调用有参构造,会发生偏移。 - 格式化:格式化只对
Date
有用,对于Calendar
则不行 - 线程不安全
java8中的java.time API已经纠正了过去的缺陷。
时间日期的相关packge:
LocalDate,
LocalTime,
LocalDateTime是其中比较重要的几个类,他们的实例均为不可变实例,使用
ISO-8601日历系统。
ISO-8601日历系统是国际标准话组织制定的现代公民的日期和时间的表示法(公历)
相关方法:
上面四个层次其实就是构造、get、set、加减操作。和
Calendar类似。
localDate是一个
final类,有构造方法,类似
String,
Math,举例当前时间生成:
LocalDate localDate = LocalDate.now(); //2021-04-27 LocalTime localTime = LocalTime.now(); //19:24:37.171676500 LocalDateTime localDateTime = LocalDateTime.now(); //2021-04-27T19:24:37.171676500
举例设置指定时间:
LocalDateTime localDateTime1 = LocalDateTime.of(2020,10,6,13,12,13);//2020-10-06T13:12:13
举例相关
get操作:
System.out.println(localDateTime.getMonth()); //APRIL System.out.println(localDateTime.getMonthValue()); //4
这里的月份是从1开始的。
.with操作(设置相关属性):
LocalDate localDate1 = localDate.withDayOfMonth(22); //2021-04-22 System.out.println(localDate); //2021-04-27 System.out.println(localDate1);
locatDate实例本身并没有发生变化(不可变性)。
加减操作:
LocalDate localDate2 = localDate.plusDays(4); //localDate为4-27 System.out.println(localDate2 25f4 );//2021-05-01 //减的话即将Plus换位minus
2.3 Instant(瞬时)
时间线上的一个瞬时点,可能用来记录应用程序中的事件时间戳。
同样是起始于1970年1月1日00:00:00的一个时间戳(纳秒级)。
相关方法:
时间标准主要有:UTC, GMT, CST,UTC时间与伦敦本地时间相同,与北京相差8个小时(早了8个小时)
Instant instant = Instant.now(); System.out.println(instant); //2021-04-27T11:45:00.321544Z,实际时间19:45,相差8个小时
偏移应用:
OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8)); System.out.println(offsetDateTime); //2021-04-27T19:48:17.448368100+08:00
返回时间戳(毫秒数):
System.out.println(instant.toEpochMilli());//1619524168468
设置特定时间,和
Date类似:
Instant instant1 = Instant.ofEpochMilli(1619524168468L); //2021-04-27T11:49:28.468Z,这里的时间就是毫秒级的了 System.out.println(instant1);
2.4 DateTimeFormatter
三种预定义的标准格式:
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME; //格式化:日期-->字符串 LocalDateTime localDateTime = LocalDateTime.now(); String str = dateTimeFormatter.format(localDateTime); //将当前时间格式化 System.out.println(str); //2021-04-27T19:59:19.0153049 //解析:字符串-->日期 TemporalAccessor temporalAccessor = dateTimeFormatter.parse("2021-04-27T19:59:19.0153049"); System.out.println(temporalAccessor);//{},ISO resolved to 2021-04-27T19:59:19.015304900
本地化相关的格式:
DateTimeFormatter format = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM); //SHORT 2021/4/27 下午8:09, MEDIUM 2021年4月27日 下午8:10:02, // 在java15中LONG会异常,1.8不会,DateTime中没有FULL,Date中有 String str1 = format.format(localDateTime); System.out.println(str1);
自定义格式(类似于
SimpleDateFormat):
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"); String str1 = format.format(localDateTime); //2021-04-27 08:21:52 System.out.println(str1); TemporalAccessor temporalAccessor1 = format.parse(str1); System.out.println(temporalAccessor1); //{MicroOfSecond=0, HourOfAmPm=8, MilliOfSecond=0, NanoOfSecond=0, MinuteOfHour=21, SecondOfMinute=52},ISO resolved to 2021-04-27
解析同上面即可,注意解析时需要一个
TemporalAccessor转承。
其他的一些API(不再详细赘述):
以上三种
Date之间的转换:
3. 比较器
这里牵扯到对象的比较
实现
Comparable接口(自然排序),重写
compareTo()方法,重写的规则是:当前对象this大于形参对象obj,返回正整数;this小于,返回负整数;this等于,返回0;
使用
Comparator接口(定制排序)
适用于该类型没有实现
Comparable接口,且不方便修改代码;或者实现了
Comparable接口但是排序规则不适合当前操作
对比:
Comparable
接口的方式可以保证类的对象在任何位置都可以实现比较Comparator
接口属于临时性的比较
关于应用在之前的博客中已有实现,可参考
(Set, Map, Collections工具类)JAVA集合框架二
4. System, Math, BigInteger 和 BigDecimal
4.1 System
java.lang.System
成员变量:in, out ,err三个,分别代表标准输入流(键盘输入),标准输出流(显示器),标准错误输出流(显示器)
static long currentTimeMillis()返回当前时间(以毫秒为单位)。表达格式同时间戳。
static void exit(int status)终止当前运行的Java虚拟机。
status为0时代表正常退出,非零则为异常退出。
static void gc()运行垃圾回收器。请求系统进行垃圾回收。
static String getProperty(String key)获取指定键指示的系统属性。对于常用的
key:
4.2 Math
以上为
Math常用方法总结。可见开发文档。
4.3 BigInteger与BigDecimal
BigInteger
构造方法:
BigInteger提供所有java的基本整数操作符的对应物,并提供
java.lang.Math的所有相关方法,另外,还提供一下运算:模算术,GCD计算,质数测试,素数生成,位操作等。
BigDecimal
Float和
Double的精度不能满足用户需求时,可以使用
BigDecimal
构造方法:
BigDecimal(double val)将
double转换为
BigDecimal,这是
double的二进制浮点值的精确十进制表示。
BigDecimal(String val)将BigDecimal的字符串表示
BigDecimal转换为
BigDecimal。
还有很多,只举例了两种常用的。
加减乘除操作类似于
BigInteger,说明一下
devide:
scale即保留多少位小数,上下文设置用的不多不再赘述。
几种舍入模式:
其中,有些翻译不够准确,解释一下:
ROUND_UP,即向上舍。0.1203456789,当精度为3的时候,按照
ROUND_UP模式,结果是0.121
ROUND_DOWN即向下舍。
而
ROUND_HALF_EVEN,像邻近的偶数方向舍。
这几个可以参考对应英文进行理解。
4.4 个人总结的其他类
其实经常用到的还有
Ramdom,生活中经常用到随机数。
例如取一个随机整数。
Random r1 = new Random(); int i = r1.nextInt(100); //取0到100的随机整数,无 100
其他方法都是与之类似的,具体可参考开发文档。
- Java基础学习总结(41)——JPA常用注解
- Java基础学习总结(21)——常用正则表达式列表
- JAVA_SE ----- 基础知识总结-----关键字,标识符,注释,常量
- 2020.7.24Java基础总结9_面向对象5_常用修饰符与内部类
- Java基础学习总结(21)——常用正则表达式列表
- java基础总结20-java常用API(基本类型包装类)
- JAVA基础知识之我的理解5(总结了最近常用的JAVA关键字,拿来分享之)
- Java基础学习总结(60)——Java常用的八种排序算法
- Java基础学习总结(70)——开发Java项目常用的工具汇总
- Java基础知识总结 (一) Object 常用方法
- Java基础语法常用知识点总结:
- 1.22 Java基础总结 最常用冒泡排序
- Java基础学习总结(70)——开发Java项目常用的工具汇总
- 重拾java基础(十一):Eclipse和bean对象三大常用方法总结
- Java基础学习总结(4)——常用正则表达式列表
- EasyDemo*Java SE 基础实用篇(个人总结)
- Java基础学习总结(60)——Java常用的八种排序算法
- 黑马程序员 13 Java基础教学 - 13 - Java常用类总结
- Java基础学习总结(41)——JPA常用注解
- java面试总结-se基础-题目与答案