常用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
    }
}
相关推荐
过期动态1 天前
MySQL中的约束
android·java·数据库·spring boot·mysql
wxin_VXbishe1 天前
springboot新能源车充电站管理系统小程序-计算机毕业设计源码29213
java·c++·spring boot·python·spring·django·php
程序员陆通1 天前
月烧 400 刀到不到 20 刀:我是怎么把 OpenClaw 的 Token 账单砍掉 95% 的
java·前端·数据库
江南十四行1 天前
Python生成器与协程:从迭代器到异步编程的进阶之路
开发语言·python
代码漫谈1 天前
一文学习 SpringBoot 的 application.yml 配置,基于 Spring Boot 3.2.x
java·spring boot·spring·配置文件
SamDeepThinking1 天前
程序员如何接受工作内容毫无意义?
java·后端·程序员
测试员周周1 天前
【AI测试功能3】AI功能测试的三层架构:单元测试 → 集成测试 → E2E测试——AI系统测试金字塔实战指南
开发语言·人工智能·python·功能测试·架构·单元测试·集成测试
lly2024061 天前
AppML 案例原型
开发语言
三翼鸟数字化技术团队1 天前
基于Redis ZSet实现分布式优先级队列的技术实践
java·redis
jllllyuz1 天前
MATLAB 回声抵消(AEC)、噪声抑制(NS)、自动增益控制(AGC)完整实现
开发语言·matlab