常用类
常用类
Object类
修饰符和类型 | 方法的描述 |
---|---|
protected Object |
clone() 创建并返回此对象的副本 |
boolean |
equals(Object obj) 指示一些其他对象是否等于此 |
protected void |
finalize() 当垃圾收集确定不再有对该对象的引用时,垃圾收集器在对象上调用该对象 |
Class<?> |
getClass() 返回此 Object 的运行时类 |
int |
hashCode() 返回对象的哈希码值 |
void |
notify() 唤醒正在等待对象监视器的单个线程 |
void |
notifyAll() 唤醒正在等待对象监视器的所有线程 |
String |
toString() 返回对象的字符串表示形式 |
void |
wait() 导致当前线程等待,直到另一个线程调用该对象的 notify() 方法或 notifyAll() 方法 |
void |
wait(long timeout) 导致当前线程等待,直到另一个线程调用 notify() 方法或该对象的 notifyAll() 方法,或者指定的时间已过 |
void |
wait(long timeout, int nanos) 导致当前线程等待,直到另一个线程调用该对象的 notify() 方法或 notifyAll() 方法,或者某些其他线程中断当前线程,或一定量的实时时间 |
equals
1.五种特性
x.equals(x); // 自反性 true
x.equals(y) == y.equals(x); // 对称性,一致性 true
if (x.equals(y) && y.equals(z)) x.equals(z); // 传递性 true
x.equals(null); // 与 null 的比较 false
2.equals方法 和 == 比较运算符 的区别
== :如果判断基本数据类型,判断值是否相同;如果判断引用数据类型,判断的是地址是否相同(是否是同一个对象)
equals:是Object类中的方法,只能用来判断引用数据类型,默认是判断地址是否相同,但是像String类重写了该方法,用来判断字符串值是否相同
// Object类的源码
public boolean equals(Object obj) {
return (this == obj);
}
/**
* String类的源码
* Compares this string to the specified object. The result is {@code
* true} if and only if the argument is not {@code null} and is a {@code
* String} object that represents the same sequence of characters as this
* object.
*/
public boolean equals(Object anObject) {
if (this == anObject) { // 比较地址是否相同
return true;
}
if (anObject instanceof String) { // 判断是否为String 或者 String的父类
String aString = (String)anObject; // 向下转型:目的是为了获得String类的属性和方法
if (!COMPACT_STRINGS || this.coder == aString.coder) {
return StringLatin1.equals(value, aString.value);
}
}
return false;
}
// StringLatin1类的源码 底层就是比较字符数组中每个字符是否相同
@HotSpotIntrinsicCandidate
public static boolean equals(byte[] value, byte[] other) {
if (value.length == other.length) {
for (int i = 0; i < value.length; i++) {
if (value[i] != other[i]) {
return false;
}
}
return true;
}
return false;
}
hashCode
作用:返回该对象的哈希码值(散列值),是为了提高哈希表的性能
注意细节
- 提高具有哈希结构的容器的效率
- 两个引用都指向同一个对象,则哈希值一定相同
- 哈希值主要是根据地址来的,将对象的内部地址转换成一个整数来实现的
toString
默认返回:全类名 + @ + 哈希值十六进制
作用:用于返回该对象的属性信息
// Object源码
// java.lang.Object@16b98e56
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
当直接输出一个对象时,toString方法会被默认的调用
Object o = new Object();
System.out.println(o.toString()); // java.lang.Object@16b98e56
System.out.println(o); //java.lang.Object@16b98e56
clone()
概念:clone() 是 Object 的 protected 方法,它不是 public,一个类不显式去重写 clone(),其它类就不能直接去调用该类实例的 clone() 方法
@HotSpotIntrinsicCandidate
protected native Object clone() throws CloneNotSupportedException;
Cloneable 接口只是规定,如果一个类没有实现 Cloneable 接口又调用了 clone() 方法,将会抛出异常
public class ObjectDemo01 {
public static void main(String[] args) throws CloneNotSupportedException {
cloneImpl clone = new cloneImpl();
clone.clone();
}
}
// 没有实现Cloneable接口,直接调用clone.clone()会出现CloneNotSupportedException异常
class cloneImpl implements Cloneable{
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
// Invoking Object's clone method on an instance that does not implement Cloneable
// Cloneable接口原码
public interface Cloneable {
}
区分浅拷贝和深拷贝
- 浅拷贝:拷贝对象和原始对象的引用类型引用同一个对象
- 深拷贝:拷贝对象和原始对象的引用类型引用不同对象
可以使用重写的方法进行拷贝,但是方式复杂并且有风险,并且还需要类型转换,可以使用拷贝构造函数或者拷贝工厂来拷贝一个对象(例子取自java全栈体系)
public class CloneConstructorExample {
private int[] arr;
public CloneConstructorExample() {
arr = new int[10];
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
}
}
public CloneConstructorExample(CloneConstructorExample original) {
arr = new int[original.arr.length];
for (int i = 0; i < original.arr.length; i++) {
arr[i] = original.arr[i];
}
}
public void set(int index, int value) {
arr[index] = value;
}
public int get(int index) {
return arr[index];
}
}
CloneConstructorExample e1 = new CloneConstructorExample();
CloneConstructorExample e2 = new CloneConstructorExample(e1);
e1.set(2, 222);
System.out.println(e2.get(2)); // 2
finalize
概念:当垃圾回收器确定不存在该对象的更多引用时,由对象的垃圾回收器调用此方法
注意细节
-
当某个对象没有任何引用时,则jvm虚拟机就会来销毁该对象,在销毁该对象前,就会调用该对象的finalize方法
public class person { public person() {} // 该方法已经被废除,不推荐使用 @Override protected void finalize() throws Throwable { System.out.println("我已经被销毁了..."); } } class test{ public static void main(String[] args) { new person(); System.gc(); // 运行垃圾回收器 } } // 显示效果:我已经被销毁了...
-
垃圾回收机制的调用,由系统来决定,我们可以通过System.gc() 主动触发垃圾回收机制
Wrapper类
包装类的分类
包装类 | 基本数据类型 | 直接父类 |
---|---|---|
boolean | Boolean | Object |
char | Character | Object |
byte | Byte | Number |
short | Short | Number |
int | Int | Number |
long | Long | Number |
float | Float | Number |
double | Double | Number |
装箱 & 拆箱
- 手动拆装箱
- 自动拆装箱
// 代码示例
public class Wrapper01 {
public static void main(String[] args) {
// jdk5以前手动装箱&手动拆箱;jdk5之后可以自动拆装箱
// 以Character为例
char name = 'n';
// 手动装箱
// Character ch1 = new Character(name); // 不推荐
Character ch2 = Character.valueOf(name);
// 手动拆箱
char name2 = Character.valueOf(ch2); // 本质就是使用charValue方法
char name3 = ch1.charValue();
// 自动装箱
Character ch3 = name; // 本质使用的就是valueOf方法
// 自动拆箱
char CH4 = ch3; // 本质就是使用charValue方法
}
}
底层分析
缓冲池(重点!!!)
基本类型对应的缓冲池如下:
- boolean :true and false
- byte :all values
- short : between -128 and 127
- int :between -128 and 127
- char :in the range \u0000 to \u007F
在使用这些基本类型对应的包装类型时,就可以直接使用缓冲池中的对象。
// 以Integer为例
// new Integer(1) 与 Integer.valueOf(1)或者数值1 的区别在于:
// 1.new Integer(123) 每次都会新建一个对象
// 2.Integer.valueOf(123) 会使用缓存池中的对象,多次调用会取得同一个对象的引用
System.out.println(new Integer(1) == new Integer(1)); // false
Integer a = 1;
Integer b = 1;
System.out.println(a==b); // true
Integer a = Integer.valueOf(1);
Integer b = Integer.valueOf(1);
System.out.println(a==b); // true
缓冲池源码分析
// 以Integer为例 jdk1.8中缓存池的大小默认为 -128~127
static final int low = -128;
static final int high;
static final Integer cache[];
static {
// high value may be configured by property
// 最大值会根据配置数据而改变,但是h的值至少大于127 Math.max(i, 127);
int h = 127;
String integerCacheHighPropValue =
sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");
if (integerCacheHighPropValue != null) {
try {
int i = parseInt(integerCacheHighPropValue);
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - (-low) -1);
} catch( NumberFormatException nfe) {
// If the property cannot be parsed into an int, ignore it.
}
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
// 静态初始化所有在缓冲池内的数据
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
// range [-128, 127] must be interned (JLS7 5.1.7)
assert IntegerCache.high >= 127;
}
String类
概述
是一组字符序列 本质上是char[] value 字符数组实现
public static void main(String[] args) {
/*
* "Al_tair"被称为字符常量 用双引号括起来的字符序列
* 一个字符占用两个字节(每个字符不区分字母和汉字)
*/
String name = "Al_tair";
}
// public final class String 说明String的final类,不能被其它类继承
// private final byte[] value 用于存放字符串 value是用final修饰的类型,该数组不能指向新地址,但是能修改它的值
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
/** The value is used for character storage. */
private final char value[];
}
接口和构造器
String内存图
// 运行代码,内存图如下
class code{
public static void main(String[] args){
String a = "Al_tair";
String b = new String("Al_tair");
}
}
字符串 VS 字符数组
结合代码和内存图分析
class Text{
String str = new String("lns");
// final指的是char类型数据存储的地址不能改变,但是值是可以改变的
final char[] ch = {'j','a','v','a'};
public void change(String str,char[] ch){
str = "zlr";
ch[1] = 'c';
}
public static void main(String[] args) {
Text text = new Text();
text.change(text.str,text.ch);
System.out.println(text.str.toString()+" and "+text.ch[1]); // lnsandc
}
}
String类的常用方法
- equals 区别大小写,判断字符串的内容是否相同
- equalsIgnoreCase 忽略大小写 来判断字符串的内容是否相同
- length 获取字符串的个数,或者称为字符串长度
- indexOf 获取字符在字符串中第一次出现的索引,索引从0开始,如果没有找到则返回-1
- lastindexOf 获取字符在字符串中最后一次出现的索引,索引从0开始,如果没有找到则返回-1
- substring 截取指定范围的字串
- trim 去掉字符串前后的空格
- charAt 获取某索引处的字符
- compareTo 比较两个字符串的大小,如果前者大于等于后者,则返回自然数;反之后者大,则返回负数
- intern 如果常量池中已经包含值相同的字符串,则返回常量池中的字符串引用地址,否则将String对象添加到常量池中,并返回String对象的引用
// intern 方法的使用
String a = "l";
String b = new String("l");
System.out.println(a.equals(b)); // true
System.out.println(a == b); // false
System.out.println(a == b.intern()); // true
System.out.println(b == b.intern()); // false
// equals()方法源码
public boolean equals(Object anObject) {
if (this == anObject) { // 地址是否相同
return true;
}
if (anObject instanceof String) { // 是否为String类或者String父类
String aString = (String)anObject;
if (!COMPACT_STRINGS || this.coder == aString.coder) {
return StringLatin1.equals(value, aString.value);
}
}
return false;
}
@HotSpotIntrinsicCandidate
public static boolean equals(byte[] value, byte[] other) {
if (value.length == other.length) {
for (int i = 0; i < value.length; i++) {
if (value[i] != other[i]) {
return false;
}
}
return true;
}
return false;
}
// 占位符的讲解 涉及方法format <=> c语言输出
// %s,%d,%.3f,%c
String name = "lns";
int age = 18;
double height = 185.35;
char gender = '男';
String Info = "姓名:%s\t年龄:%d\t身高:%.3f\t性别:%c";
String show = String.format(Info,name,age,height,gender);
System.out.println(show); // 姓名:lns 年龄:18 身高:185.350 性别:男
包装类 <=> String类
public class WrapperVsString {
public static void main(String[]args){
// String类 转换成 包装类
String age = "120";
Integer age2 = Integer.valueOf(age); // 方式一:valueOf函数 本质上就是parseInt()方法
Integer a2 = Integer.parseInt(age); // 方式二:parseInt函数
Integer age3 = new Integer(age); //不推荐,本质就是parseInt()方法
// 包装类 转换成 String类
Integer height = 180; // 自动装箱
String h = String.valueOf(height); // 方式一:valueOf函数 本质就是调用toString()方法
String h2 = height + ""; // 方式二: 类型转换 Integer + ""
String h3 = height.toString(); // 方式三: toString()函数
/*
* String.valueOf()源码
* public static String valueOf(Object obj) {
* return (obj == null) ? "null" : obj.toString();
* }
*
* Integer.valueOf()源码
* public static Integer valueOf(String s) throws NumberFormatException {
* return Integer.valueOf(parseInt(s, 10)); // 10指的是传入的数字是十进制数
* }
*
* new Integer()源码
* @Deprecated(since="9")
* public Integer(String s) throws NumberFormatException {
* this.value = parseInt(s, 10);
* }
*/
}
}
StringBuffer类
概念:代表可变的字符序列,可以对字符串内容进行增删,是一个容器
构造方法
Constructor and Description |
---|
StringBuffer() 构造一个没有字符的字符串缓冲区,初始容量为16个字符。 |
StringBuffer(CharSequence seq) 构造一个包含与指定的相同字符的字符串缓冲区 CharSequence 。 |
StringBuffer(int capacity) 构造一个没有字符的字符串缓冲区和指定的初始容量。 |
StringBuffer(String str) 构造一个初始化为指定字符串内容的字符串缓冲区。 |
/*
* Constructs a string buffer with no characters in it and an
* initial capacity of 16 characters.
* StringBuffer()构造器
*/
@HotSpotIntrinsicCandidate
public StringBuffer() {
super(16); // 初始容量为16个字符 存储在父类的value数组中
}
常用方法
修饰符和类型 | 方法和描述 |
---|---|
StringBuffer |
append(String str) 将指定的字符串附加到此字符序列 |
StringBuffer |
delete(int start, int end) 删除此序列的子字符串中的字符 |
int |
length() 返回长度(字符数) |
StringBuffer |
replace(int start, int end, String str) 用指定的String中的字符替换此序列的子字符串中的 String |
int |
indexOf(String str) 返回指定子字符串第一次出现的字符串内的索引 |
public static void main(String[] args) {
// 常用方法
// append 增
StringBuffer stringBuffer = new StringBuffer("");
stringBuffer.append("lns"); // lns
/*
* append源码
* 不管传入什么数据类型,返回StringBuffer类型
* public synchronized StringBuffer append(String str) {
* toStringCache = null;
* super.append(str);
* return this;
* }
*/
// delete 删除
// 删除索引范围 [start,end)
stringBuffer.delete(0,1); // 删除第一个字符 ns
// replace 替换
// 替换范围[start,end)
stringBuffer.replace(0, 1,"ln"); // lns
// indexOf 查找
// 查找第一次在字符串中出现的索引,如果查找到会返回你查找的字符串首个字母索引,如果找不到返回-1
stringBuffer.indexOf("ns"); // 1
// length 长度
System.out.println(stringBuffer.length()); // 3
}
StringBuffer底层分析
添加null字符串
String str = null;
StringBuffer sb = new StringBuffer();
sb.append(str);
System.out.println(sb); // null
System.out.println(sb.length()); // 4
/*
* // 底层分析
* // StingBuffer类
* public synchronized StringBuffer append(String str) {
* toStringCache = null;
* super.append(str); // 跳转到父类
* return this;
* }
* // AbstractStringBuilder抽象类
* public AbstractStringBuilder append(String str) {
* if (str == null) {
* return appendNull(); // 跳转到该方法
* }
* int len = str.length();
* ensureCapacityInternal(count + len);
* putStringAt(count, str);
* count += len;
* return this;
* }
* // appendNull方法
* private AbstractStringBuilder appendNull() {
* ensureCapacityInternal(count + 4);
* int count = this.count;
* byte[] val = this.value;
* if (isLatin1()) {
* val[count++] = 'n';
* val[count++] = 'u';
* val[count++] = 'l';
* val[count++] = 'l';
* } else {
* count = StringUTF16.putCharsAt(val, count, 'n', 'u', 'l', 'l');
* }
* this.count = count;
* return this;
* }
*/
StringBuffer sb = new StringBuffer(str); // 抛出空指针异常 NullPointerException
/*
* AbstractStringBuilder(String str) {
* int length = str.length(); // str为null
* int capacity = (length < Integer.MAX_VALUE - 16)
* ? length + 16 : Integer.MAX_VALUE;
* final byte initCoder = str.coder();
* coder = initCoder;
* value = (initCoder == LATIN1)
* ? new byte[capacity] : StringUTF16.newBytesFor(capacity);
* append(str);
* }
*/
字符串拼接
// 创建了几个对象 答:3 结论:字符串常量相加地址存放在常量池,字符串变量相加地址存放在String对象中
// sum 指向的是value[](String对象),再指向常量池中"HelloString"字符串
public static void main(String[]args){
String m = "Hello";
String n = "String";
/*
* 解读:
* 1. 创建新对象 new StringBuilder();
* 2. 通过append函数添加字符串 “Hello”
* 3. 通过append函数添加字符串 “String”
* 4. 返回new String("HelloString");
*/
String sum = m + n;
}
// 分析sum 的指向和底层源码
// debug test
// first insert
public StringBuilder() {
super(16);
}
//secong insert str = "Hello"
public StringBuilder append(String str) {
super.append(str);
return this;
}
// third insert str = "String"
public StringBuilder append(String str) {
super.append(str);
return this;
}
// last one
public String toString() {
// Create a copy, don't share the array
return isLatin1() ? StringLatin1.newString(value, 0, count): StringUTF16.newString(value, 0, count);
}
String <=> StringBuffer
String类和StringBuffer类的区别
- String保存的是字符串常量,里面的值不能更改,每次值的更新实际上就是更改地址,效率低
- Stringbuffer保存的是字符串变量,里面的值是可以改变的,不需要每次都更改地址,效率高
String类和StringBuffer类的相互转换
public static void main(String[] args) {
// String和StringBuffer的相互转换
// String => StringBuffer
String str = "lns";
StringBuffer stringBuffer = new StringBuffer(str); // 方式一: 使用StringBuffer构造器
StringBuffer append = new StringBuffer().append(str); // 方式二: 使用的是append方法
// StringBuffer => String
StringBuffer sbr = new StringBuffer("zlr");
String s = sbr.toString(); // 方式一: 使用toString方法
String s1 = new String(sbr); // 方式二:使用String构造器
}
StringBuilder类
概念:一个可变的字符序列。 线程不安全。 此类设计用作简易替换为StringBuffer
在正在使用由单个线程字符串缓冲区的地方。 在可以的情况下,建议使用这个类别优先于StringBuffer
,因为它在大多数实现中将更快。
常用方法大部分与 StringBuffer类似
特殊点:没有做互斥处理,因此在单线程下使用
// 源码剖析 区别在于关键字 synchronized 保证线程安全
// StringBuffer 的append方法
@Override
@HotSpotIntrinsicCandidate
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
// StringBuilder 的append方法
@Override
@HotSpotIntrinsicCandidate
public StringBuilder append(String str) {
super.append(str);
return this;
}
String,StringBuffer,StringBuilder的区别
- String:不可变字符序列,效率低,但是因为存在常量池所以复用率高,String 不可变,因此是线程安全的
- StringBuffer:可变字符序列,效率较高(增删),线程安全
- StringBuilder:可变字符序列,效率最高,线程不安全
使用原则
- 如果字符串存在大量的修改操作,一般使用StringBuffer或者StringBuider
- 如果字符串存在大量的修改操作,并在单线程的情况,使用StringBuilder
- 如果字符串存在大量的修改操作,并在多线程的情况,使用StringBuffer
- 如果字符串很少修改,被多个对象引用,使用String 比如:配置信息等
Math类
概念:Math类包含执行基本数学运算的方法
常用方法
public static void main(String[] args) {
// Math类中大部分是静态方法,可以直接通过类名.方法名访问
// abs 绝对值
int abs = Math.abs(-10);
System.out.println(abs); // 10
// pow 求幂
double pow = Math.pow(2,4);
System.out.println(pow); // 16.0
// ceil 向上取整,返回>=该参数的最小整数(整数会转换成double型)
double ceil = Math.ceil(-3.002);
System.out.println(ceil); // -3.0
// floor 向下取整,返回<=该参数的最大整数(整数会转换成double型)
double floor = Math.floor(3.2);
System.out.println(floor); // 3.0
// round 四舍五入 <=> Math.floor(参数+0.5)
double round = Math.round(3.24);
System.out.println(round); // 3.0
// sqrt 求开平方
double sqrt = Math.sqrt(4);
System.out.println(sqrt); // 2.0
// random 随机数 [0,1)
int random = (int)(Math.random()*50+50);
System.out.println(random); // 整数范围 [50,100)
}
Arrays类
概念:该类包含用于操作数组的各种方法(如排序和搜索),大部分方法也是静态方法
常用方法
toString方法
作用:将数组的值按照一定格式以字符串的方式输出
// 测试代码
public static void main(String[] args) {
Integer[] array1 = null;
System.out.println(Arrays.toString(array1)); // null
Integer[] array2 = {};
System.out.println(Arrays.toString(array2)); // []
Integer[] array3 = new Integer[3];
System.out.println(Arrays.toString(array3)); // [null,null,null]
Integer[] array4 = {3,5,6,47,8};
System.out.println(Arrays.toString(array4)); // [3, 5, 6, 47, 8]
}
// toString方法源码(以整数数组为例)
// 1.数组为null Integer[] array = null;
// 2.数组为空 Integer[] array = {};
// 3.底层使用StringBuider来拼接数组值,并且转换成String
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重载,可以通过传入一个接口Comparator实现定制排序
Integer[] array = {3,5,6,47,8};
Arrays.sort(array);
System.out.println(Arrays.toString(array)); // [3, 5, 6, 8, 47]
Arrays.sort(array,new Comparator(){
@Override
public int compare(Object o1, Object o2) {
Integer i1 = (Integer)o1;
Integer i2 = (Integer)o2;
return i2 - i1; // 决定是升序还是降序
}
});
System.out.println(Arrays.toString(array)); // [47, 8, 6, 5, 3]
// MySort的冒泡实现
public class MySort {
public static void main(String[] args) {
int[] arr = {6,4,5,6,845,4,51};
bubble(arr, new Comparator() {
@Override
public int compare(Object o1, Object o2) {
int i1 = (Integer)o1;
int i2 = (Integer)o2;
return i1 - i2;
}
});
System.out.println(Arrays.toString(arr));
}
public static void bubble(int[] arr, Comparator c){
int temp = 0;
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - 1 - i; j++) {
if(c.compare(arr[j],arr[j+1]) >= 0){ // 动态绑定机制
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
}
binarySearch方法
作用:通过二分搜索法进行查找,要求必须升序,如果数组中不存在,则返回 -(low + 1)
Integer[] array = {3,5,6,47,8};
Arrays.sort(array); // [3, 5, 6, 8, 47]
int index = Arrays.binarySearch(array,9);
System.out.println(index); // -5 应该在索引4位置(8和471之间),返回-(4+1)
// binarySearch 源码
public static int binarySearch(int[] a, int fromIndex, int toIndex,
int key) {
rangeCheck(a.length, fromIndex, toIndex);
return binarySearch0(a, fromIndex, toIndex, key);
}
// Like public version, but without range checks.
private static int binarySearch0(int[] a, int fromIndex, int toIndex,
int key) {
int low = fromIndex;
int high = toIndex - 1;
while (low <= high) {
// 无符号右移,按位右移补零操作符
// >>> 操作符运算 要快于加减乘除运算
int mid = (low + high) >>> 1;
int midVal = a[mid];
if (midVal < key)
low = mid + 1;
else if (midVal > key)
high = mid - 1;
else
return mid; // key found
}
return -(low + 1); // key not found.
}
其他方法
// copeOf 数组的赋值 如果赋值的长度大于原数组的长度,则多余的数据用null填入
Integer[] integers = Arrays.copyOf(array, array.length-1);
System.out.println(Arrays.toString(integers)); // [3, 5, 6, 8]
// fill 数组的填充 替换数组中的所有数据
int[] fillNum = {2,45,78,85,15};
Arrays.fill(fillNum,2);
System.out.println(Arrays.toString(fillNum)); // [2, 2, 2, 2, 2]
// equals 比较两个数组元素内容是否相同
int[] equalsNum = {2,45,78,85,15};
int[] equalsNum2 = {2,45,78,85,15};
System.out.println(Arrays.equals(equalsNum,equalsNum2)); // true
System类
概念:System
类包含几个有用的类字段和方法。 它不能被实例化。
常用方法
public static void main(String[] args) {
// gc方法:调用垃圾回收器
new System01();
System.gc();
// currentTimeMillis方法:在1970年1月1日UTC之间的当前时间和午夜之间的差异,以毫秒为单位
System.out.println(System.currentTimeMillis()); // 1645776480314
// arraycopy方法:复制数组(深拷贝)
int[] src = {1,2,3};
int[] desc = {0,0,0};
/*
* 从左到右的五个参数描述
* src the source array. 被复制内容的数组
* srcPos starting position in the source array. 源数组索引位置(从哪个位置开始拷贝)
* dest the destination array. 复制内容得到的数组
* destPos starting position in the destination data. 目标数组的索引位置
* length the number of array elements to be copied. 拷贝的数组长度
*/
System.arraycopy(src,0,desc,0,3);
System.out.println(Arrays.toString(desc)); //[1, 2, 3]
System.out.println(src == desc); // false
// exit方法:退出程序
System.out.println("程序开始");
// System.exit(0)是正常退出程序,而System.exit(1)或者说非0表示非正常退出程序
System.exit(0);
System.out.println("程序结束"); // 不执行
}
@Override
protected void finalize(){
System.out.println("我已经被销毁了");
}
BigIneger和BigDecimal类
概念:BigIneger 适合保存比较大的整型数据;BigDecimal 适合保存精度更高的浮点型数据
常用方法
// BigIneger 适合保存比较大的整型数据 long数据类型无法存储
BigInteger bigInteger = new BigInteger("998456349564561256465489");
System.out.println(bigInteger); // 998456349564561256465489
// + - * / 运算 => 方法实现 add subtract multiply divide
bigInteger = bigInteger.add(new BigInteger("1"));
System.out.println(bigInteger); // 998456349564561256465490
bigInteger = bigInteger.divide(new BigInteger("2"));
System.out.println(bigInteger); // 499228174782280628232745
bigInteger = bigInteger.subtract(new BigInteger("2"));
System.out.println(bigInteger); // 499228174782280628232743
bigInteger = bigInteger.multiply(new BigInteger("2"));
System.out.println(bigInteger); // 998456349564561256465486
// BigDecimal 适合保存精度更高的浮点数 double数据类型无法存储
BigDecimal bigDecimal = new BigDecimal("9980.2561295645485648548485646541");
System.out.println(bigDecimal); // 9980.2561295645485648548485646541
// + - * / 运算 => 方法实现 add subtract multiply divide
bigDecimal = bigDecimal.add(new BigDecimal("1"));
System.out.println(bigDecimal); // 9981.2561295645485648548485646541
bigDecimal = bigDecimal.divide(new BigDecimal("2")); // 如果除不尽则返回算术异常
System.out.println(bigDecimal); // 4990.62806478227428242742428232705
bigDecimal = bigDecimal.subtract(new BigDecimal("2"));
System.out.println(bigDecimal); // 4988.62806478227428242742428232705
bigDecimal = bigDecimal.multiply(new BigDecimal("2"));
System.out.println(bigDecimal); // 9977.25612956454856485484856465410
// 解决小数除法异常问题:指定精度(JDK9以后不建议使用)
bigDecimal = bigDecimal.divide(new BigDecimal("2.3326"),BigDecimal.ROUND_CEILING);
System.out.println(bigDecimal); // 4277.31121047952866537548167909376
源码分析BigIneger
// BigIneger 适合保存比较大的整型数据 long数据类型无法存储
BigInteger bigInteger = new BigInteger("998456349564561256465489");
System.out.println(bigInteger); // 998456349564561256465489
// 源码分析
public BigInteger(String val) {
this(val, 10); // 默认十进制
}
public BigInteger(String val, int radix) {
int cursor = 0, numDigits;
final int len = val.length();
if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
throw new NumberFormatException("Radix out of range");
if (len == 0)
throw new NumberFormatException("Zero length BigInteger");
// 检查符号
int sign = 1;
int index1 = val.lastIndexOf('-');
int index2 = val.lastIndexOf('+');
if (index1 >= 0) {
if (index1 != 0 || index2 >= 0) {
throw new NumberFormatException("Illegal embedded sign character");
}
sign = -1;
cursor = 1;
} else if (index2 >= 0) {
if (index2 != 0) {
throw new NumberFormatException("Illegal embedded sign character");
}
cursor = 1;
}
if (cursor == len)
throw new NumberFormatException("Zero length BigInteger");
// Skip leading zeros and compute number of digits in magnitude
while (cursor < len &&
Character.digit(val.charAt(cursor), radix) == 0) {
cursor++;
}
if (cursor == len) {
signum = 0;
mag = ZERO.mag;
return;
}
numDigits = len - cursor;
signum = sign;
// 预分配预期大小的数组。可能太大,但永远不能太小,通常是准确的
long numBits = ((numDigits * bitsPerDigit[radix]) >>> 10) + 1;
if (numBits + 31 >= (1L << 32)) {
reportOverflow();
}
int numWords = (int) (numBits + 31) >>> 5;
int[] magnitude = new int[numWords];
// Process first (potentially short) digit group
int firstGroupLen = numDigits % digitsPerInt[radix];
if (firstGroupLen == 0)
firstGroupLen = digitsPerInt[radix];
String group = val.substring(cursor, cursor += firstGroupLen);
magnitude[numWords - 1] = Integer.parseInt(group, radix);
if (magnitude[numWords - 1] < 0)
throw new NumberFormatException("Illegal digit");
// Process remaining digit groups
int superRadix = intRadix[radix];
int groupVal = 0;
while (cursor < len) {
group = val.substring(cursor, cursor += digitsPerInt[radix]);
groupVal = Integer.parseInt(group, radix);
if (groupVal < 0)
throw new NumberFormatException("Illegal digit");
destructiveMulAdd(magnitude, superRadix, groupVal);
}
// Required for cases where the array was overallocated.
mag = trustedStripLeadingZeroInts(magnitude);
if (mag.length >= MAX_MAG_LENGTH) {
checkRange();
}
}
日期类
第一代日期类
Date:精确到毫秒,代表瞬间
SimpleDateFormat:格式和解析日期类(日期 <=> 文本)
public static void main(String[] args) throws ParseException {
// Date 日期类
Date date = new Date(); // 当前日期
System.out.println(date); // Mon Apr 25 11:49:31 CST 2022
Date date2 = new Date(4564956); // 输入距离1970年1月1日的毫秒数
System.out.println(date2); // Thu Jan 01 09:16:04 CST 1970
// SimpleDateFormat 格式和解析日期类 按照自己的格式的日期 年 月 日 时 分 秒 星期
SimpleDateFormat sdf = new SimpleDateFormat("YYYY年MM月dd日 hh:mm:ss E");
System.out.println(sdf.format(date)); // 2022年04月25日 11:28:41 周一
String dateStr = "2021年02月26日 05:07:32 周一";
System.out.println(sdf.format(sdf.parse(dateStr))); // 2021年12月28日 05:07:32 周一
}
SimpleDateFormat的规定格式
第二代日期类
Calendar类(日历) 是一个抽象类
// 抽象类 可以通过getInstance方法获取实例
Calendar calendar = Calendar.getInstance();
System.out.println("年:"+calendar.get(calendar.YEAR)); // 年:2022
System.out.println("月:"+calendar.get(calendar.MONTH)+1); // 月:2 源码:JANUARY} which is 0
System.out.println("日:"+calendar.get(calendar.DAY_OF_MONTH)); // 日:25
System.out.println("小时:"+calendar.get(calendar.HOUR)); // 小时:8
System.out.println("分钟:"+calendar.get(calendar.MINUTE)); // 分钟:11
System.out.println("秒:"+calendar.get(calendar.SECOND)); // 秒:46
第三代日期类 (JDK8)
LocalDate 日期:年月日
LocalTime 时间:时分秒
LocalDateTime:年月日 时分秒
LocalDateTime localDateTime = LocalDateTime.now();
LocalTime localTime = LocalTime.now();
LocalDate localDate = LocalDate.now();
// localDateTime: 2022-02-25T20:30:19.250574
// LocalDate: 2022-02-25
// LocalTime: 20:30:19.250574
System.out.println("localDateTime: "+localDateTime+" LocalTime: "+
localTime+" LocalDate: "+localDate);
System.out.println("年: "+localDateTime.getYear()); // 年: 2022
System.out.println("月: "+localDateTime.getMonth()); // 月: FEBRUARY
System.out.println("日: "+localDateTime.getDayOfMonth()); // 日: 25
System.out.println("时: "+localDateTime.getHour()); // 时: 20
System.out.println("分: "+localDateTime.getMinute()); // 分: 33
System.out.println("秒: "+localDateTime.getSecond()); // 秒: 45
DateTimeFormatter格式日期类
// DateTimeFormatter 格式日期类
LocalDateTime localDateTime = LocalDateTime.now();
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("YYYY年MM月dd日 hh:mm:ss E");
System.out.println(dateTimeFormatter.format(localDateTime)); // 2022年04月25日 11:28:41 周一
所有字母“A”至“Z”和“a”至“z”保留为图案字母。 定义了以下图案字母:
Symbol Meaning Presentation Examples
------ ------- ------------ -------
G era text AD; Anno Domini; A
u year year 2004; 04
y year-of-era year 2004; 04
D day-of-year number 189
M/L month-of-year number/text 7; 07; Jul; July; J
d day-of-month number 10
Q/q quarter-of-year number/text 3; 03; Q3; 3rd quarter
Y week-based-year year 1996; 96
w week-of-week-based-year number 27
W week-of-month number 4
E day-of-week text Tue; Tuesday; T
e/c localized day-of-week number/text 2; 02; Tue; Tuesday; T
F week-of-month number 3
a am-pm-of-day text PM
h clock-hour-of-am-pm (1-12) number 12
K hour-of-am-pm (0-11) number 0
k clock-hour-of-am-pm (1-24) number 0
H hour-of-day (0-23) number 0
m minute-of-hour number 30
s second-of-minute number 55
S fraction-of-second fraction 978
A milli-of-day number 1234
n nano-of-second number 987654321
N nano-of-day number 1234000000
V time-zone ID zone-id America/Los_Angeles; Z; -08:30
z time-zone name zone-name Pacific Standard Time; PST
O localized zone-offset offset-O GMT+8; GMT+08:00; UTC-08:00;
X zone-offset 'Z' for zero offset-X Z; -08; -0830; -08:30; -083015; -08:30:15;
x zone-offset offset-x +0000; -08; -0830; -08:30; -083015; -08:30:15;
Z zone-offset offset-Z +0000; -0800; -08:00;
p pad next pad modifier 1
' escape for text delimiter
'' single quote literal
[ optional section start
] optional section end
# reserved for future use
{ reserved for future use
} reserved for future use
Instant 时间戳
// Instant -> Date
Instant instant = Instant.now();
System.out.println(instant); // 2022-02-25T14:48:47.557358800Z
java.util.Date from = Date.from(instant);
System.out.println(from); // Fri Feb 25 22:48:47 CST 2022
// Date -> Instant
Instant instant1 = from.toInstant();
System.out.println(instant1); // 2022-02-25T14:55:27.377Z