目录
一、equals
- == 和equals的对比
1. ==: ==是一个比较运算符,既可以判断基本类型,又可以判断引用类型
2. ==: 如果判断的是基本类型,判断的值是否相等。
3. ==: 如果判断的是引用类型,判断的是地址是否相等,即判断是不是同一个对象
4. equals: equals是Objectll类中的方法,只能判断引用类型
5. equals默认判断的是地址是否相等,子类中往往重写该方法,用于判断内容是否相等。比如Integer,String
package com.learn.object_;
public class Equals01 {
public static void main(String[] args) {
A a = new A();
A b = a;
A c = b;
System.out.println(a == c); //true
System.out.println(b == c); //true
B obj = a;
System.out.println(obj == c); //true
//equals方法, 源码怎么查看.
//把光标放在equals方法上直接ctrl + b
"hello".equals("abc");
/*
//JDk的源码,String类的equals
//把Object的equals方法重写了,变成了比较两个字符串值是否相同
public boolean equals(Object anObject) {
if (this == anObject) { //如果是同一个对象
return true; //返回true
}
if (anObject instanceof String) { //判断类型是否相等
String anotherString = (String)anObject; //向下转型
int n = value.length;
if (n == anotherString.value.length) { //如果两个字符串长度相等
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) { //用循环一个一个的比较字符
if (v1[i] != v2[i]) //只要有一个字符串不相同就返回false
return false;
i++;
}
return true; //如果两个字符串的所有字符都相等,则返回true
}
}
return false; //如果比较的不是字符串,直接返回false
}
*/
/*
//看看Object类的 equals
//即 Object类的 equals方法 默认就是比较对象是否相同,也就是判断两个对象是不是同一个对象
public boolean equals(Object obj) {
return (this == obj);
}
*/
/*
//从源码可以看到 Integer 也重写了Object的equals方法,变成判断两个值是否相等
public boolean equals(Object obj) {
if (obj instanceof Integer) { //如果当前Integer的值等于传进来的Integer对象的值
return value == ((Integer)obj).intValue(); //返回true
}
return false;
}
*/
//练习题
Integer integer1 = new Integer(1000);
Integer integer2 = new Integer(1000);
System.out.println(integer1 == integer2); //false,它们指的不是同一个对象
System.out.println(integer1.equals(integer2)); //true,它们两的值相同
String learn1 = new String("learn");
String learn2 = new String("learn");
//判断地址是否相同(同一个对象)
System.out.println(learn1 == learn2); //false,new了两次,两个指向不同的对象
//判断两个的值是否相同
System.out.println(learn1.equals(learn2)); //true,两个值都为learn
}
}
class B {}
class A extends B {}
equals练习题
package com.learn.object_;
public class EqualsExercise01 {
public static void main(String[] args) {
Person person1 = new Person("jack", 10, '男');
Person person2 = new Person("jack", 10, '男');
//没有重写equals,equals方法是从Object调来的,Object的equals方法默认比较两个对象是否相等
System.out.println(person1.equals(person2));
}
}
//要求:
//判断两个 Person 对象的内容是否相等,
//如果两个 Person 对象的各个属性值都一样,则返回 true,反之 false
class Person{ //extends Object
private String name;
private int age;
private char gender;
public Person(String name, int age, char gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
//重写Object 的 equals方法
public boolean equals(Object obj){
//判断如果比较的两个对象是同一个对象,则直接返回true
if(this == obj){
return true;
}
//进行类型判断
if(obj instanceof Person){ //传入的obj是一个Person类型,我们才比较
//进行类型转换,向下转型,为了取得传进来的对象的属性(传入的是Object类型,所以要转)
//传参的时候发生了向上转型,而instanceof是比较运行类型,obj的编译类型是Object
//而运行类型不是Object,所以要向下转型再取回属性比较
Person p = (Person)obj;
return this.name.equals(p.name) && this.age == p.age && this.gender == p.gender;
}
//如果不是Person,则直接返回false
return false;
}
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;
}
public char getGender() {
return gender;
}
public void setGender(char gender) {
this.gender = gender;
}
}
二、hashCode方法
小结: 1.提高具有哈希结构的容器的效率
2.两个引用如果指向的是同一个对象,则哈希值肯定是一样的
3.两个引用如果指向的不是同一个对象,则哈希值是不一样的
4.哈希值主要是根据地址来的,不能完全将哈希值等价于地址
5.在讲集合时会详讲如何重写hashCode
三、toString方法
1.基本介绍
①默认返回:全类名(包名+类名) + @ + 哈希值的十六进制
②子类中往往重写toString方法,用于返回对象的属性信息
2.重写toString方法,打印对象属性或拼接对象的属性时,都会自动调用该对象的toString形式
3.当直接输出一个对象时,toString方法会被默认调用。
比如:System.out.pringln(monster);默认调用monster.toString()
package com.learn.object_;
public class ToString_ {
public static void main(String[] args) {
/*
Object的toString()源码
1.getClass().getName() 类的全类名(包名+类名)
2.Integer.toHexString(hashCode()) 将对象的hashCode值转成16进制字符串
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
*/
Monster monster = new Monster("小妖怪", "巡山", 1000);
System.out.println(monster.toString());
System.out.println("==当直接输出一个对象时,toString 方法会被默认的调用==");
System.out.println(monster); //等价于 monster.toString()
}
}
class Monster{
//属性
private String name;
private String job;
private double sal;
//构造器
public Monster(String name, String job, double sal) {
this.name = name;
this.job = job;
this.sal = sal;
}
//重写toString方法,输出对象的属性
//快捷键:alt + insert 生成toString方法
@Override
public String toString() { //重写后,一般是把对象的属性输出,当然程序员可以自己定制
return "Monster{" +
"name='" + name + '\'' +
", job='" + job + '\'' +
", sal=" + sal +
'}';
}
}
四、finalize方法
- 提示:在实际开发中,几乎不会用到finalize,更多的是为了应付面试
1.当对象被回收时,系统自动调用该对象的finalize方法。子类可以重写该方法,做一些释放资源的操作
2.什么时候被回收:当某个对象没有任何引用时,JVM就认为这个对象是一个垃圾对象,就会使用垃圾回收机制来销毁该对象,在销毁对象前会先调用finalize方法
3.垃圾回收机制的调用,是由系统来决定的(即有自己的GC算法),也可以通过System.gc() 主动触发垃圾回收机制
package com.learn.object_;
//演示 Finalize的用法
public class Finalize {
public static void main(String[] args) {
Car bmw = new Car("宝马");
//当执行bmw=null后,这时car对象就是一个垃圾,垃圾回收器就会回收(销毁)对象,在销毁对象前会调用该对象的finalize方法
//,程序员就可以在 finalize中写自己的业务逻辑代码(比如释放资源:数据库连接,或者打开文档...)
//,如果程序员重写了finalize,那就可以实现自己的逻辑
bmw = null;
System.gc();//主动调用垃圾回收器
System.out.println("程序退出了....");
}
}
class Car{
private String name;
public Car(String name) {
this.name = name;
}
//重写finalize方法
@Override
protected void finalize() throws Throwable {
// super.finalize();//默认情况下是调用Object的finalize方法
System.out.println("我们销毁 汽车" + name);
System.out.println("释放了某些资源...");
}
}