常用API(Object类 & Objects类)

一、常用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
    }
}
相关推荐
小碗羊肉2 小时前
【从零开始学Java | 第三十六篇】字符流
java·开发语言
海寻山2 小时前
Java枚举(Enum):基础语法+高级用法+实战场景+面试避坑
java·开发语言·面试
鱼鳞_2 小时前
Java学习笔记_Day31(IO流)
java·笔记·学习
t***5442 小时前
能否给出更多现代C++设计模式的示例
开发语言·c++·设计模式
神仙别闹2 小时前
基于 MATLAB 实现的流载体的LSB隐藏项目
开发语言·matlab
网域小星球2 小时前
C语言从0入门(二十三)|预处理:#define、#include、条件编译详解
c语言·开发语言
石榴树下的七彩鱼2 小时前
身份证 OCR 识别 API 接入详解(Python / Java 示例)
java·开发语言·人工智能·后端·python·ocr·api
云烟成雨TD2 小时前
Spring AI Alibaba 1.x 系列【16】异步工具核心组件与执行流程
java·人工智能·spring