文章目录
- 常用类
-
- Objects
-
- `equals()`
- `isNull()`
- `requireNonNull()`
- Math
- Arrays
-
- `binarySearch()`
- `toString()`
- `sort()`
- `copyOf()`
- BigDecimal
-
- 概念
- 常用构造方法
- 常用方法
-
- 加减乘除
- 获取对应数字类型
- Date
- DateFormat
-
- `format()`
- `parse()`
- Calendar
-
- ==注意==
- `get()`
- `set()`
- `add()`
- `getTime()`
- `getActualMaxinum()`
- 字符串
-
- String
-
- 存储
- 字符串常量池
-
- ==引申==:为什么要避免“+”拼接?
- 构造方法
-
- `String(byte[] bytes)`
- `String(byte[] bytes,String charsetName)`
- 常用方法
-
- `subString()`
- StringBuilder 和 StringBuffer
常用类
Objects
equals()
equals()
源代码:
public static boolean equals(Object a, Object b) {
return (a == b) || (a != null && a.equals(b));
}
在使用
Objects
的 equals 方法前,我们要保证,我们对比的对象,也重写了 equals 方法
我们之所以不直接使用比对对象重写的 equals 方法,是因为担心比对对象的某一个是 null:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-llpmPxq2-1619949680298)(/Users/faro_z/Library/Application Support/typora-user-images/image-20210430132841642.png)]
使用 Objects.equals(),是会进行空判断的:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oWdQ872h-1619949680300)(/Users/faro_z/Library/Application Support/typora-user-images/image-20210430133002380.png)]
用这个方法来判断 String,可以保证不会出现空指针异常
isNull()
isNull()
判断对象是否为空
public static boolean isNull(Object obj) {
return obj == null;
}
requireNonNull()
requireNonNull()
如果传入的对象为空,抛出异常
public static <T> T requireNonNull(T obj) {
if (obj == null)
throw new NullPointerException();
return obj;
}
Math
这个看 API 文档就好了
Arrays
binarySearch()
binarySearch()
二分查找,其重载很多,具体看 APi 或者代码提示
在使用前,一定要对数组进行排序
toString()
toString()
就是将数组变为字符串
这里,我主要看中源码作者对 for 循环的使用方法
public static String toString(int[] a) {
if (a == null)
return "null";
int iMax = a.length - 1;
if (iMax == -1)
return "[]";
StringBuilder b = new StringBuilder();
b.append('[');
for (int i = 0; ; i++) {
b.append(a[i]);
if (i == iMax)
return b.append(']').toString();
b.append(", ");
}
}
sort()
sort()
顾名思义,就是排序
源码作者使用的是快速排序
public static void sort(int[] a) {
DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);
}
copyOf()
copyOf()
用来为数组进行动态扩容
public static int[] copyOf(int[] original, int newLength) {
int[] copy = new int[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
使用方法如下:
int[] arr={3,6,23,7,0,65,1};
System.out.println(arr.length);
arr = Arrays.copyOf(arr, 20);
System.out.println(arr.length);
System.out.println(Arrays.toString(arr));
BigDecimal
概念
java 中的 double 进行加减法运算,会出现精度问题
这对于有高精度要求的程序,是致命的
而 BigDecimal,就是为了解决这一问题
常用构造方法
public BigDecimal(String val) {
}
常用方法
加减乘除
获取对应数字类型
Date
所有对应方法都已经过时,现在 Date 只有一个作用,就是表示时间
DateFormat
用来格式化时间
一般,都是使用其子类SimpleDateFormat
format()
format()
将 Date()类型,按照指定格式格式化
y : 年
M : 月
d : 日
H : 时
m : 分
s : 秒
S : 毫秒
SimpleDateFormat中,只有占位符的位置会被替换,其他的部分可以按照要求随意填写
parse()
parse()
按照指定格式,解析时间字符串
Calendar
这玩意儿,是为了能通过不同时区,创建时间对象的
我们知道,泰国,日本使用的时间比较特殊,比如说日本,是什么水曜年这些东西,那这些年的表示,就需要使用 Calendar
因为 Calendar 是抽象类,所以,我们要调用 getInstance()方法,去获取对象:
调用 getInstance()构造:
注意
Calendar 的月,是从0开始的,也就是说我们的 5 月,在 Calendar 中,显示的是 4
get()
get()
按照单位,获取数据
Calendar cal = Calendar.getInstance();
int year = cal.get(Calendar.YEAR);
System.out.println(year);
set()
set()
cal.set(Calendar.YEAR,1); //将年份设置为 1
int year = cal.get(Calendar.YEAR);
int month = cal.get(Calendar.MONTH);
System.out.println(year);
System.out.println(month);
add()
add()
按照指定单位,增加年份
Calendar cal = Calendar.getInstance();
System.out.println("当前年份:"+cal.get(Calendar.YEAR));
cal.add(Calendar.YEAR,1);
System.out.println("年份+1后:"+cal.get(Calendar.YEAR));
下面这个实验,说明,calendar 中,月份的范围是0-11
Calendar cal = Calendar.getInstance();
cal.set(Calendar.MONTH,11);
System.out.println("将当前月份设置为 11(实际为 12 月):"+cal.get(Calendar.MONTH));
cal.add(Calendar.MONTH,1);
System.out.println("为月份+1后:"+cal.get(Calendar.MONTH));
getTime()
getTime()
获取日历时间表示的 Date 对象
Calendar cal = Calendar.getInstance();
Date date = cal.getTime();
System.out.println(new SimpleDateFormat("yyyy-MM-dd").format(date));
getActualMaxinum()
getActualMaxinum()
获取当前单位的最大值
获取当前年份的最大月数:
Calendar cal = Calendar.getInstance();
System.out.println(cal.getActualMaximum(Calendar.MONTH));
注意:因为 Calendar 的月,是从 0 开始数的,所以,这里显示的 11,其实是 12 月!!
字符串
String
存储
如果两个字符串内容完全相同,则指向同一个内存区域
字符串常量池
使用字符串常量池的目的,是为了保证字符串的使用效率,不然,频繁的创建和销毁,会影响系统的性能。
字符串常量池在方法区中
下面,给个图示:
String str1 = “abc”;
String str2 = “abc”;
String str3 = “abc”;
String str4 = new String(“abc”);
String str5 = new String(“abc”);
String str6 = new String(“abc”);
了解了上面的知识,我们可以出一个面试题:
面试题:String str4 = new String(“abc”) 创建多少个对象?所以,常量池中没有“abc”字面量则创建两个对象,否则创建一个对象,以及创建一个引用
- 在常量池中查找是否有“abc”对象
- 有则返回对应的引用实例
- 没有则创建对应的实例对象
- 在堆中 new 一个 String(“abc”) 对象
- 将对象地址赋值给str4,创建一个引用
引申:为什么要避免“+”拼接?
假设我们有这么一段代码:
String text1 = "锄禾日当午";
String text2 = "汗滴禾下土";
String text3 = "床前明月光";
text1=text1+text2+text3;
System.out.println(text1);
我们来看看在内存中,是个什么样子:
- 创建完三个新字符串,是这个样子:
- 每次“+”,都要在字符串常量池新申请一个空间
- 不再被使用的区域,成了“垃圾”,(但不会被回收)
text1 在拼接前指向的位置,和拼接中的副产物,因为不会再被引用(除非又有一个新字符串,内容和这两个部分一模一样),所以成了’垃圾’,但是因为字符串常量池是永久代,所以,这些‘垃圾’不会被 GC 回收,会一直存在于内存中。
所以,如果大量使用“+”去拼接字符串的话,久而久之,就会在内存中,产生大量不会去被回收的垃圾,那程序就会越运行,越卡
就是因为上面的原因,很多人用 java 搞爬虫,一旦用了很多“+”操作,就会导致程勋运行占用大量内存
如果要搞字符串拼接,请使用 StringBuffer,或者StringBuilder
构造方法
我们一般直接使用
String str = "aaa"
这种方式创建,但是也会有下面这些方式创建
String(byte[] bytes)
String(byte[] bytes)
通过字节数组创建
String(byte[] bytes,String charsetName)
String(byte[] bytes,String charsetName)
指定编码类型,通过字节数组创建
常用方法
subString()
subString()
获得子串,包头去尾
String str = "abcde";
System.out.println(str.substring(1,2));
StringBuilder 和 StringBuffer
二者的使用其实差不多,区别只是在于线程是否安全
StringBuilder线程不安全,但是效率高
StringBuffer线程安全,但是效率低
我们就那 StringBuilder 举例:
StringBuilder sb = new StringBuilder();
sb.append("锄禾日当午");
sb.append("汗滴禾下土");
System.out.println(sb.toString());
使用
append()
替代 String 中的“+”操作,
append
过程中,产生的垃圾,因为是在新生代,所以会被 GC 回收,这样,就不会造成内存浪费