Object
Object 类是所有类的父类,也就是说 Java 中所有的类都默认继承 Object,子类可以使用 Object 的所有方法。
public class Test {
}
相当于
public class Test extends Object {
}
Object 类是类层次结构的根,Object 类是 Java 中唯一没有父类的类。
clone()
clone() 方法用于创建并返回一个对象的拷贝。
clone() 方法是浅拷贝,对象内属性引用的对象只会拷贝引用地址,而不会将引用的对象重新分配内存,相对应的深拷贝则会连引用的对象也重新创建。
public class Test implements Cloneable {
String name;
int age;
public static void main(String[] args) throws CloneNotSupportedException {
Test obj1 = new Test();
obj1.name = "jason";
obj1.age = 18;
System.out.println(obj1.name); // jason
System.out.println(obj1.age); // 18
// 创建 obj1 的拷贝
Test obj2 = (Test) obj1.clone();
System.out.println(obj2.name); // jason
System.out.println(obj2.age); // 18
}
}
toString()
toString() 方法用于返回对象的字符串表示形式。
默认返回格式:对象的 class 名称 + @ + hashCode 的十六进制字符串。
public class Test {
public static void main(String[] args) {
Object obj1 = new Object();
System.out.println(obj1.toString()); // java.lang.Object@1b6d3586
Object obj2 = new Object();
System.out.println(obj2.toString()); // java.lang.Object@4554617c
// 数组元素值返回一个字符串的表达式
String[] arr = {"a", "b", "c"};
System.out.println(arr[0].toString()); // a
System.out.println(arr[1].toString()); // b
}
}
也可重写 toString() 方法
public class Test {
public static void main(String[] args) {
Test test = new Test();
System.out.println(test.toString()); // Test
}
public String toString() {
return "Test";
}
}
getClass()
getClass() 方法用于获取对象的运行时对象的类。
public class Test {
public static void main(String[] args) {
Object obj = new Object();
System.out.println(obj.getClass()); // class java.lang.Object
String str = new String();
System.out.println(str.getClass()); // class java.lang.String
Test test = new Test();
System.out.println(test.getClass()); // class Test
}
}
equals()
equals() 方法用于比较两个对象是否相等。
equals() 方法是直接判断 this 和 obj 本身的值是否相等,即用来判断调用equals的对象和形参 obj 所引用的对象是否是同一对象,所谓同一对象就是指内存中同一块存储单元,如果 this 和 obj 指向的hi同一块内存对象,则返回true,如果 this 和 obj 指向的不是同一块内存,则返回 false。
注意:即便是内容完全相等的两块不同的内存对象,也返回 false。
public class Test {
public static void main(String[] args) {
// 比较两个对象
Object obj1 = new Object();
Object obj2 = new Object();
// 不同对象,内存地址不同,不相等,返回 false
System.out.println(obj1.equals(obj2)); // false
// 对象引用,内存地址相同,相等,返回 true
Object obj3 = obj1;
System.out.println(obj1.equals(obj3)); // true
// String 类重写了 equals() 方法,用于比较两个字符串是否相等
String str1 = new String();
String str2 = new String();
System.out.println(str1.equals(str2)); // true
System.out.println(str1 == str2); // false
str1 = "a";
str2 = "a";
System.out.println(str1.equals(str2)); // true
System.out.println(str1 == str2); // true
}
}
== 和 equals() 方法的区别
- == 可以比较两个基本数据类的变量的值是否相等,也可以比较对象的首地址是否相同。
- equals() 方法只能比较对象的首地址是否相同。
hashCode()
hashCode() 方法用于获取对象的 hash 值。
hashCode() 方法用于哈希查找,可以减少在查找中使用 equals() 的次数,重写了equals方法一般都要重写 hashCode() 方法。这个方法在一些具有哈希功能的 Collection 中用到。
import java.util.ArrayList;
public class Test {
public static void main(String[] args) {
Object obj1 = new Object();
Object obj2 = new Object();
System.out.println(obj1.hashCode()); // 460141958
System.out.println(obj2.hashCode()); // 1163157884
String str = new String();
System.out.println(str.hashCode()); // 0
ArrayList<Integer> arr = new ArrayList<>();
System.out.println(arr.hashCode()); // 1
}
}
一般必须满足 obj1.equals(obj2) == true
。可以推出 obj1.hash Code() == obj2.hashCode()
,但是hashCode 相等不一定就满足 equals。不过为了提高效率,应该尽量使上面两个条件接近等价。
wait()
wait() 方法让当前线程进入等待状态。直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法。
notify() 唤醒在该对象上等待的某个线程。
notifyAll() 唤醒在该对象上等待的所有线程。
import java.util.Date;
class WaitTest {
public static void main(String[] args) {
ThreadA threadA = new ThreadA("threadA");
synchronized (threadA) {
try {
// 启动线程
threadA.start();
System.out.println(Thread.currentThread().getName() + " wait() " + new Date());
// 主线程等待 ta 通过 notify 唤醒。
threadA.wait();// 不是使ta线程等待,而是当前执行 wait 的线程等待
System.out.println(Thread.currentThread().getName() + " continue " + new Date());
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
class ThreadA extends Thread {
public ThreadA(String name) {
super(name);
}
@Override
public void run() {
synchronized (this) {
try {
Thread.sleep(1000); // 使当前线程阻塞1秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " call notify()");
this.notify();
}
}
}
输出结果:
main wait() Sat Jul 24 13:03:57 CST 2021
threadA call notify()
main continue Sat Jul 24 13:03:58 CST 2021
finalize()
finalize() 方法用于实例被垃圾回收器回收的时触发的操作。
class Test {
public static void main(String[] args) {
User u1 = new User(1);
User u2 = new User(2);
User u3 = new User(3);
u2 = u3 = null;
System.gc();
}
}
class User {
private int id;
public User(int id) {
this.id = id;
System.out.println("User Object " + id + " is created");
}
protected void finalize() throws java.lang.Throwable {
super.finalize();
System.out.println("User Object " + id + " is disposed");
}
}
关于垃圾回收:
-
对象可能不被垃圾回收。只要程序没有濒临存储空间用完的那一刻,对象占用的空间就总也得不到释放。
-
垃圾回收并不等于 “析构”。
-
垃圾回收只与内存有关。使用垃圾回收的唯一原因是为了回收程序不再使用的内存。
finalize() 的用途:
无论对象是如何创建的,垃圾回收器都会负责释放对象占据的所有内存。
这就将对 finalize() 的需求限制到一种特殊情况,即通过某种创建对象方式以外的方式为对象分配了存储空间。不过这种情况一般发生在使用 “本地方法” 的情况下,本地方法是一种在 Java 中调用非 Java 代码的方式。
String
在 Java 中字符串属于对象,Java 提供了 String 类来创建和操作字符串。
创建方式
class Test {
public static void main(String[] args) {
// 直接赋值方式创建对象是在方法区的常量池
String str1 = "hello";
// 通过构造方法创建字符串对象是在堆内存
String str2 = new String("hello");
// 引用传递,str3 直接指向 st2 的堆内存地址
String str3 = str2;
String str4 = "hello";
System.out.println(str1 == str2); // false
System.out.println(str1 == str3); // false
System.out.println(str3 == str2); // true
System.out.println(str1 == str4); // true
}
}
常用方法
字符串判断
方法 | 描述 |
---|---|
boolean equals(Object obj) | 比较字符串的内容是否相同 |
boolean equalsIgnoreCase(String str) | 比较字符串的内容是否相同,忽略大小写 |
boolean startsWith(String str) | 判断字符串对象是否以指定的str开头 |
boolean endsWith(String str) | 判断字符串对象是否以指定的str结尾 |
字符串截取
方法 | 描述 |
---|---|
int length() | 获取字符串的长度,其实也就是字符个数 |
char charAt(int index) | 获取指定索引处的字符 |
int indexOf(String str) | 获取str在字符串对象中第一次出现的索引 |
String substring(int start) | 从start开始截取字符串 |
String substring(int start,int end) | 从start开始,到end结束截取字符串。包括start,不包括end |
字符串转换
方法 | 描述 |
---|---|
char[] toCharArray() | 把字符串转换为字符数组 |
String toLowerCase() | 把字符串转换为小写字符串 |
String toUpperCase() | 把字符串转换为大写字符串 |
其他方法
方法 | 描述 |
---|---|
String trim() | 去除字符串两端空格 |
String[] split(String str) | 按照指定符号分割字符串 |
StringBuilder 和 StringBuffer
StringBuilder 是一个可变的字符序列。它继承于 AbstractStringBuilder,实现了 CharSequence 接口。
StringBuffer 也是继承于 AbstractStringBuilder 的子类;
但是,StringBuilder 和 StringBuffer 不同,前者是非线程安全的,后者是线程安全的。
常用方法
方法 | 描述 |
---|---|
public StringBuffer append(String s) | 将指定的字符串追加到此字符序列。 |
public StringBuffer reverse() | 将此字符序列用其反转形式取代。 |
public delete(int start, int end) | 移除此序列的子字符串中的字符。 |
public insert(int offset, int i) | 将 int 参数的字符串表示形式插入此序列中。 |
insert(int offset, String str) | 将 str 参数的字符串插入此序列中。 |
replace(int start, int end, String str) | 使用给定 String 中的字符替换此序列的子字符串中的字符。 |
class Test {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder(10);
// StringBuffer sb = new StringBuffer(10);
sb.append("Test..");
System.out.println(sb); // Test..
sb.append("!");
System.out.println(sb); // Test..!
sb.insert(6, "Java");
System.out.println(sb); // Test..Java!
sb.delete(4, 6);
System.out.println(sb); // TestJava!
}
}
StringBuilder 和 StringBuffer 用法差不多。
String、StringBuilder、StringBuffer 之间的区别:
首先需要说明的是:
-
String 字符串常量
-
StringBuilder 字符串变量(非线程安全)
-
StringBuffffer 字符串变量(线程安全)
在大多数情况下三者在执行速度方面的比较:StringBuilder > StringBuffer > String
对于三者使用的总结:
-
如果要操作少量的数据用 = String
-
单线程操作字符串缓冲区下操作大量数据 = StringBuilder
-
多线程操作字符串缓冲区下操作大量数据 = StringBuffer
Number
所有的包装类(Integer、Long、Byte、Double、Float、Short)都是抽象类 Number 的子类。
包装类
包装类 | 基本数据类型 |
---|---|
Boolean | boolean |
Byte | short |
Short | short |
Integer | int |
Long | long |
Character | char |
Float | float |
Double | double |
使用方法
实现 int 和 Integer 的相互转换
class Test {
public static void main(String[] args) {
int m = 500;
Integer obj = new Integer(m);
int n = obj.intValue();
System.out.println(n); // 500
Integer obj1 = new Integer(500);
System.out.println(obj.equals(obj1)); // true
}
}
将字符串转换为整数
class Test {
public static void main(String[] args) {
String[] str = {"123", "123abc", "abc123", "abcxyz"};
for (String str1 : str) {
try {
int m = Integer.parseInt(str1, 10);
System.out.println(str1 + " 可以转换为整数 " + m);
} catch (Exception e) {
System.out.println(str1 + " 无法转换为整数");
}
}
}
}
输出结果:
123 可以转换为整数 123
123abc 无法转换为整数
abc123 无法转换为整数
abcxyz 无法转换为整数
将整数转换为字符串
class Test {
public static void main(String[] args) {
int m = 500;
String s = Integer.toString(m);
System.out.println(s); // 500
String s2 = m + "a";
System.out.println(s2); // 500a
}
}
Math
Java 的 Math 包含了用于执行基本数学运算的属性和方法,如初等指数、对数、平方根和三角函数。
常量值
常量 | 描述 |
---|---|
Math.PI | 记录的圆周率 |
Math.E | 记录e的常量 |
常用方法
方法 | 描述 |
---|---|
Math.abs | 返回参数的绝对值。 |
Math.sin | 求指定double类型参数的正弦值。 |
Math.cos | 求指定double类型参数的余弦值。 |
Math.tan | 求指定double类型参数的正切值。 |
Math.toDegrees | 将角度转换为弧度。 |
Math.ceil | 得到不小于某数的最大整数。 |
Math.floor | 得到不大于某数的最大整数。 |
Math.IEEEremainder | 求余 |
Math.max | 返回两个参数中的最大值。 |
Math.min | 返回两个参数中的最小值。 |
Math.sqrt | 求参数的算术平方根。 |
Math.pow | 求某数的任意次方, 抛出ArithmeticException处理溢出异常 |
Math.exp | 返回自然数底数e的参数次方。 |
Math.log10 | 以10为底的对数 |
Math.log | 返回参数的自然数底数的对数值。 |
Math.rint | 求距离某数最近的整数(可能比某数大,也可能比它小)。 |
Math.round | 同上,返回int型或者long型(上一个函数返回double型)。 |
Math.random | 返回0,1之间的一个随机数。 |
Random
random() 方法用于返回一个随机数,随机数范围为 0.0 =< Math.random < 1.0。
常用方法
方法 | 描述 |
---|---|
protected int next(int bits) | 生成下一个伪随机数。 |
boolean nextBoolean() | 返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的boolean值。 |
void nextBytes(byte[] bytes) | 生成随机字节并将其置于用户提供的 byte 数组中。 |
double nextDouble() | 返回下一个伪随机数,它是取自此随机数生成器序列的、在0.0和1.0之间均匀分布的double值。 |
float nextFloat() | 返回下一个伪随机数,它是取自此随机数生成器序列的、在0.0和1.0之间均匀分布float值。 |
double nextGaussian() | 返回下一个伪随机数,它是取自此随机数生成器序列的、呈高斯(“正 态”)分布的double值,其平均值是0.0标准差是1.0。 |
int nextInt() | 返回下一个伪随机数,它是此随机数生成器的序列中均匀分布的 int 值。 |
int nextInt(int n) | 返回一个伪随机数,它是取自此随机数生成器序列的、在(包括和指定值(不包括)之间均匀分布的int值。 |
long nextLong() | 返回下一个伪随机数,它是取自此随机数生成器序列的均匀分布的 long 值。 |
void setSeed(long seed) | 使用单个 long 种子设置此随机数生成器的种子。 |
import java.util.Random;
class Test {
public static void main(String[] args) {
System.out.println(Math.random()); // 0.6456063107220328
System.out.println(Math.random()); // 0.579336669972285
Random rand = new Random();
int i = rand.nextInt(100);
System.out.println(i); // 生成随机数为0-100的整数,不包括100
}
}
Date
java.util 包提供了 Date 类来封装当前的日期和时间。 Date 类提供两个构造函数来实例化 Date 对象。
常用方法
方法 | 描述 |
---|---|
boolean after(Date date) | 若当调用此方法的Date对象在指定日期之后返回true,否则返回false。 |
boolean before(Date date) | 若当调用此方法的Date对象在指定日期之前返回true,否则返回false。 |
int compareTo(Date date) | 比较当调用此方法的Date对象和指定日期。两者相等时候返回0。调用对象在指定日期之前则返回负数。调用对象在指定日期之后则返回正数。 |
int compareTo(Object obj) | 若obj是Date类型则操作等同于compareTo(Date) 。否则它抛出ClassCastException。 |
long getTime( ) | 返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。 |
oid setTime(long time) | 用自1970年1月1日00:00:00 GMT以后time毫秒数设置时间和日期。 |
import java.text.SimpleDateFormat;
import java.util.Date;
class Test {
public static void main(String[] args) {
Date date = new Date();
System.out.println(date.toString()); // Sat Jul 24 14:44:45 CST 2021
long time1 = date.getTime();
long time2 = date.getTime();
System.out.println(time1 == time2); // true
// SimpleDateFormat 格式化时间
SimpleDateFormat ft = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
System.out.println(ft.format(date)); // 2021-07-24 02:46:37
}
}
Calendar
Calendar 类是一个抽象类,在实际使用时实现特定的子类的对象,创建对象的过程对程序员来说是透明的,只需要使用getInstance方法创建即可。
常量值
常量 | 描述 |
---|---|
Calendar.YEAR | 年份 |
Calendar.MONTH | 月份 |
Calendar.DATE | 日期 |
Calendar.DAY_OF_MONTH | 日期,和上面的字段意义完全相同 |
Calendar.HOUR | 12小时制的小时 |
Calendar.HOUR_OF_DAY | 24小时制的小时 |
Calendar.MINUTE | 分钟 |
Calendar.SECOND | 秒 |
Calendar.DAY_OF_WEEK | 星期几 |
import java.util.Calendar;
class Test {
public static void main(String[] args) {
Calendar c = Calendar.getInstance();
// 获得年份
int year = c.get(Calendar.YEAR);
System.out.println(year); // 2021
// 获得月份
int month = c.get(Calendar.MONTH) + 1;
System.out.println(month); // 7
// 获得日期
int date = c.get(Calendar.DATE);
System.out.println(date); // 24
// 获得小时
int hour = c.get(Calendar.HOUR_OF_DAY);
System.out.println(hour); // 14
// 获得分钟
int minute = c.get(Calendar.MINUTE);
System.out.println(minute); // 57
// 获得秒
int second = c.get(Calendar.SECOND);
System.out.println(second); // 47
// 获得星期几
int day = c.get(Calendar.DAY_OF_WEEK);
System.out.println(day); // 7
}
}