本文主要是介绍Java必须掌握的多态中调用成员的特点-(含面试大厂题含源码),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
在Java中,多态是面向对象编程的核心概念之一,它允许对象采取多种形式。多态的实现主要依靠继承和接口。在面向对象的设计中,多态性允许一个接口使用不同的实例,提高了代码的可重用性和可扩展性。
针对大厂面试题,我们可以设计一个关于Java多态中成员(特别是方法)调用的特点的问题。这个问题不仅考察了应聘者对多态概念的理解,还考察了对Java中方法重载和重写规则的掌握。
面试题
考虑以下Java代码:
class Animal {public void eat() {System.out.println("Animal is eating");}
}class Dog extends Animal {@Overridepublic void eat() {System.out.println("Dog is eating");}public void bark() {System.out.println("Dog is barking");}
}public class TestPolymorphism {public static void main(String[] args) {Animal myAnimal = new Dog();myAnimal.eat();// myAnimal.bark(); // 行A}
}
- 当执行
myAnimal.eat();
时,输出结果是什么?为什么? - 如果取消注释行A (
// myAnimal.bark();
),会发生什么?解释为什么会这样。 - 如何能够使
myAnimal
调用bark
方法,同时保留多态性的特性?提供代码示例。
答案
- 输出结果是
"Dog is eating"
。这是因为myAnimal
虽然被声明为Animal
类型,但实际指向的是Dog
类的实例。在Java中,调用的是实际对象的方法(即Dog
的eat
方法),这是多态性的表现。 - 取消注释行A后,代码将无法编译通过。这是因为编译器检查
myAnimal
的引用类型Animal
,而Animal
类中没有定义bark
方法。即使myAnimal
实际指向一个Dog
对象,由于在编译时只能调用引用类型中声明的方法,因此编译器不允许这种调用。 - 要调用
bark
方法,我们需要将myAnimal
的引用类型转换为Dog
,这样就可以调用Dog
类特有的方法了,同时还保持了对象的多态性。示例如下:
if (myAnimal instanceof Dog) {((Dog)myAnimal).bark();
}
这段代码首先检查myAnimal
是否真的是一个Dog
实例,如果是,就将其向下转型为Dog
类型并调用bark
方法。这种方式既利用了多态性,也确保了类型安全。以下是针对Java多态概念的三个面试题目,每个题目都附带了源码示例和相关问题。这些题目旨在测试应聘者对Java多态、方法重写、接口实现以及类型转换的理解和应用能能力。
面试题1: 方法重写与运行时多态
class Bird {public void sing() {System.out.println("Bird is singing");}
}class Sparrow extends Bird {@Overridepublic void sing() {System.out.println("Sparrow is singing");}
}public class PolymorphismExample {public static void main(String[] args) {Bird myBird = new Sparrow();myBird.sing();}
}
问题: 执行myBird.sing();
时,输出结果是什么?解释为什么会这样。
答案: 输出结果是"Sparrow is singing"
。这是因为myBird
虽然被声明为Bird
类型,但实际上它引用的是Sparrow
的一个实例。在Java中,这种情况下会调用实际对象(即Sparrow
对象)的方法,这是多态性的体现。
面试题2: 接口实现与多态
interface Swimmable {void swim();
}class Fish implements Swimmable {public void swim() {System.out.println("Fish is swimming");}
}class Duck extends Bird implements Swimmable {public void swim() {System.out.println("Duck is swimming");}@Overridepublic void sing() {System.out.println("Duck is singing");}
}public class InterfacePolymorphism {public static void main(String[] args) {Swimmable mySwimmable = new Duck();mySwimmable.swim();// ((Bird)mySwimmable).sing(); // 行B}
}
问题:
- 执行
mySwimmable.swim();
时,输出结果是什么?为什么? - 如果取消注释行B (
// ((Bird)mySwimmable).sing();
),执行该行代码时输出结果是什么?解释原因。
答案:
- 输出结果是
"Duck is swimming"
。因为mySwimmable
引用的是Duck
类的一个实例,该实例实现了Swimmable
接口的swim
方法。 - 执行
((Bird)mySwimmable).sing();
后,输出结果是"Duck is singing"
。因为mySwimmable
实际上指向的是一个Duck
对象,通过向下转型为Bird
类型,可以调用Duck
类重写的sing
方法。
面试题3: 抽象类、多态和方法重载
abstract class Shape {abstract void draw();
}class Circle extends Shape {void draw() {System.out.println("Drawing Circle");}// 方法重载void draw(String color) {System.out.println("Drawing Circle with color " + color);}
}public class AbstractClassExample {public static void main(String[] args) {Shape myShape = new Circle();myShape.draw();// ((Circle)myShape).draw("Red"); // 行C}
}
问题:
- 执行
myShape.draw();
时,输出结果是什么?解释为什么。 - 如果取消注释行C (
// ((Circle)myShape).draw("Red");
),执行该行代码时输出结果是什么?解释原因。
答案:
- 输出结果是
"Drawing Circle"
。这是因为myShape
虽然被声明为Shape
类型,但实际上引用的是Circle
类的一个实例。在运行时,会调用实际对象的draw
方法,即Circle
类中的draw
方法。 - 取消注释并执行行C后,输出结果是
"Drawing Circle with color Red"
。通过将myShape
向下转型为Circle
类型,可以调用重载的draw
方法,传入字符串参数进行绘制。这体现了多态性以及方法重载的概念。
这篇关于Java必须掌握的多态中调用成员的特点-(含面试大厂题含源码)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!