JavaImprove--Lesson02--Object类,Objects工具类,封装类

发布时间 2023-12-27 21:41:04作者: 回忆也交给时间

一.Object类

Java中的Object类是所有类的超类,它是Java类层次结构的根类。这意味着所有的类都直接或间接地继承自Object

  • equals(Object obj): 用于比较两个对象是否相等。默认实现是比较对象的引用,但可以通过重写此方法来比较对象的内部状态。
  • hashCode(): 返回对象的哈希码值,通常用于散列数据结构,如哈希表。
  • toString(): 返回对象的字符串表示形式。默认实现可能不提供足够的信息,因此经常被重写。
  • clone(): 创建并返回此对象的一个副本。默认实现是浅复制,可以通过重写clone()方法和Cloneable接口来实现深复制。
  • finalize(): 当垃圾收集器准备回收对象的内存时,会调用此方法。可以用于释放资源,但不建议依赖此方法,因为它不是保证会运行。

Object自带的方法有很多,但是常使用的就是toString,equals,clone方法

这些方法都是主要使用的方法,但是Object类是被任何类所继承或者间接继承的,所以说任何类都可以使用到这些方法

但是,作为子类大多数情况下并不是为了使用父类的方法,而是重写父类的方法,从而使这些方法能够适配子类

举个例子,如果不重写object类的方法,clone()就会一直克隆object类,很显然,大多数情况下,我们不需要使用克隆object,而是克隆当前类,就需要重写clone方法

toString方法

toString方法,如果不重写父类的方法,那么就还是调用父类的方法,父类的方法就是打印一些关于当前对象的类名和对象的hashcode

public class toStringDemo {
    private String name;
    private String clasName;
    private double grade;

    public toStringDemo() {
    }

    public toStringDemo(String name, String clasName, double grade) {
        this.name = name;
        this.clasName = clasName;
        this.grade = grade;
    }
    
}

 

如上代码,没有重写父类的方法,我们在主方法调用toString方法

输出如下

 我们重写toString方法:

注意,重写需要清楚是自己重写还是让编译器帮我们重写

自己重写就根据自己想让此方法输出什么,就diy就好了

编译器帮我们重写的toString方法是用来打印当前对象的属性值的,我们可以使用快捷键 alt + insert ,或者手动输入tosting,编译器会提示此方法

但是一般重写都是让编译器帮我们重写,因为大多数人使用toString方法都是想看看对象的内部属性内容的

重写toString方法:

@Override
public String toString() {
    return "toStringDemo{" +
            "name='" + name + '\'' +
            ", clasName='" + clasName + '\'' +
            ", grade=" + grade +
            '}';
}

 

使用有参构造,再来获取一个对象后,调用toString方法

输出如下:

 总结:大多数情况下,我们都会让编译器重写object类的toString方法,使其能打印一些类对象的内部细节

equals

equals方法是用来比较两个对象是否相等的,使用方法:对象 . equals(对象)

对象之间的比较方式是确定equals方法执行的关键,object方法自带的比较方式是比较内存地址,但是再Java中,使用new关键字创建的对象都不是单例模式

也就是每次new关键字实例化出来的对象都是新建的,所以他们有自己的内存地址

所以使用object类的equals方法比较结果都是false

我们重写equals方法后,可以根据自定义的方式来判断两个对象是否相等,我们判断的标准可以变为对象的属性值是否一一对应相等,如果不是才返回false

重写equals方法:

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    toStringDemo that = (toStringDemo) o;
    return Double.compare(that.grade, grade) == 0 && Objects.equals(name, that.name) && Objects.equals(clasName, that.clasName);
}

 

这是编译器自动生成的equals方法,我们可以来看看这个方法的执行逻辑

if (this == o) return true;

 

这是equals方法的重写第一句,this调用此方法的对象,而o代表传入的对象

== 符号是用来判断地址是否相等的,如果这两个对象地址相等,那么肯定是一个对象,则返回true

if (o == null || getClass() != o.getClass()) return false;

 

第二句话先判断传入的对象是否为空,不为空且传入对象的类和this类是否属于一个类

如果不是一个类,那么不管怎么创建对象,两个类new出来的对象就一定是不同的对象,所以直接返回false

toStringDemo that = (toStringDemo) o;
    return Double.compare(that.grade, grade) == 0 && Objects.equals(name, that.name) && Objects.equals(clasName, that.clasName);

 

最后一段代码就是将两个对象的属性值进行依次比较,只要有一个不相等,就返回false,反之,都相等,返回ture

clone方法

这不是 Java代码实现的方法,而是c++写的方法

它可以实现对象克隆,它是在内存中操作的方法,Java本身不提供指针操作,所以使用c++的方法会更加的高效,它们可以操作内存,这些非Java写的代码一般存放再Java的jvm虚拟机的本地方法栈中

这个方法就重写就只能靠编译器重写了

@Override
protected Object clone() throws CloneNotSupportedException {
    return super.clone();
}

 

这种写法是浅克隆,可以克隆一个一摸一样的对象出来,hashcode是不一样的,内容是一样的

关于深克隆和浅克隆可以看我的博客:GOF23--23种设计模式(二)

查看设计模式的原型模式部分,有深克隆和浅克隆的详解

 二.Objects工具类

