前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >第三阶段-Java常见对象:【第一章 Object类】

第三阶段-Java常见对象:【第一章 Object类】

作者头像
BWH_Steven
发布2019-08-09 15:51:40
4120
发布2019-08-09 15:51:40
举报
文章被收录于专栏:理想二旬不止理想二旬不止

(一)

Object类

引言:

在讲解Object类之前,我们不得不简单的提一下什么是API,先贴一组百度百科的解释:

API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件得以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节。

简单的说:就是 Java 中有好多现成的类库,其中封装了许多函数,只提供函数名和参数,但隐藏了函数的具体实现,这些可见的部分作为与外界联系的桥梁,也就是我们所称的 API ,不过由于Java是开源的,所以这些隐藏的实现我们也是可以看到的。

(一) Object 类的概述

(1) Object是类层次结构的根类,所有的类都隐式的(不用写extends)继承自Object类

(2) Java 所有的对象都拥有Object默认方法

(3) Object类的构造方法有一个,并且是无参构造

这就对应了前面学习中的一句话,子类构造方法默认访问父类的构造是无参构造

我们需要了解的方法又有哪些呢?

A: hashCode() B: getClass() C: finalize() D: clone

E: notify() F: notifyAll()

我们需要掌握的方法又有哪些呢?

A: toString() B: equals()

(1) hashCode

返回对象的哈希值(散列码),不是实际地址值,不过可以理解为地址值。

它实际上返回一个int型整数,用于确定该对象在哈希表中的索引位置

暂时了解即可,学习集合框架内容后将会专篇深入学习

代码语言:javascript
复制
  //Student类
  
  public class Student extends Object {
  }
代码语言:javascript
复制
  //StudentDemo类
  
  public class StudentDemo {
      public static void main(String[] args) {
          Student s1 = new Student();
          System.out.println(s1.hashCode());
  
          Student s2 = new Student();
          System.out.println(s2.hashCode());
  
          Student s3 = s1;
          System.out.println(s3.hashCode());
      }
  }
  
  //运行结果:
  460141958
  1163157884
  460141958
(2) getClass

返回对象的字节码文件对象,在反射篇章详细解释, 暂做简单了解。

代码语言:javascript
复制
  public class StudentDemo {
      public static void main(String[] args) {
          Student s = new Student();
          Class c = s.getClass();
          String str = c.getName();
          System.out.println(str);
  
  //链式编程
          String str2 = s.getClass().getName();
          System.out.println(str2);
      }
  }
  
  //运行结果
  cn.bwh_02_getClass.Student
  cn.bwh_02_getClass.Student
(3) finalize()

在对象将被垃圾回收器清除前调用,但不确定时间,并且对象的finalize()方法只会被调用一次,调用后也不一定马上清除该对象。

(4) clone()

以实现对象的克隆,包括成员变量的数据复制,但是它和两个引用指向同一个对象是有区别的。

我们先来解释一下后半句话

如果我们想要复制一个变量,可以这样做 Eg:

代码语言:javascript
复制
  int a = 20;
  int b = a;

那么我们想要复制一个对象,是不是也可以这样做呢?

代码语言:javascript
复制
  //Student
  
  public class Student {
      int age;
  
      public int getAge() {
          return age;
      }
  
      public void setAge(int age) {
          this.age = age;
      }
  }
代码语言:javascript
复制
  //StudentDemo
  
  public class StudentDemo {
      public static void main(String[] args) {
          Student s1 = new Student();
          s1.setAge(20);
          Student s2 = s1;//将引用赋值
          System.out.println("学生1年龄:" + s1.getAge());
          System.out.println("学生2年龄:" + s2.getAge());
          System.out.println("------------------------------");
  
          s2.setAge(25);
          System.out.println("学生1年龄:" + s1.getAge());
          System.out.println("学生2年龄:" + s2.getAge());
      }
  }
  
  //运行结果
  学生1年龄:20
  学生2年龄:20
  ---------------------------
  学生1年龄:25
  学生2年龄:25

很明显,即使将对象s1赋值给对象s2,但是通过set传值的时候,两者仍然会同时变化,并没有起到克隆(独立)的作用,这是因为赋值时只是将存储在栈中,对对象的引用赋值,因此它们两个的引用指向同一个对象(堆中),所以无论如何赋值,只要堆中的对象属性发生了变化,通过引用显示属性的时候,均是相同的。

用法:

1. 实现Cloneable接口 2. 重写clone方法

分类:

浅拷贝: 仅拷贝对象,不拷贝成员变量,仅复制了变量的引用,拷贝前后变量使用同一块内存,内存销毁后,必须重新定义(两者同生共死) 深拷贝: 不仅拷贝对象,也拷贝成员变量(真正意义上的复制, 两者独立无关)

代码语言:javascript
复制
  //浅拷贝
  
  public class Person implements Cloneable{
      private int age = 20;
   
  @Override
      protected Object clone() throws CloneNotSupportedException {
          return super.clone();
      }
  }
代码语言:javascript
复制
  //深拷贝
  
  public class Person implements Cloneable {
      public int age = 20;
  
  @Override
      protected Object clone() throws CloneNotSupportedException {
  //拷贝对象
          Person person = (Person) super.clone();
  //拷贝成员变量
          person.age = (int) age.clone();
  //返回拷贝对象
          return person;
      }
  }

