你真的熟悉Java中的继承与多态?给你几分钟能回答上来(1)

}

public Employee(String s) {
System.out.println(s);
}
}

class Person {
public Person() {
System.out.println(“(1) Performs Person’s tasks”);
}
}

结果:

在第3 行,new Faculty() 调用Faculty 的无参构造方法。由于 Faculty 是 Employee 的子类,所以,在Faculty 构造方法中的所有语句执行之前,先调用 Employee 的无参构造方法。Employee 的无参构造方法调用Employee 的第二个构造方法(第13 行)。由于 Employee 是 Person 的子类,所以,在 Employee 的第二个构造方法中所有语句执行之前,先调用 Person 的无参构造方法。

2.3 调用父类的方法

super.方法名(参数);

3.方法重写

子类从父类中继承方法。有时,子类需要修改父类中定义的方法的实现,这称作方法重 写(method overriding),:要重写一个方法,需要在子类中使用和父类一样的签名以及一样的返回值类型来对该方法进行定义。

注意以下几点:

  1. 仅当实例方法是可访问时,它才能被覆盖。因为私有方法在它的类本身以外是不能访问的,所以它不能被覆盖。如果子类中定义的方法在父类中是私有的,那么这两个方法完全没有关系。
  2. 子类不能用语法 super.super.toStringO 访问父类的父类中的toString ,这是一个语法错误。
  3. 与实例方法一样,静态方法也能被继承。但是,静态方法不能被覆盖。如果父类中定义的静态方法在子类中被重新定义,那么在父类中定义的静态方法将被隐藏。可以使用语法:父类名 .静态方法名(SuperClassName.staticMethodName) 调用隐藏的静态方法。

这个再次详细说明一下

public class StaticExtends {

public static void main(String[] args) {
//声明为Father类,son1静态方法和Father类绑定
Father son = new Son();

son.method();
son.staticMethod();

Son son2 = new Son();
son2.method();
son2.staticMethod();
}
}

class Father {

void method() {
System.out.println(“父类方法”);
}

static void staticMethod() {
System.out.println(“父类静态方法”);
}
}

class Son extends Father {

@Override
void method() {
System.out.println(“子类方法”);
}

static void staticMethod() {
System.out.println(“子类静态方法”);
}
}

输出结果:

在子类中重写父类的static方法,是不会报错的,编译也可以通过,但是在通过一个声明为父类,实际类型为子类的引用变量调用该方法时,发现被调用的仍是父类中原本以为会被覆盖的方法,不具有“多态”特性。所以呢,父类的static方法是不会被重写的。

4.Object类及其常用方法

Java 中的所有类都继承自 java.lang.Object 类,如果在定义一个类时没有指定继承性,那么这个类的父类就被默认为是 Object。

4.1 toString()方法

Object 类中toString()方法的默认实现是:

public String toString() {
return getClass().getName() + “@” + Integer.toHexString(hashCode());
}

调用一个对象的 toString() 会返回一个描述该对象的字符串。默认情况下,它*返回一个由该对象所属的类名、at 符号(@)以及该对象十六进制形式的内存地址组成的字符串。*这个信息不是很有用,所以重写。

  • 像String、Date、File、包装类等都重写了Object类中的toString()方法。使得在调用对象的toString()时,返回"实体内容"信息。
  • 可以根据需要在用户自定义类型中重写toString()方法。 如String 类重写了toString()方法,返回字符串的值。

s1=“hello”;
System.out.println(s1);//相当于System.out.println(s1.toString());

  • 基本类型数据转换为String类型时,调用了对应包装类的toString()方法

int a=10;
System.out.println(“a=”+a);

4.2 equals()方法

Object 类中 equals 方法的默认实现是:

public boolean equals(Object obj) {
return (this obj);
}

说明:Object类中定义的equals()和==的作用是相同的:比较两个对象的地址值是否相同.即两个引用是否指向同一个对象实体。

  • 像String、Date、File、包装类等都重写了Object类中的equals()方法。重写以后,比较的不是两个引用的地址是否相同,而是比较两个对象的"实体内容"是否相同。
  • 通常情况下,我们自定义的类如果使用equals()的话,也通常是比较两个对象的"实体内容"是否相同。那么,我们 就需要对Object类中的equals()进行重写。重写的原则:比较两个对象的实体内容是否相同