Objects 是 Java 中的一个实用工具类,它包含了一系列用于处理对象的方法。由于 Object 是所有类的超类,Objects 类中的方法可以用于任何 Java 对象。以下是一些 Objects 类中的常用方法:

  1. equals(): 用于比较两个对象是否相等。这个方法首先检查两个对象是否为同一个对象(即它们的引用是否相同),如果是,则返回 true。如果不是,它会调用对象的 equals() 方法。如果对象没有重写 equals() 方法,则默认实现会比较对象的内存地址,而不是它们的内部状态。
  2. hashCode(): 返回对象的哈希码值。哈希码是一个整数,通常用于在哈希表等数据结构中存储对象。默认情况下,hashCode() 方法返回对象的内存地址的整数表示,但也可以通过重写该方法来提供更合适的哈希码计算方式。
  3. toString(): 返回对象的字符串表示形式。默认情况下,这个方法返回对象的类名和内存地址的字符串表示形式,但也可以通过重写该方法来提供更有意义的字符串表示。
  4. hash(): 计算对象的哈希码值,前提是该对象实现了 hashCode() 方法。
  5. toString(Object obj): 返回对象的字符串表示形式,前提是该对象实现了 toString() 方法。

Objects类中的方法都是静态的,所以说,我们可以直接通过Objects . 方法使用这个工具类重点的方法

 Objects类中的工具方法有很多,详细了解请款JDK帮助文档

equals方法

 object的equals方法和objects的equals方法使用是不一样的

调用方式:

object的equals方法:对象 . equals(对象)

ObjectsDemo obj1 = new ObjectsDemo();
ObjectsDemo obj2 = new ObjectsDemo();
obj1.equals(obj2);

 

 objects的equals方法: Objects.equals(对象,对象)

ObjectsDemo obj1 = new ObjectsDemo();
ObjectsDemo obj2 = new ObjectsDemo();
//静态方法,直接点出来
Objects.equals(obj1,obj2);

 

 object的equlas方法需要可以重写,但是objects的equals方法是静态方法,是架构师写好的,我们只能使用,不用重写

object

//object类的equals
public boolean equals(Object obj) {
        return (this == obj);
    }

 

objects

//Objects类的equals
public static boolean equals(Object a, Object b) {
    return (a == b) || (a != null && a.equals(b));
}

 

 

我们可以看到objects类的方法更加的专业

它有非空校验,但是object的方法没有

obj1=null;
obj1.equals(obj2);

 

object的比较方式没有校验,如上比较后,会报错:

 而使用objects的equals方法比较:

obj1=null;
System.out.println(Objects.equals(obj1, obj2));

 总结:

Objects工具类中的方法更加专业,所以如果不想自己重写object的方法,可以使用Objects工具类中的方法

三.封装类(包装类)

众所周知,Java 是一门面向对象的编程语言,所谓万物皆对象

但是Java中又必须有一些不是对象的基本类型

编程语言一共有八个基本数据类型,对于这些不是对象,且必须存在面向对象的编程语言的类型怎么办呢?

这时候Java就拥有了基本类型的包装类,每一个基本类型都有它的包装类,它们的包装类就是对象类型

Java中的包装类(Wrapper class)是对基本数据类型的封装,它们为每种基本数据类型提供了对应的包装类。这些包装类在Java标准库中定义,并且都是java.lang包的一部分。

以下是Java中的8种基本数据类型及其对应的包装类:

  1. byte -> Byte
  2. short -> Short
  3. int -> Integer
  4. long -> Long
  5. float -> Float
  6. double -> Double
  7. char -> Character
  8. boolean -> Boolean

我们在泛型中讲到,泛型中不支持基本类型的,所以有了包装类,我们可以使用包装类

举个例子:ArrayList<>泛型就只接收对象类型

ArrayList<Integer> list = new ArrayList<>();

 

使用Interger对象,就可以毫无问题的传入int类型

但是有没有想过,为什么我们传入的是int类型,而ArrayList<>中又是Interger类型,但是任然可以装进去呢?

这就涉及到Java的另外一个领域了,自动拆箱和装箱

自动装箱指的是,我们可以直接将int型变量赋给Integer对象,有JVM帮我们调用相关方法

如下:

Integer a = 12;
Integer b = Integer.valueOf(12);

 

这两个命名方式是一样的,但是上一条语句就是自动装箱的结果,在ArrayList中,我们也是传入了一个int型的值

只不过它被自动装箱成了Integer对象罢了

自动拆箱指的是,可以将一个Integer对象直接赋值给基本类型

如下:

Integer a = 12;
int b = a;
int c = a.intValue();

 

自动拆箱也不需要调用相关的方法,可以使封装类直接转换为基本类型

详细的自动拆箱和装箱可以看:Java拓展-拆,装箱,线程,反射

Integer.parseInt()和String.valueOf()

 这两个方法是包装类的重点方法

parse方法可以将字符串转换为int,float,double

valueOf可以将其它类型转换为string类型

尤其是在web开发的时候,前后端传递参数都是String类型的,就可以通过paseInt将本是int类型的数据转换为int

parse系列方法:

parseInt:

String a = "12";
int b = Integer.parseInt(a);

 

parseDouble:

String a = "12";
double b = Double.parseDouble(a);

 

parseFloat:

String a = "12";
float b = Float.parseFloat(a);

 

注意:

如果a = “12.5”这种一看就是浮点型是不能使用int去转换的,它转不了

而且如果a中包含字符,也是转换不了的

上面两种情况都是会报错的

valueOf()方法:

此方法是包含于String类型的,可以将其它类型转换为S听类型

String a = String.valueOf(12);
String b = String.valueOf(12.0);

 

但是这个在实际开发中用到的比较少,因为一般我们会选择使用字符拼接