我们来利用浅拷贝解决刚开始那个问题

代码语言:javascript
复制
  //Person类,写出get、set方法、重写clone方法
  
  //PersonDemo类
  
  public class PersonDemo {
      public static void main(String[] args) throws CloneNotSupportedException {
          Person p1 = new Person();
          p1.setAge(20);
          Person p2 = (Person) p1.clone();
          System.out.println("第一个人的年龄:"+ p1.getAge() );
          System.out.println("第二个人的年龄:"+ p2.getAge() );
          System.out.println("--------------------------");
  
          p2.setAge(25);
          System.out.println("第一个人的年龄:"+ p1.getAge() );
          System.out.println("第二个人的年龄:"+ p2.getAge() );
      }
  }
  
  运行结果:
  第一个人的年龄:20
  第二个人的年龄:20
  --------------------------
  第一个人的年龄:20
  第二个人的年龄:25
(5) wait、notify和notifyAll

三者属于线程通信间的Api,此部分放在日后讲

(6) toString()——重要

public static toString(): 返回该对象的字符串表示

代码语言:javascript
复制
  //Student类
  
  public class Student {
      private String name;
      public int 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;
      }
  }
代码语言:javascript
复制
  //StudentDemo类
  
  package cn.bwh_04_toString;
  
  public class StudentDemo {
      public static void main(String[] args) {
          Student s = new Student();
          s.setName("admin");
          s.setAge(20);
  //直接输出s也会默认的调用toString方法
          System.out.println(s.toString());
      }
  }
  
  //通过set方法赋值后,直接调用toString()
  
  运行结果:
  cn.bwh_04_toString.Student@1b6d3586

很明显,给我们返回这样的信息意义是不大的,所以我们建议对所有子类重写该方法

代码语言:javascript
复制
  //在Student类中重写 toString()
  
  @Override
   public String toString() {                                         
    return "Student[" + "name=" + name + ", " + "age=" + age + "]";
  
  //运行结果:
  Student[name=admin, age=20]

通过重写toString后,结果按照我们所定的规则以字符串的形式输出

(重写后会优先使用类中的toString方法)

为什么要用它呢?

主要目的还是为了简化输出

  1. 在类中重写toString()后,输出类对象就变得有了意义(输出s 和 s.toString()是一样的 ,不写也会默认调用),变成了我们实实在在的信息,而不是上面的cn.bwh_04_toString.Student@1b6d3586。

2. 如果我们想要多次输出 类中的成员信息,就需要多次书写 get方法(每用一次就得写)

代码语言:javascript
复制
  System.out.println("Student[" + "name=" + s.getName() + ", " + "age=" + s.getAge() + "]");

而调用toString()就简单多了

补充:
代码语言:javascript
复制
  //两者等价
  toString();
  getClass().getName()+ '@' + Integer.toHexString(hashCode())
      
  //输出结果
  cn.bwh_04_toString.Student@1b6d3586。
(7) equals()——重要

比较两个对象是否相同

默认情况下,比较的是地址值是否相同。

而比较地址值是没有意义的,所以,一般子类也会重写该方法。

在诸多子类,如String、Integer、Date 等均重写了equals()方法

改进思路: 我们可以将比较地址值转变为比较成员变量 1. 因为name为String类型,而String类型为引用类型,所以不能够用==比较,应该用equal() 2. String中默认重写过的equal()方法是用来比较字符串内容是否相同 3. 我们要使用的是学生类的成员变量,所以父类 Object不能调用子类Student的特有功能 所以使用向下转型

代码语言:javascript
复制
  //重写v1.0
      public boolean equals(Object o) {
          Student s = (Student) o;
          if (this.name.equals(s.name) && this.age == s.age) {
              return true;
          } else {
              return false;
          }
      }
代码语言:javascript
复制
  //重写v2.0 (可作为最终版)
      public boolean equals(Object o) {
          if (this.name == o) {
              return true;
          }
  //测试它左边的对象是否是它右边的类的实例,返回 boolean 的数据类型。
          if (!(o instanceof Student)) {
              return false;
          }
          Student s = (Student) o;
          return this.name.equals(s.name) && this.age == s.age;
      }
代码语言:javascript
复制
  //idea自动生成版
  @Override
      public boolean equals(Object o) {
          if (this == o) return true;
          if (o == null || getClass() != o.getClass()) return false;
          Student student = (Student) o;
          return age == student.age &&
                  Objects.equals(name, student.name);
      }
equals() 和 == 的区别 ?

== 的作用:

基本类型:比较值是否相同   

引用类型:比较的就是堆内存地址是否相同

equals 的作用:

引用类型:默认情况下,比较的是地址值。

注:一般选择重写方法,比较对象的成员变量值是否相同 ,不过一般重写都是自动生成。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-06-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 理想二旬不止 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引言:
  • (一) Object 类的概述
    • (1) hashCode
      • (2) getClass
        • (3) finalize()
          • (4) clone()
            • 用法:
            • 分类:
          • (5) wait、notify和notifyAll
            • (6) toString()——重要
              • 为什么要用它呢?
              • 补充:
            • (7) equals()——重要
              • equals() 和 == 的区别 ?
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档