2.Object
2.1.概述
1. Object类是所有类继承层次的祖先类,所有类(包括数组)都直接或者间接的继承自该类,都实现了该类的方法。
2. 我们在自定义类时,并不需要特别标注extends Object。
3. 如果一个类没有明确的指出它的父类,Object类就默认被认为是这个类的父类,extends Object则被省略了。
2.2.默认的无参构造
- 当一个类没有定义构造方法的时候,就会自动添加默认构造方法
- 一旦有默认构造方法,在创建子类对象的时候,就会执行子类对象的隐式初始化
- 隐式初始化,默认调用父类的无参构造
- 所以最终,一定能保证,调用到Object类的无参构造方法,先初始化Object这个父类
2.3.一些常用成员方法
2.3.1.public final Class<?> getClass()
- 其作用是返回调用此方法的Object的运行时类的Class对象。
- 需要注意的是Class首字母大写,这是一个类的对象,和String一样
- JVM每加载一个类,都会在内存中创建唯一一个和该类对应的Class对象
- 这个Class对象包含了这个类的全部信息
- 帮助程序员在运行时期,了解该对象的属性和行为
- Class对象处于堆上
- 在运行时期程序员可以通过这个类,获取该类型的所有信息
- 由于Class对象和类是一一对应的,所有Class对象很多时候被称为类对象
- Class对象和方法区中加载的字节码文件,都是在触发类加载的时候生成的
- 类加载只会触发一次,Class对象也只独一份
- 类的对象和类对象的区别
- 一个类的Class对象叫做类对象,也称之为运行时类对象,整个程序运行期间独一份
- 类的对象是类的一个实例,程序运行期间可以创建多个
- Class类对象是反射的基础
- Class的常用API
getName()
获取类的全限定类名getSimpleName()
获取类名
2.3.2.public String toString()
- 返回该对象的字符串(String)表示
- 通常,toString 方法会返回一个“以文本方式表示”此对象的字符串
- 结果应是一个简明但易于读懂的信息表达式
- 建议所有子类都重写此方法
- 直接打印数组名或者对象名,默认调用
toString()
方法,然后打印该方法返回的字符串- 用一个字符串和一个对象直接拼接,默认拼接该类的
toString()
方法字符串- debug时下一步会打印
toString()
返回的字符串
- 不要在
toString()
方法里对对象进行操作,避免造成奇怪的bug- 如果类中有别的引用类型,可以在返回语句中调用该引用类型的
toString()
方法
2.3.3.public boolean equals(Object obj)
-
指示其他某个对象是否与此对象“相等”
- 此对象:调用
equals()
方法的对象 - 其他某个对象:
equals()
方法括号中的对象
- 此对象:调用
-
对象相等的含义
- 我们理想状态下的对象相等:
- 首先两个对象的类型要相同,如果类型都不想同,那就没有意义了
- 类型相同的情况下,比较成员变量的取值是否相等,都相等则认为两个对象相等
Object
类中的相等:- 只有两个对象的内存地址相等,才叫相等
- Object类中的
equals()
方法等价于==
- 对象存在堆上没有办法直接拿出来比,于是
==
比较的是两个对象的引用 - 两个引用变量是否相等,取决于它们是否指向了同一对象,也就是比较对象的内存地址
Object
类中的equal()
方法不能满足我们需求,需要自己手动重写该方法
- 我们理想状态下的对象相等:
-
设计
equals()
方法需遵循的原则- 自反性:对于任何非空引用值
x
,x.equals(x)
都应返回true
- 排他性:当比对的不是同种类型的对象或者是一个null时,默认返回
false
- 对称性:对于任何非空引用值
x
和y
,当且仅当y.equals(x)
返回 true 时,x.equals(y)
才应返回 true - 传递性:对于任何非空引用值
x
、y
和z
,如果x.equals(y)
返回true
,并且y.equals(z)
返回true
- 那么
x.equals(z)
应返回true
- 那么
- 一致性:对于任何非空引用值
x
和y
,多次调用x.equals(y)
始终返回true
或始终返回false
- 前提是对象上
equals
比较中所用的信息没有被修改
- 前提是对象上
- 其实只要按照下述原则重写,就能够满足上面的常规协定
- 若是不同类型的对象,直接认定不相等
- 若是相同类型的对象,认为具有相同的成员变量的两个对象,才是相等的
- 自反性:对于任何非空引用值
-
equals
方法使用注意事项:- 对于任何非空引用值
x
,x.equals(null)
都应返回false
- 不要使用一个
null
常量,调用方法,会引发程序错误- 在方法中,我们只能对方法的参数进行校验,没办法校验调用者
- 应该在外部写代码,防止使用一个
null
去调用方法
- 如果类中有引用类型的成员变量,继续调用该引用类型的
equal()
方法判断
- 对于任何非空引用值
2.3.4.public int hashCode()
- 通过一个哈希(散列)函数,返回该对象的哈希(码)值
- 支持此方法是为了提高哈希表的性能(主要是集合体系中用)
hashCode
的常规协定:- 在 Java 应用程序执行期间,在对同一对象多次调用
hashCode
方法时,必须一致地返回相同的整数,前提是将象进行equals
比较时所用的信息没有被修改(哈希值是根据成员变量来计算的)。从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致。 - 如果根据
equals(Object)
方法,两个对象是相等的,那么对这两个对象中的每个对象调用hashCode
方法都必须生成相同的整数结果。 - 如果根据
equals(java.lang.Object)
方法,两个对象不相等,那么对这两个对象中的任一对象上调用hashCode
方法不要求一定生成不同的整数结果。但是,程序员应该意识到,为不相等的对象生成不同整数结果可以提高哈希表的性能。
- 在 Java 应用程序执行期间,在对同一对象多次调用
hashCode()
方法是会返回一个对应于当前对象的一个整数,为了将来在集合中更快捷的查找对象- 集合类似于数组,但不同的是集合中只能装对象
- Java中的集合类
hashMap
、hashSet
底层的实现都是哈希表,之所以采用哈希表- 是因为他能克服链表和二叉树等数据结构在查询上的低效率问题
- 哈希表的存储,就是根据对象的哈希值,以此确定他的存储位置
2.3.5.protected Object clone()
-
创建并返回此对象的一个副本(对象的引用)
-
对于任何对象 x,表达式:
x.clone() != x
为true
(这一条是必须的)x.clone().getClass() == x.getClass()
为true
(一般情况下满足,非必须)x.clone().equals(x)
为true
(一般情况下满足,非必须)
-
clone()
方法的使用规范: 1,要想使用一个类的
clone()
方法,这个类都必须实现Cloneable
接口,否则抛出CloneNotSupportedException
异常 2,在一个类中创建,自身类对象的拷贝,无需重写
clone()
方法 3,
Object
类中的clone()
为protected
方法,除开2中的情况外,都必须重写clone()
方法,用来改变其访问权限 -
Cloneable
接口:- 该接口是一个标记接口,没有任何方法
- 空(标记)接口的意义:
- 实现空接口后,从成员角度,该类没有任何变化
- 但是在内存中,该类的数据类型已然发生了改变,成为了这个接口的一个实现类
- 空接口的作用:
- 空接口给该实现类打上了标记
- 使用
instanceOf
运算符,可以判断一个类是否是该空接口的实现类 - 如果判定是,可以进行一系列操作
使用clone() 方法创建对象:使用clone() 方法创建对象和new创建对象属于同等级别
-
浅拷贝和深拷贝:
- 浅拷贝:
- 被复制对象的,所有基本类型成员变量值,都与原来对象的相同,且独立
- 被复制对象的,所有引用类型的引用,仍然指向原来的对象,相当于复制了对象引用,而没有复制对象
- 深拷贝:
- 在浅拷贝的基础上,复制对象引用的同时,也复制了对象,并让复制的引用指向了复制的对象
Object
类当中的clone()
方法只是浅拷贝- 深拷贝基于浅拷贝实现,需要我们手动重写
clone()
方法实现
- 浅拷贝:
-
案例:
/**
* 对于创建深拷贝的副本,应该按如下步骤进行
* 1.每个子类及其父类实现Clonable接口
* 2.重写clone()方法并抛出CloneNotSupportedException异常,因为clone()方法的protected访问权限导致子类无法直接调用
* 3.对于每个涉及到的引用类型重新克隆
* 4.克隆完毕的对象指向新克隆的引用类型
* 5.返回克隆完毕的对象
*
*/
public class Star implements Cloneable{
int age;
String name;
public Star() {
}
public Star(int age, String name) {
this.age = age;
this.name = name;
}
//对于无引用类型的类,直接克隆即可,因为String的不变形,所以不必克隆
@Override
protected Object clone() throws CloneNotSupportedException {
//浅克隆
return super.clone();
}
}
public class Student implements Cloneable{
int age;
String name;
Star s;
public Student() {
}
public Student(int age, String name, Star s) {
this.age = age;
this.name = name;
this.s = s;
}
@Override
protected Object clone() throws CloneNotSupportedException {
//调用父类Object的clone()方法,返回Object对象,应强制类型转化为Student类型
Student cloneStudent = (Student) super.clone();
//对于Student对象,里边的Star引用类型应重新克隆,继续调用Clone()方法,并返回Star类型
Star cloneStar = (Star) this.s.clone();
//Student的对象里的Star引用类型指向新克隆的对象
cloneStudent.s = cloneStar;
//返回克隆完毕的Student类型
return cloneStudent;
}
}
public class Teacher implements Cloneable{
int age;
String name;
Student s;
public Teacher() {
}
public Teacher(int age, String name, Student s) {
this.age = age;
this.name = name;
this.s = s;
}
//与上一个克隆同理
//对于克隆的对象,每个被克隆对象只需管好自己的引用成员即可,不需要管引用成员里嵌套的引用成员变量,所以只需克隆两层
@Override
protected Object clone() throws CloneNotSupportedException {
Teacher cloneTeacher = (Teacher) super.clone();
Student cloneStudent = (Student) this.s.clone();
cloneTeacher.s = cloneStudent;
return cloneTeacher;
}
@Override
public String toString() {
return "Teacher{" +
"age=" + age +
", name='" + name + '\'' +
", s.name='" + s.name +'\''+
",s.age="+s.age +
",star.name='" + s.s.name +'\''+
",star.age="+ s.s.age +
'}';
}
}
public class Test {
public static void main(String[] args) throws CloneNotSupportedException {
//Test
Teacher t = new Teacher(18, "马云", new Student(10, "马化腾", new Star(99, "张三")));
Teacher cloneTeacher = (Teacher) t.clone();
System.out.println(cloneTeacher);
System.out.println(t);
System.out.println("-----------------------");
System.out.println(cloneTeacher.s);
System.out.println(t.s);
System.out.println("-----------------------");
System.out.println(cloneTeacher.s.s);
System.out.println(t.s.s);
cloneTeacher.name = "新垣结衣";
System.out.println(cloneTeacher.name);
System.out.println(t.name);
}
}
//输出结果
Teacher@1b6d3586
Teacher@4554617c
-----------------------
Student@74a14482
Student@1540e19d
-----------------------
Star@677327b6
Star@14ae5a5
新垣结衣
马云
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/181088.html