Java面向对象三大特征之多态

本文介绍了Java中的多态概念及其实现前提,通过具体示例展示了如何利用多态进行对象设计,同时讨论了final关键字的用途及其在修饰数据、方法和类时的作用。
final关键字:最终的无法改变
final可以用来修饰:数据、方法和类
1、修饰数据:该数据一旦被赋值,将不能被改变
2、修饰方法:该方法不能被子类重写(覆盖),private修饰的方法隐含默认为final修饰
3、修饰类:该类不能被继承,final类中所有的方法都隐式指定为final

4、用于引用变量上,该引用变量的引用不能被改变


多态

什么是多态呢?

多态即一种事物多种形态,例如:一只二哈,我们可以叫其二哈,也可以叫其狗,也可以叫它小动物,比如水,可以有三种状态:液体,固体和气体


多态的定义:指同一操作作用于某一类对象,可以有不同的解释,产生不同的执行结果


实现多态的前提:
1.需要存在继承和实现关系
2.同样的方法调用而执行不同的操作,运行不同的代码(重写)
3.在运行时父类或者接口的引用变量可以引用其子类的对象
Animal  a = new Dog();
Animal  a : 为父类或者接口的引用变量
new  Dog():子类的对象

下面举个例子:

根据人类的行为惯等,定义一个人的模板出来,即人类

package com.pyj.demo;
/**
 * 定义一个人的类
 * @author Pyj
 *
 */
public class Person {
	private String name;//姓名
	private int age;//年龄
	//一个无参的构造方法
	public Person() {
	}
	//有参构造方法
	public Person(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;
	}
	//吃饭的方法
	public void eat(){
		System.out.println("吃饭");
	}
	//睡觉的方法
	public void sleep(){
		System.out.println("睡觉");
	}
	//输出个人的信息
	public void show(){
		System.out.println("姓名:"+name+",年龄:"+age);
	}
	
}


下面为一个学生,我们想一下,学生也是人,所以学生也有人的所有行为特征,并且学生是需要上学的,所以学生有自己的上学方法,并且学生考试所有有成绩,下面就是学生类,它是人,所以我们使用extends关键字来使学生也有人的一切行为习惯

package com.pyj.demo;

public class Student extends Person {
	private int score;//分数
	public Student() {
	}
	public Student(String name, int age,int score) {
		super(name, age);
		this.score = score;
	}
	//取值赋值方法
	public int getScore() {
		return score;
	}
	public void setScore(int score) {
		this.score = score;
	}
	@Override
	public void show() {
		super.show();//使用父类的show方法
		System.out.println("分数:"+score);
	}
	@Override
	public void eat() {
		//super.eat();//调用父类吃饭方法
		System.out.println("学生吃营养餐");
	}
	@Override
	public void sleep() {
		super.sleep();//父类的睡觉方法
		System.out.println("学生睡十个小时");
	}
	//学生自己的上课方法
	public void attendClass(){
		System.out.println("学生去上课");
	}
}

下面我们用下面的例子来说明一下

package com.pyj.demo;

public class Test {
	public static void main(String[] args) {
		/*Student student = new Student("张三",17,90);
		student.show();//调用学生的show方法
		student.setScore(100);//为学生重新设置分数
		student.attendClass();//学生自己的上课方法
		student.eat();//学生的吃饭方法
		student.sleep();//学生的睡觉方法
		student.show();//学生的show方法*/
		
		Person p = new Student("李四",20,88);
		p.show();//调用show方法
		//p.setScore(100);无法使用学生的设置分数的方法
		//p.attendClass();无法使用学生的上课方法
		p.eat();//吃饭方法
		p.sleep();//睡觉方法
		p.show();//show方法
	}
}


下面我们来看test里面第一段注释代码,这段代码执行产生的结果,即Student student = new Student()一系列产生的结果


下面这个代码的图,为上面代码中没有注释的部分,即Person p = new Student();产生的结果


可以看出当我们使用的父类的引用变量时,会失去其子类的属性,子类特有方法,如果父类方法与子类方法名字一样,默认子类重写了父类的方法



总结了一下多态成员访问的特点:

1.父类的引用变量不能使用子类私有的方法,包括子类私有变量的取值赋值访法
2.当父类的变量调用方法时,如果这个方法被子类重写了,则调用被子类重写的方法,如果没有被重写,则会调用父类自身的方法。
3.子类可以访问父类的所有公开的方法以及属性
4.静态的方法或者变量存在方法区中,通过使用类名.属性 或者类名.方法来使用,哪个类有静态的变量或者方法,就用哪个类名


多态的好处和弊端:

好处:
1.多态解除了类型之间的耦合关系
2.多态的存在提高了程序的扩展性和后期的可维护性
弊端:
前期建立父类的引用虽然可以接收后期所有该类的子类对象。
   但是只能使用父类中的功能,不能使用子类中的特有功能,
   因为前期的程序无法知道后期的子类的特有内容的。
   但是前期的程序可以使用子类覆盖了父类的方法的内容