tips:==和equals的区别:

  • 1 = 既可以比较基本类型也可以比较引用类型。对于基本类型就是比较值,对于引用类型 就是比较内存地址
  • 2 equals的话,它是属于java.lang.Object类里面的方法,如果该方法没有被重写过默认也是;我们可以看到String等类的equals方法是被重写过的,而且String类在日常开发中用的比较多,久而久之,形成了equals是比较值的错误观点。
  • 3 具体要看自定义类里有没有重写Object的equals方法来判断。
  • 4 通常情况下,重写equals方法,会比较类中的相应属性是否都相等。

二. 多态

5.1 介绍

首先呢,我们知道继承关系使一个子类继承父类的特征,并且附加一些新特征。子类是它的父类的特殊化,每个子类的实例都是其父类的实例,但是反过来就不成立。例如:每个圆都是一个几何对象,但并非每个几何对象都是圆。因此,总可以将子类的实例传给需要父类型的参数。使用父类对象的地方都可以使用子类的对象。这就是通常所说的多态。简单来说,多态意味着父类型的变量可以引用子类型的对象。

5.2 动态绑定

我们都知道方法可以在父类中定义而在子类中重写。(方法可以在沿着继承链的多个类中实现。JVM 决定运行时调用哪个方法。)那么

Object o = new SonObject();
System.out.println(o.toSting);

这里的 o 调用哪个 tostring() 呢? 我们首先介绍两个术语:声明类型和实际类型。**一个变量必须被声明为某种类型。变量的这个类型称为它的声明类型(declared type)。**这里,o 的声明类型是 Object。一个引用类型变量可以是一个 null 值或者是一个对声明类型实例的引用。实例可以使用声明类型或它的子类型的构造方法创建。变量的实际类型(actual type) 是被变量引用的对象的实际类。这里,o 的实际类型是SonObject, 因为 o 指向使用 new SonObject() 创建的对象。o 调用哪个toString() 方法由 o 的实际类型决定。这称为动态绑定(dynamic binding)。 也就是多态情况下,编译时,看左边;运行时,看右边。 “看左边”:看的是父类的引用(父类中不具备子类特有的方法) “看右边”:看的是子类的对象(实际运行的是子类重写父类的方法)

态绑定工作机制如下:假设对象 o 是类 Cl, C2, … ,Cn-1, Cn 的实例,其中 C1是 C2的子类,C2 是 C3 的子类,… ,Cn-1是 Cn 的子类。也就是说,Cn 是最通用的类,C1是最特殊的类。在 Java 中,Cn 是 Object 类。如果对象 o 调用一个方法 p, 那么JVM 会依次在类 Cl,C2, … ,Cn-1,Cri 中查找方法 p 的实现,直到找到为止一旦找到一个实现,就停止査找,然后调用这个首先找到的实现。

看以下代码:

public class DynamicBindDemo {
public static void main(String[] args) {
m(new GraduateStudent());
m(new Student());
m(new Person());
m(new Object());
}

public static void m(Object x) {
System.out.println(x.toString());
}
}

class GraduateStudent extends Student {

}

class Student extends Person {
@Override
public String toString() {
return “Student”;
}
}

class Person {
@Override
public String toString() {
return “Person”;
}
}

输出结果:

5.3 对象转换和instanceof()运算符

5.3.1 对象转换

对象的引用可以类型转换为对另外一种对象的引用,这称为对象转换。

更多:Java进阶核心知识集

包含:JVM,JAVA集合,网络,JAVA多线程并发,JAVA基础,Spring原理,微服务,Zookeeper,Kafka,RabbitMQ,Hbase,MongoDB,Cassandra,设计模式,负载均衡,数据库,一致性哈希,JAVA算法,数据结构,加密算法,分布式缓存等等

image

高效学习视频

。**

更多:Java进阶核心知识集

包含:JVM,JAVA集合,网络,JAVA多线程并发,JAVA基础,Spring原理,微服务,Zookeeper,Kafka,RabbitMQ,Hbase,MongoDB,Cassandra,设计模式,负载均衡,数据库,一致性哈希,JAVA算法,数据结构,加密算法,分布式缓存等等

[外链图片转存中…(img-yzLeXj9G-1714574012992)]

高效学习视频

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

  • 8
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值