day11目录:
Object(类)
public int hashCode()
public final Class getClass()
public String toString()
public boolean equals(Object obj)
11.17_常见对象(API概述以及Object类的概述)(掌握)
A:API(Application Programming Interface)
应用程序编程接口
B:Java API
就是Java提供给我们使用的类,这些类将底层的实现封装了起来,
我们不需要关心这些类是如何实现的,只需要学习这些类如何使用。
C:Object类概述
类层次结构的根类
所有类都直接或者间接的继承自该类
D:构造方法
public Object()
回想面向对象中为什么说:
子类的构造方法默认访问的是父类的无参构造方法
11.18_常见对象(Object类的hashCode()方法)(掌握)
A:案例演示
public int hashCode()
a:返回该对象的哈希码值。默认情况下,该方法会根据对象的地址来计算。
b:不同对象的,hashCode()一般来说不会相同。
但是,同一个对象的hashCode()值肯定相同。
c:不是对象的实际地址值,可以理解为逻辑地址值。
public class MyTest {
public static void main(String[] args) {
//java.lang 包下的类 不需要导入包
// public class Object类 Object 是类层次结构的根类。每个类都使用 Object 作为超类。所有对象(包括数组)都实现这个类的方法。
//Object 类,是所有类的顶层父类,所有类都是直接或间接继承自她
//创建对象
Object obj = new Object();
System.out.println(obj);
int i = obj.hashCode();
System.out.println(i);
Object obj2 = new Object();
System.out.println(obj2);
int i1 = obj2.hashCode();
System.out.println(i1);
}
}
· 学习到后面,会和“集合”的知识有关
11.19_常见对象(Object类的getClass()方法)(掌握)
A:案例演示
public final Class getClass()
a:返回此 Object 的运行时类。
b:可以通过Class类中的一个方法,获取对象的真实类的全名称。
public String getName()
public class MyTest2 {
public static void main(String[] args) {
Object object = new Object();
System.out.println(object);
//返回该类的字节码文件对象。Object.java--->Object.class---->加载进内存--->JVM会为Object.class创建对象---->通过getClass()获取字节码文件对象
//Class 这个类型,用来表示是 字节码文件类型
Class<?> aClass = object.getClass();
Object object2 = new Object();
System.out.println(object2);
Class<?> aClass1 = object2.getClass();
System.out.println(object==object2);//false
System.out.println(aClass==aClass1); //true 字节码文件是一份
}
}
· 学习到后面,会和“反射”的知识有关
11.20_常见对象(Object类的toString()方法)(掌握)
A:案例演示
public String toString()
a:返回该对象的字符串表示。
源代码:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
b:它的值等于:
getClass().getName() + '@' + Integer.toHexString(hashCode())
c:由于默认情况下的数据对我们来说没有意义,一般建议重写该方法。
怎么重写, 一般是将该类的所有的成员变量组成返回即可
B:最终版
自动生成
C: 直接输出对应的名称,就是调用对象的toString()方法
public class MyTest {
public static void main(String[] args) {
Object obj = new Object();
//toString();获取该对象的地址值,以字符串的形式返回。
String s = obj.toString();
System.out.println(s);
System.out.println(obj); //当你打印对象名的时候,默认这个对象就在调用toString()方法
System.out.println(obj.toString());
}
}
public class MyTest2 {
public static void main(String[] args) {
Student student = new Student();
student.setName("张三");
student.setAge(23);
//int i = student.hashCode();
// Class<? extends Student> aClass = student.getClass();
String s = student.toString();
System.out.println(s);
System.out.println(student);
//两者结果一样:org.westos.demo2.Student@61bbe9ba
/*
* public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
*
* */
//我们觉得父类的toString()老是获取对象的地址值,我觉得意义不大,我想要获取我认为有意义的数据。比如我们想要看我的成员变量的值是什么,觉得有意义
}
}
子类重写了父类的tostring方法:
public class Student extends Object{
private String name;
private 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;
}
/* @Override
public String toString() {
return "姓名:"+this.name+"==年龄:"+this.age;
}*/
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
//输出结果:Student{name='张三', age=23}
当打印一个对象时,没打印地址值,说明该方法被重写了。例如:Scanner方法被重写了:
public class MyTest3 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
//1.地址值。 2.其他的
//以后,当你输出一个对象名的时候,如果输出的不是地址值,说明该类重写过toString();
System.out.println(scanner);
}
}
11.21_常见对象(Object类的equals()方法)(掌握)
A:案例演示
a:指示其他某个对象是否与此对象“相等”。
源代码:
public boolean equals(Object obj) {
return (this == obj);
}
b:默认情况下比较的是对象的引用是否相同。
c:由于比较对象的引用没有意义,一般建议重写该方法。一般用于比较成员变量的值是否相等
d:==和equals()的区别。(面试题):
// == 和 equals()方法的区别
// == 是比较运算符,可以比较基本数据类型,也可以比较引用数据类型。
// == 比较基本数据类型,比较的是两个值是否相等。
// == 比较的是引用数据类型,比较的是两个对象的地址值是否相同
public class MyTest3 {
public static void main(String[] args) {
Student s1 = new Student("崔继轩", 18);
Student s2 = new Student("卢佳苗", 19);
System.out.println(s1);
System.out.println(s2);
// == 他比如是比较引用类型,比较的是两个对象的地址值是否相同
System.out.println(s1==s2); //false
//equals() 默认也是在比较两个对象的地址值是否相同
boolean b = s1.equals(s2);
/*
public boolean equals (Object obj){
return (this == obj);
}
*/
System.out.println(b);
}
}
public class MyTest4 {
public static void main(String[] args) {
Student s1 = new Student("崔继轩", 18); //name age
Student s2 = new Student("崔继轩", 18);
//Object类中的equals()方法,默认是比较两个对象是否相等,
//但是有的时候,我们的子类认为,老是比较两个对象的地址值,是否相同意义不大
//子类想比较一些,他认为有意义的东西,比如我们自定义的这个Student类认为,只要两个对象的成员变量值一样,就认为这两个对象相同
boolean b = s1.equals(new Dog()); //ClassCastException
boolean b2 = s1.equals(s1);
//比较性能:
System.out.println(b);
System.out.println(b2);
}
}
class Dog{
}
11.22_常见对象(Object类的equals()方法代码优化)(掌握)
A:案例演示
Object类的equals()方法代码优化
a: 提高效率
b: 提高健壮性(instanceof)
B:最终版
自动生成
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 boolean equals(Object obj) { //Object obj=s2; s2 dog
if(this==obj){
return true;
}
//判断传过来的这个对象,是不是学生类型,如果是学生类型,我就向下转型,如果不是直接返回false
//instanceof 判断一个对象或引用,是不是该类型的一个引用
if(!(obj instanceof Student)){
return false;
}
//比较两个对象的成员变量值是否一样。
//obj.name 多态形式访问成员变量,编译看左边,运行也看左边。
//向下转型
Student s2= (Student) obj;
//"崔继轩"=="崔继轩" 比较的是地址值 如果是比较两个字符串,字面上的内容是否相同,我们用equals()
//boolean f = "崔继轩".equals("崔继轩");
//String 类重写了equals方法来比较两个字符串字面上的内容是否相同
return this.name.equals(s2.name)&&this.age==s2.age;
}
}
11.23_常见对象(Object类的clone() 方法)(掌握)
clone()的权限修饰符是受保护的,在用的时候,让该类重写该方法,并把该方法的权限修饰符改为public
对象的浅克隆:浅克隆和深克隆
使用clone()方法采用的是浅克隆的方式
对象浅克隆要注意的细节:
1. 如果一个对象需要调用clone的方法克隆,那么该对象所属的类必须要实现Cloneable接口。
2. Cloneable接口只不过是一个标识接口而已,没有任何方法。
3. 对象的浅克隆就是克隆一个对象的时候,如果被克隆的对象中维护了另外一个类的对象,这时候只是克隆另外一个对象的地址,而没有把
另外一个对象也克隆一份。
4. 对象的浅克隆也不会调用到构造方法的。
对象的深克隆(后面讲):采用IO流来实现 使用 ObjectOutputStream 将对象写入文件中,然后再用ObjectInputStream读取回来
浅克隆:只克隆了0X001
深克隆:克隆了0X001和0X002
public class MyTest {
public static void main(String[] args) throws CloneNotSupportedException {
DogFood dogFood = new DogFood("王中王");
Dog dog = new Dog("小白", 2, dogFood);
dog.dogFood.name="金锣";
//调用clone()方法属于浅克隆
//对象的浅克隆:就是克隆一个对象的时候,
//如果被克隆的对象中维护了另外一个类的对象,
//这时候只是克隆另外一个对象的地址,而没有把另外一个对象也克隆一份。
Dog dog1= (Dog) dog.clone();
dog1.name="小黑";
dog1.dogFood.name="双汇";
System.out.println(dog.name); //小白
System.out.println(dog.age); //2
System.out.println(dog.dogFood.name);//双汇
System.out.println("==========================");
System.out.println(dog1.name);//小黑
System.out.println(dog1.age);//2
System.out.println(dog1.dogFood.name); //双汇
}
}
class Dog implements Cloneable {
String name;
int age;
DogFood dogFood;
public Dog() {
}
public Dog(String name, int age, DogFood dogFood) {
this.name = name;
this.age = age;
this.dogFood = dogFood;
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); //继续调用父类的克隆逻辑
}
}
class DogFood{
String name;
public DogFood(String name) {
this.name = name;
}
}
11.23_day11重点总结
Object类的equals 方法是默认比较两个对象是否相等,但是有时候我们的子类认为,老是比较两个对象的地址值是否相同意义不大。
子类想比较一些他们认为有意义的东西,比如我们自定义的Student类认为,只要两个对象的成员变量值一样。
如果是比较两个字符串的字面内容是相同,我们用equals()。String类重写了equals方法来比较两个字符串字面上的内容
instanceof----判断一个对象或引用是不是一个该类型的一个引用----obj instanceof Student
以后你定义一个方法时,得从方法的健壮性(周全)先考虑,性能方面的优化
==和equals方法的区别:
==是比较运算符,可以比较基本数据类型,也可以用来比较引用数据类型;比较基本数据类型:比较的是两个值是否相等;比较的是引用数据类型:比较的是两个对象的地址值是否相同。
equals是Objetc类中的一个方法,默认比较的是两个对象的地址值是否相同,但是有些类会重写Object类中的equals()方法,去比较他认为的有用的东西。比如String类,他也重写了父类的equals()方法,比较的是两个字符串,字面上的内容是否相同。如果使我们自定义的类型,一般会重写,去比较两个对象的成员变量值是否一样。
Favorites—书签–ctrl 点
//TODO 。。。在下方RUn的旁边能找到
标记接口–Cloneable—接口中没有任何方法,就是给类打一个标记,告诉JVM可能要实现某种操作,让JVM能支持某种操作。
克隆一个对象时,需要注意以下两点:
- Object类中的克隆方法是个受保护的方法,为了能够调用到,我们可以让这个类重写克隆方法,把方法的权限修饰符改为public
- 为了克隆能够被支持,需要该类实现Cloneable这个标记接口
注意:克隆时不调构造方法
两个概念:深克隆、浅克隆
调用clone()属于浅克隆:就是只克隆了一个对象的地址值。