多态的向上转型:

由子类转型成父类,在继承图上是向上移动的,所以一般称为向上转型,向上转型是从一个具体的类型向较通用类型的转换,所以总是安全的,也就是说子类是父类的一个超集。

缺陷:向上转型过程中,类或接口中唯一发生的事情就是方法的丢失,而不是获取方法,丢失子类特有的方法
Person p = new Student(“张三”,17,90);
Student会丢失特有的方法,即无法被调用,父类的引用变量只能调用父类的特有的方法或者子类重写父类的方法


多态的向下转型

由父类转型成子类,在继承图上是向下移动的,所以一般称为向下转型,向下转型是从一个较通用的类型向具体类型的转换,所以是不安全的,需要使用
instancof 操作符来判断,instanceof运算符返回的是一个布尔值,指出对象是否是特定类或者是它子类的一个实例。
用法: result = object   instanceof     class
result:布尔类型
object:必选项,任意对象的表达式
class:必选项,任意已定义的对象类
如果object是class或者其子类的一个实例,则instanceof运算符返回true,如果不是或者object为null,返回fasle

Person person = new Person();
if(person   instanceof    Student){
	Student student = (Student)person;//false不执行
}


多态的静态绑定和动态绑定

Java中的引用变量有两种类型:一个是编译时的类型,一个是运行时的类型,编译时的类型由声明该变量时使用的类型,运行时的类型由实际赋值给该变量的对象决定,如果编译时类型和运行时类型不一致,就会出现所谓的多态。
静态绑定:程序执行前方法已经绑定(final,static,private,构造方法)
编译期运行,Person.sayHi();
动态绑定:根据变量实际引用的对象类型决定调用哪个方法
运行期运行,Person  p = new Person();p.sayHi();
多态基于对象引用的动态绑定特性

