一、常用API
API(Application Programming interface)意思是应用程序编程接口,说人话就是Java帮我们写好的一些程序,如:类、方法等,我们直接拿过来用就可以解决一些问题。
"千里之行始于足下,多记、多查、多写代码、孰能生巧!"
二、Object类
要学习的第一个API就是Object类。Object类是Java中所有类的祖宗类,因此,Java中所有类的对象都可以直接使用Object类中提供的一些方法。
我们找到Object类的下面两个方法:
- 2.1 toString()方法
public String toString()
调用toString()方法为了被子类重写,以便返回对象的字符串表示形式。
默认的格式是:"包名.类名@哈希值16进制"
假设有一个学生类如下
public class Student { // extends Object这个写不写都会默认继承Object对象
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
再定义一个测试类
public class Test {
public static void main(String[] args) {
Student s1 = new Student("柳岩",18);
System.out.println(s1.toString()); // toString()方法是可以省略不写的
}
}

如果,在Student类重写toString()方法,那么我们可以返回对象的属性值,代码如下
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}

2.2 equals(Object o)方法
public boolean equals(Object o)
判断此对象与参数对象是否"相等", 默认判断地址是否相等
我们写一个测试类,测试一下
public class Test{
public static void main(String[] args) {
Student s1 = new Student("柳岩",18);
System.out.println(s1.toString());
Student s2 = new Student("刘涛",18);
//equals本身也是比较对象的地址,和"=="没有区别
System.out.println(s1.equals(s2)); // false
//如果只是比较地址是否一样, 没有必要使用父类的equals方法 "=="就可以它也比较对象的地址
System.out.println(s1 == s2); //false
}
}
思考: 为什么使用父类的equals方法? 用==也可以替代啊
因为父类equals方法比较两个对象的地址, 我们是很少使用的,
在开发中我们同样是让子类重新equals()方法, 以便子类自己来自定义比较规则
如果我们在Student类中,把equals方法重写了,就按照对象的属性值进行比较
import java.util.Objects;
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
//重写equals方法,比较两个对象的内容一样就返回true. 这样在开发中才有意义
// 比较者: s1 ==> this
// 被比较者: s2 ==> Object o
@Override
public boolean equals(Object o) {
// 1. 判断两个对象的地址是否一样, 一样直接返回true
if (this == o) return true;
// 2. 判断o是null 直接返回false, 或者比较者的类型与被比较者的类型不一样, 返回false
// Student.class != Student.class
if (o == null || this.getClass() != o.getClass()) return false;
// 3. o不是null, 且o一定是学生类型的对象, 就开始比较内容.
Student student = (Student) o;
return this.age == student.age && Objects.equals(this.name, student.name);
}
}

总结一下Object的toString方法和equals方法
public String toString()
返回对象的字符串表示形式。默认的格式是:“包名.类名@哈希值16进制”
【子类重写后,返回对象的属性值】
public boolean equals(Object o)
判断此对象与参数对象是否"相等"。默认比较对象的地址值,和"=="没有区别
【子类重写后,比较对象的属性值】
2.3 clone() 方法(了解)
我们学习Object类的clone()方法,克隆。意思就是某一个对象调用这个方法,这个方法会复制一个一模一样的新对象,并返回。
public Object clone()
当某个对象调用这个方法时,这个方法会复制一个一模一样的新对象返回。
想要调用clone()方法,必须让被克隆的类实现Cloneable接口。如我们准备克隆User类的对象,代码如下
/**
* Cloneable当前接口中什么都没有
* Cloneable它是一个标记接口
* 可以理解是规则: 意思是当前类实现了这个规则, 当前类的对象就拥有了克隆的能力
* 如果不实现这个接口, 虚拟机就看不到实现的这个接口, 它就不认为当前类的对象能克隆, 就会报错
*/
public class User implements Cloneable{
private int id; //编号
private String username; //用户名
private String password; //密码
private double[] scores; //分数
public User() {
}
public User(int id, String username, String password, double[] scores) {
this.id = id;
this.username = username;
this.password = password;
this.scores = scores;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public double[] getScores() {
return scores;
}
public void setScores(double[] scores) {
this.scores = scores;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", password='" + password + '\'' +
", scores=" + Arrays.toString(scores) +
'}';
}
/**
* 重写clone方法
* 注意: 不是所有的类都可以被克隆的, 克隆还需要让当前类实现Cloneable接口
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
// super去调用父类Object中的clone方法
return super.clone();
}
}
接着,我们写一个测试类,克隆User类的对象。并观察打印的结果
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
// 创建用户对象
User u1 = new User(1,"zhangsan","wo666",new double[]{99.0,99.5});
System.out.println(u1.getId());
System.out.println(u1.getUsername());
System.out.println(u1.getPassword());
System.out.println(u1.getScores());
System.out.println("==================");
//调用方法克隆得到一个新对象
User u2 = (User) u1.clone();
System.out.println(u2.getId());
System.out.println(u2.getUsername());
System.out.println(u2.getPassword());
System.out.println(u2.getScores());
}
}

上面演示的克隆方式,是一种浅克隆的方法,浅克隆的意思:拷贝出来的对象封装的数据与原对象封装的数据一模一样(引用类型拷贝的是地址值) 。如下图所示
还有一种拷贝方式,称之为深拷贝,拷贝原理如下图所示
下面演示一下深拷贝User对象
public class User implements Cloneable{
private int id; //编号
private String username; //用户名
private String password; //密码
private double[] scores; //分数
public User() {
}
public User(int id, String username, String password, double[] scores) {
this.id = id;
this.username = username;
this.password = password;
this.scores = scores;
}
// 自己提供Getter和Setter方法....
/**
* 重写clone方法
* 注意: 不是所有的类都可以被克隆的, 克隆还需要让当前类实现Cloneable接口
* @return
* @throws CloneNotSupportedException
*/
@Override
protected Object clone() throws CloneNotSupportedException {
//先克隆得到一个新对象
User u = (User) super.clone();
//再将新对象中的引用类型数据,再次克隆
u.scores = u.scores.clone();
return u;
}
}
三、Objects类
Objects是一个工具类,提供了一些方法可以对任意对象进行操作。主要方法如下

下面写代码演示一下这几个方法
public class Test{
public static void main(String[] args) {
String s1 = null;
String s2 = "liuyan";
// 这里会出现NullPointerException异常,调用者不能为null
System.out.println(s1.equals(s2));
// 此时不会有NullPointerException异常,底层会自动先判断空
System.out.println(Objects.equals(s1,s2)); // 更安全, 更好用
System.out.println("===============================");
// 判断对象是否为null,等价于==
System.out.println(Objects.isNull(s1)); //true
System.out.println(s1 == null); //true
System.out.println("===============================");
// 判断对象是否不为null,等价于!=
System.out.println(Objects.nonNull(s2)); //true
System.out.println(s2 != null); //true
}
}