Object类入门这一篇就够了!
第三阶段 JAVA常见对象的学习
第一章 常见对象——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型整数,用于确定该对象在哈希表中的索引位置
暂时了解即可,学习集合框架内容后将会专篇深入学习
//Student类
public class Student extends Object {
}
//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
返回对象的字节码文件对象,在反射篇章详细解释, 暂做简单了解。
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:
int a = 20;
int b = a;
那么我们想要复制一个对象,是不是也可以这样做呢?
//Student
public class Student {
int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
//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传值的时候,两者仍然会同时变化,并没有起到克隆(独立)的作用,这是因为赋值时只是将存储在栈中,对对象的引用赋值,因此它们两个的引用指向同一个对象(堆中),所以无论如何赋值,只要堆中的对象属性发生了变化,通过引用显示属性的时候,均是相同的。
用法:
- 实现Cloneable接口
- 重写clone方法
分类:
浅拷贝: 仅拷贝对象,不拷贝成员变量,仅复制了变量的引用,拷贝前后变量使用同一块内存,内存销毁后,必须重新定义(两者同生共死)
深拷贝: 不仅拷贝对象,也拷贝成员变量(真正意义上的复制, 两者独立无关)
//浅拷贝
public class Person implements Cloneable{
private int age = 20;
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
//深拷贝
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;
}
}
我们来利用浅拷贝解决刚开始那个问题
//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(): 返回该对象的字符串表示
//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;
}
}
//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
很明显,给我们返回这样的信息意义是不大的,所以我们建议对所有子类重写该方法
//在Student类中重写 toString()
@Override
public String toString() {
return "Student[" + "name=" + name + ", " + "age=" + age + "]";
//运行结果:
Student[name=admin, age=20]
通过重写toString后,结果按照我们所定的规则以字符串的形式输出
(重写后会优先使用类中的toString方法)
为什么要用它呢?
主要目的还是为了简化输出
在类中重写toString()后,输出类对象就变得有了意义(输出s 和 s.toString()是一样的 ,不写也会默认调用),变成了我们实实在在的信息,而不是上面的cn.bwh_04_toString.Student@1b6d3586。
如果我们想要多次输出 类中的成员信息,就需要多次书写get方法(每用一次就得写)
System.out.println("Student[" + "name=" + s.getName() + ", " + "age=" + s.getAge() + "]");
而调用toString()就简单多了
补充:
//两者等价
toString();
getClass().getName()+ '@' + Integer.toHexString(hashCode())
//输出结果
cn.bwh_04_toString.Student@1b6d3586。
(7) equals()——重要
比较两个对象是否相同
默认情况下,比较的是地址值是否相同。
而比较地址值是没有意义的,所以,一般子类也会重写该方法。
在诸多子类,如String、Integer、Date 等均重写了equals()方法
改进思路:
我们可以将比较地址值转变为比较成员变量
因为name为String类型,而String类型为引用类型,所以不能够用==比较,应该用equal()
String中默认重写过的equal()方法是用来比较字符串内容是否相同
我们要使用的是学生类的成员变量,所以父类 Object不能调用子类Student的特有功能
所以使用向下转型
//重写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;
}
}
//重写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;
}
//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 的作用:
引用类型:默认情况下,比较的是地址值。
注:一般选择重写方法,比较对象的成员变量值是否相同 ,不过一般重写都是自动生成。
结尾:
如果内容中有什么不足,或者错误的地方,欢迎大家给我留言提出意见, 蟹蟹大家 !_
如果能帮到你的话,那就来关注我吧!(系列文章均会在公众号第一时间更新)
在这里的我们素不相识,却都在为了自己的梦而努力 ❤
一个坚持推送原创Java技术的公众号:理想二旬不止
Object类入门这一篇就够了!的更多相关文章
- React入门看这篇就够了
摘要: 很多值得了解的细节. 原文:React入门看这篇就够了 作者:Random Fundebug经授权转载,版权归原作者所有. React 背景介绍 React 入门实例教程 React 起源于 ...
- [转]React入门看这篇就够了
摘要: 很多值得了解的细节. 原文:React入门看这篇就够了 作者:Random Fundebug经授权转载,版权归原作者所有. React 背景介绍 React 入门实例教程 React 起源于 ...
- [转帖]Zookeeper入门看这篇就够了
Zookeeper入门看这篇就够了 https://my.oschina.net/u/3796575/blog/1845035 Zookeeper是什么 官方文档上这么解释zookeeper,它是一个 ...
- .NET Core实战项目之CMS 第五章 入门篇-Dapper的快速入门看这篇就够了
写在前面 上篇文章我们讲了如在在实际项目开发中使用Git来进行代码的版本控制,当然介绍的都是比较常用的功能.今天我再带着大家一起熟悉下一个ORM框架Dapper,实例代码的演示编写完成后我会通过Git ...
- Git入门仅这篇就够了
版权声明:本文为博主原创文章,未经博主允许不得转载. 转载请表明出处:http://www.cnblogs.com/cavalier-/p/5978937.html 前言 大家好,我是Cavalier ...
- Struts2入门这一篇就够了
前言 这是Strtus的开山篇,主要是引入struts框架...为什么要引入struts,引入struts的好处是什么,以及对Struts2一个简单的入门.... 为什么要引入struts? 既然Se ...
- Hibernate入门这一篇就够了
前言 本博文主要讲解介绍Hibernate框架,ORM的概念和Hibernate入门,相信你们看了就会使用Hibernate了! 什么是Hibernate框架? Hibernate是一种ORM框架,全 ...
- 《ElasticSearch入门》一篇管够,持续更新
一.顾名思义: Elastic:灵活的:Search:搜索引擎 二.官方简介: Elasticsearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTf ...
- c语言入门这一篇就够了-学习笔记(一万字)
内容来自慕课网,个人学习笔记.加上了mtianyan标签标记知识点. C语言入门 -> Linux C语言编程基本原理与实践 -> Linux C语言指针与内存 -> Linux C ...
随机推荐
- IO 的底层实现问题
最近在看 JAVA NIO 的相关知识,了解一下IO的底层实现原理. IO涉及到的底层的概念大致如下: 1) 缓冲区操作.2) 内核空间与用户空间.3) 虚拟内存.4) 分页技术. 一,虚拟存储器 虚 ...
- percona-toolkit 主从工具 master-slave
复制类 pt-heartbeat 监控mysql复制延迟 pt-slave-delay 设定从落后主的时间 pt-slave-find 查找和打印所有mysql复制层级关系 pt-slav ...
- webservice 概念+测试案例
webservice的概念?(一句话概括什么是WebService) WebService是一种跨编程语言.跨操作系统平台的远程调用技术.远程调用技术: 远程调用是指一台设备上的程序A可以调用另一台设 ...
- [CQOI2016]手机号码 数位DP
[CQOI2016]手机号码 用来数位DP入门,数位DP把当前是否需要限制取数范围(是否正在贴着临界值跑,即下面的limited)和一切需要满足的条件全部塞进记忆化搜索参数里面就好了,具体情况转移便好 ...
- mysql40题
一.表关系 请创建如下表,并创建相关约束 导入现有数据库数据: /* Navicat Premium Data Transfer Source Server : localhost Source Se ...
- 在Android中使用OpenGL ES进行开发第(三)节:绘制图形
一.前期基础知识储备笔者计划写三篇文章来详细分析OpenGL ES基础的同时也是入门关键的三个点: ①OpenGL ES是什么?与OpenGL的关系是什么?——概念部分 ②使用OpenGLES绘制2D ...
- c语言 指针数组
指针数组指针数组是数组,指针数组每个元素是一个指针指针数组的定义:type* parray[n]; type* 是数组中每个元素的类型parray 为数组名n为大小 例子:float* a[3] // ...
- React的基本认识
1.1.1. 官网 1) 英文官网: https://reactjs.org/ 2) 中文官网: https://doc.react-china.org/ 1.1.2. 介绍描述 1) 用于构建用户 ...
- JAVA基础知识|HTTP协议-两个特性
一.无连接 无连接:服务器与浏览器之间的一次连接只处理一个http请求,请求处理结束后,连接断开.下一次请求再重新建立连接. 然而随着互联网的发展,一台服务器同一时间处理的请求越来越多,如果依然采用原 ...
- 通过JDBC API访问数据库的基本步骤
1.获取要访问的数据库的JDBC驱动程序的类库文件,把它放到classpath中. 2.在程序中加载并注册JDBC驱动程序.例如,以下代码用于加载并注册MySQL驱动程序: //加载MySQL Dri ...