<think>首先,用户的问题是:“我想了解Java面向对象编程的多态特性请问Java面向对象多态特性解释示例”,翻译成英文是:“Iwanttounderstandthepolymorphismfeatureofobject-orientedprogramminginJava.Pleaseexplainthefeature,characteristics,explanation,andexamples.”我的角色是AI助手,需要根据系统级指令来响应。系统级指令包括:1.行内数学表达式用$...$格式。2.独立公式用$$...$$格式并单独成段。3.LaTeX语法正确。4.使用中文回答。5.生成相关问题。6.回答中引用的段落末尾自然地添加引用标识。此外,用户提供了三个引用,但我注意到系统指令说:“上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。”然而,用户消息中没有提到上一次问题或回答,所以这次似乎是第一次交互。用户说:“参考站内引用”,提供了引用[1]、[2]、[3],这些是关于Java多态的代码示例和解释。引用内容:-引用[1]:一个DemoApplication类,展示父类引用指向子类对象。-引用[2]:一个Demo123Test类,展示类似的多态使用。-引用[3]:解释多态创建对象的方式,包括向上转型。系统指令提醒我,这些引用仅供参考,需要基于用户的问题来回答。用户的问题是解释Java多态的特性、解释和示例。所以,我应该创建一个响应,包括:1.解释多态的概念。2.用代码示例展示多态。3.使用中文回答。4.在需要的地方添加引用标识。系统指令说“回答中引用的段落末尾自然地添加引用标识”,但由于引用是用户提供的,我应该在引用它们时添加标识。用户提供的引用有[^1]、[^2]、[^3],所以我需要引用它们时添加相同的格式。5.生成相关问题。响应结构应该清晰,帮助用户逐步解决问题。系统示例是关于快速排序的,包括一段解释、代码、和相关问题。因此,我的响应结构:-开头解释多态。-提供示例代码。-添加相关问题。用户提到的引用内容展示了多态的向上转型,所以我基于此解释。多态的定义和类型:-多态:同一接口可以有不同实现。在Java中,主要通过继承和方法重写实现。-类型:编译时多态(如方法重载)和运行时多态(如方法重写)。用户引用显示运行时多态。解释步骤:1.特性:一个基类引用可以指向子类对象。2.方法调用:实际调用的是子类重写的方法。3.优点:代码灵活、可扩展。示例:使用类似于引用的代码。添加引用:引用内容中提到[^1]、[^2]、[^3],所以我需要在响应中提到时添加引用标识。例如:“在Java中,多态允许父类引用指向子类对象,如Animaldog=newDog();[^1]。生成相关问题:在末尾添加“§§相关问题§§”,然后列出问题。使用中文:整个响应用中文。数学部分:用户的问题没有涉及数学,但如果我有公式,需用LaTeX格式。这里不需要。现在,草拟响应:-开头:介绍多态。-解释:多态面向对象三大特性之一(继承、封装、多态)。允许对象在不同条件下表现出不同形式。-在Java中,通过继承和接口实现。-展示向上转型代码。-方法重写示例。-添加引用。相关问题示例:1.多态和继承有什么区别?2.如何在Java中实现多态的最佳实践?3.多态在真实项目中的应用场景?响应结构:Java中的多态特性解释...```java//示例代码```特性...[添加引用]§§相关问题§§1....2....确保引用自然添加。系统指令说“自然地添加引用标识”,例如在解释中提到引用时加[^1]。在引用内容时加。例如:“如引用[1]中所示,Animaldog=newDog();[^1]。”使用相同的引用编号。完整响应。</think> ### Java面向对象编程中的多态特性 多态(Polymorphism)是面向对象编程(OOP)的核心特性之一,它允许对象在运行时根据其实际类型表现出不同行为,从而提高代码的灵活性和可维护性。在Java中,多态主要通过继承和方法重写(Override)实现,同时涉及向上转型(Upcasting)和动态绑定(Dynamic Binding)机制。以下我将从特性解释、原理说明和代码示例等方面逐步介绍。 #### 特性解释 多态的核心特性包括: - **代码重用和灵活性**:通过父类或接口类型引用子类对象,可以在不修改原有代码的基础上扩展新功能。例如,一个父类引用可以指向不同子类的对象,并调用重写的方法[^3]。 - **运行时动态绑定**:在编译时,方法调用基于引用类型检查(编译时多态);但在运行时,实际调用的方法是基于对象的真实类型(运行时多态)。这使得程序能根据具体对象类型调整行为[^2]。 - **隐藏实现细节**:用户通过父类接口操作对象,不需要关心子类的具体实现,这有助于降低耦合度,提升模块化设计[^1]。 多态分为两种类型: - **编译时多态**:通过方法重载(Overload)实现,例如,同一个类中定义多个同名方法但参数不同。 - **运行时多态**:通过方法重写实现,这是Java多态的重点,如父类方法被子类覆盖。 #### 原理说明 在Java中,多态的关键是向上转型(Upcasting),即父类类型引用指向子类对象: - **语法形式**:`<父类类型> <引用变量> = new <子类类型>();`。例如,`Animal dog = new Dog();`,此时引用变量`dog`虽然是Animal类型,但实际创建的是Dog对象[^3]。 - **方法调用规则**: - 引用变量能调用父类中声明的方法。 - 如果子类重写了父类方法,调用时优先执行子类的方法(运行时绑定)。 - 但引用变量不能直接调用子类特有的方法(需要向下转型),这保证了类型安全[^1][^2]。 - **优点**:支持开放-封闭原则(对扩展开放,对修改封闭),常用于框架设计(如集合类、GUI事件处理)[^1]。 #### 代码示例 以下是一个完整的Java示例,演示运行时多态的工作原理。代码基于用户提供的引用内容简化,展示父类引用指向子类对象,以及方法重写的效果。 ```java // 定义父类 Animal class Animal { int age = 5; // 父类成员变量 public void sound() { System.out.println("动物发出声音"); } } // 定义子类 Dog,重写父类方法 class Dog extends Animal { int age = 10; // 子类特有成员变量(隐藏父类变量) public void sound() { System.out.println("狗叫:汪汪!"); // 重写父类方法 } public void run() { System.out.println("狗在奔跑"); // 子类特有方法 } } // 测试类,展示多态应用 public class DemoApplication { public static void main(String[] args) { // 向上转型:父类引用指向子类对象 Animal dog = new Dog(); System.out.println("年龄: " + dog.age); // 输出:5(访问父类变量,无多态效果) dog.sound(); // 输出:"狗叫:汪汪!"(运行时调用子类重写方法) // 注意:dog.run(); // 编译错误!引用类型为Animal,不能调用Dog特有的方法[^1][^3] } } ``` **示例分析**: - **第1步:向上转型**:`Animal dog = new Dog();` 创建Dog对象,但引用为Animal类型[^1]。 - **第2步:变量访问**:`dog.age` 输出5,因为成员变量无多态,访问基于引用类型。 - **第3步:方法调用**:`dog.sound()` 输出"狗叫:汪汪!",证明运行时绑定到Dog类的重写方法。 - **第4步:限制**:`dog.run()` 无法调用,因为父类未声明此方法,需要向下转型(如 `if (dog instanceof Dog) ((Dog) dog).run();`)[^2][^3]。 通过这个示例,你可以看到多态如何简化代码扩展:添加新子类(如Cat)只需重写sound()方法,无需修改测试类。 多态特性让Java程序更健壮,常见于集合框架(如List引用指向ArrayList或LinkedList对象)和企业应用开发。如需更多优化建议,可参考引用内容中的最佳实践[^2][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值