JAVASE语法零基础——抽象类和接口
Write once,Runanywhere.🔥🔥🔥
💥 💥 💥如果你觉得我的文章有帮助到你,还请【关注➕点赞➕收藏】,得到你们支持就是我最大的动力!!!
💥 💥 💥
⚡版权声明:本文由【马上回来了】原创、在CSDN首发、需要转载请联系博主。
版权声明:本文为CSDN博主「马上回来了」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
🚀🚀🚀 新的知识开始喽🚀🚀🚀
Object是Java默认提供的一个类。Java里面除了Object类,所有的类都是存在继承关系的,默认会继承Object父类,即所有类的对象都可以使用Object的引用进行接收。
范例:使用Object接收所有类的对象
class Person{
//重写了Object.toString方法
@Override
public String toString() {
return "Person{}";
}
}
class Student{
}
public class Test {
private static void func(Object o){//Object接收 向上转型
// String ret = o.toString();
// System.out.println(ret);
System.out.println(o);//Object类引用 会默认调用toString方法打印哈希值
}
public static void main(String[] args) {
func(new Person());
func(new Student());
}
}
所以在开发之中,Object类是参数的最高统一类型。但是Object类也存在有定义好的一些方法。如下:
对于整个Object类中的方法需要实现全部掌握本小节当中,我们主要来熟悉这几个方法:toString()方法,equals()方法,hashcode()方法。
如果要打印对象中的内容,可以直接重写Object类中的toString()方法,之前已经讲过了,此处不再累赘。
// Object类中的toString()方法实现:
public String toString() { return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
在java中,用等号==进行比较时:
1.如果==
两边是基本类型变量,比较的是变量中的值是否相同
2.如果==
两边是引用类型变量,比较的是引用变量地址是否相同
3.如果要比较对象中的内容,必须重写object中的equals方法,因为equals方法默认也是按照地址比较的:
class Person{
public String id;
}
public class Test {
public static void main(String[] args) {
Person person = new Person();
Person person1 = new Person();
System.out.println(person==person1);//输出结果为false ==两边引用类型比较的是地址
}
}
运行结果:
class Person{
public String id;
}
public class Test {
public static void main(String[] args) {
Person person = new Person();
Person person1 = new Person();
System.out.println(person==person1);//输出结果为false ==两边引用类型比较的是地址
System.out.println(person.equals(person1));//输出结果为false object中的方法默认还是比较地址
}
}
运行结果:
在Person类里重写equals方法后,
class Person{
public String id;
public Person(String id) {
this.id = id;
}
public boolean equals(Object obj) {
Person tmp =(Person)obj;//向下转型,将父类object引用转换为Person引用,然后赋值给中间Person引用变量tmp
return this.id.equals(tmp.id);// this-调用当前方法对象的引用 .访问对象里的成员变量id
// .equals-已经被编译器底层重写过的比较字符串的方法 (tmp.id)访问中间变量中的id成员变量
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person("123");
Person person1 = new Person("123");
System.out.println(person==person1);//输出结果为false ==两边引用类型比较的是地址
System.out.println(person.equals(person1));//输出结果为true 已经将Object中的equals方法重写
}
}
当然重写这个equals方法还没重写完,有下面三种情况:
1.equals的参数为null;
2.调用equals的引用与equals的参数是同一个引用;
3.equals的参数的引用类型与调用equals引用类型不一致;
代码展示:
情况一:
class Person{
public String id;
public Person(String id) {
this.id = id;
}
public boolean equals(Object obj) {
if(obj == null){//obj为null 没必要比较,直接返回false
return false;
}
Person tmp =(Person)obj;//将父类object引用转换为Person引用,然后赋值给中间Person引用变量tmp
return this.id.equals(tmp.id);// this-调用当前方法对象的引用 .访问对象里的成员变量id
// .equals-已经被编译器底层重写过的比较字符串的方法 (tmp.id)访问中间变量中的id成员变量
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person("123");
Person person1 = new Person("123");
Person person2 = null;
System.out.println(person.equals(person2));//输出结果为false
}
}
情况2:
class Person{
public String id;
public Person(String id) {
this.id = id;
}
public boolean equals(Object obj) {
if(obj == this){//obj与调用当前equals的引用是同一个引用,不用比较直接返回true
return true;
}
Person tmp =(Person)obj;//将父类object引用转换为Person引用,然后赋值给中间Person引用变量tmp
return this.id.equals(tmp.id);// this-调用当前方法对象的引用 .访问对象里的成员变量id
// .equals-已经被编译器底层重写过的比较字符串的方法 (tmp.id)访问中间变量中的id成员变量
}
}
public class Test {
public static void main(String[] args) {
Person person = new Person("123");
Person person3 = person;
System.out.println(person.equals(person3));//输出结果为true
}
}
情况三:
class Person{
public String id;
public Person(String id) {
this.id = id;
}
public boolean equals(Object obj) {
if(!(obj instanceof Person)){//obj引用类型与调用equals引用的类型不是同一种类型,无法比较直接返回false
return false;
}
Person tmp =(Person)obj;//将父类object引用转换为Person引用,然后赋值给中间Person引用变量tmp
return this.id.equals(tmp.id);// this-调用当前方法对象的引用 .访问对象里的成员变量id
// .equals-已经被编译器底层重写过的比较字符串的方法 (tmp.id)访问中间变量中的id成员变量
}
}
class Student{
}
public class Test {
public static void main(String[] args) {
Person person = new Person("123");
Student student = new Student();
System.out.println(person.equals(student));//输出结果为false
}
}
所以完整的equals重写的完整方法:
class Person{
public String id;
public Person(String id) {
this.id = id;
}
public boolean equals(Object obj) {
if(obj == null){
return false;
}else if(obj == this){
return true;
}else if(!(obj instanceof Person)){
return false;
}
Person tmp =(Person)obj;//将父类object引用转换为Person引用,然后赋值给中间Person引用变量tmp
return this.id.equals(tmp.id);// this-调用当前方法对象的引用 .访问对象里的成员变量id
// .equals-已经被编译器底层重写过的比较字符串的方法 (tmp.id)访问中间变量中的id成员变量
//return this.name.equals(person.name) && this.age==person.age ;//当比较自定义对象多个值时,用&&符号
}
结论:比较对象中内容是否相同的时候,一定要重写equals方法。
回忆toString的原码:
public String toString() {
return getClass().getName() + "@" + Integer.toHexString(hashCode());
}
我们看到了hashCode()这个方法,他帮我算了一个具体的对象位置,这里面涉及数据结构,但是我们还没学数据结构,没法讲述,所以我们只能说它是个内存地址。然后调用Integer.toHexString()方法,将这个地址以16进制输
出。
对于同一个类里两个对象他们的成员变量相同,当我们没有重写hashcode方法时,会打印出两个对象的地址:
class A{
public String id;
public A(String id) {
this.id = id;
}
}
public class Test {
public static void main(String[] args) {
A a =new A("123");
A a1 = new A("123");
System.out.println(a.hashCode());
System.out.println(a1.hashCode());
}
}
运行结果:
但是我们认为这两个对象他们的内容都是一样的,给他们分配两个空间地址是多余的,这个两个对象应该就是使用的同一个地址,此时我们从写hashcode方法:
class A{
public String id;
public A(String id) {
this.id = id;
}
@Override
public int hashCode() {
return Objects.hash(id);
}
}
public class Test {
public static void main(String[] args) {
A a =new A("123");
A a1 = new A("123");
System.out.println(a.hashCode());
System.out.println(a1.hashCode());
}
}
运行结果:
注意事项:哈希值一样。
结论:
1、hashcode方法用来确定对象在内存中存储的位置是否相同
2、事实上hashCode() 在散列表中才有用,在其它情况下没用。在散列表中hashCode() 的作用是获取对象的
散列码,进而确定该对象在散列表中的位置。
🌏🌏🌏今天的你看懂这里又学到了很多东西吧🌏🌏🌏
🌔 🌔 🌔下次见喽🌔 🌔 🌔