本篇的重点是介绍多态的使用,上篇中介绍的继承,子类和父类,其实将父类对象应用于子类的特征就是多态。虽然不好理解,建议关于多态的定义理解,看一下参考书,因为他是抽象的内容,而且多态的综合性非常强,一条语句可能就包含很多的知识点;建议多练习,新手的话多尝试逐字逐句分析代码的含义,使其抽象的内容做到有自己的理解方式;
十二、final
1、概念
- 是java提供的一个关键字;
- final是最终的意思;
- final可以修饰类,方法,成员变量;
- 初衷是因为:java出现了继承后,子类可以更改父类的功能,当父类功能不许子类改变时可以利用final关键字修饰父类。
2、特点
- 被final修饰的类,不能被继承;
- 被final修饰的方法,不能被重写;
- 被final修饰的变量是个常量,值不能被更改;
- 常量的定义形式: final 数据类型 常量名 = 值
3、测试案例
package cn.tedu.finaldemo;
public class Test_Final {
//测试final关键字
public static void main(String[] args) {
//创建子类对象测试
Son son = new Son();
// son.SUM = 5;//在不加final时可以修改,加上final之后不可以修改
//警告提示:The static field Son.SUM should be accessed in a static way
// System.out.println(son.SUM);//没有加static通过对象调用,
System.out.println(Son.SUM);//加上静态static之后,通过类名调用
}
}
//创建父类
//1、被final修饰的类是最终类,不能被继承
//final class Father {//The type Son cannot subclass the final class Father
class Father {
//2、被final修饰的方法是最终方法,不能被重写
// final public void eat() {//The type Son cannot subclass the final class Father
public void eat() {
System.out.println("爸爸在吃肉");
}
}
//创建子类
class Son extends Father{
//是子类的特有功能,只能创建子类对象才能调用
//3、final修饰的变量是常量,常量的值不能被修改
//4、变量前加了final是说变量变成了一个常量。加了static为了方便通过类名来直接调用
// int sum = 10;
static final int SUM = 10;
@Override
public void eat() {
System.out.println("儿子在喝汤");
}
}
控制台显示:10
十三、多态
1、概念
- 多态指同一个实体同时具有多种形式。它是面向对象程序设计(OOP)的一个重要特征;
- 主要是指同一个对象,在不同时刻,代表的对象不一样,指的是对象的多种形态;
- 好处是可以把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,统一调用标准;
- 例如:水,在不同时刻可以有多种形态,包括水蒸气,冰,水;
Java怎么体现多态呢?狗有两种形态:狗和小动物
class Animal{}
class Dog extends Animal{}
Dog d = new Dog();//狗是狗
Animal a = new Dog();//狗是小动物,创建了狗的对象,赋值给动物对象,这就是多态
2、特点
- 多态的前提是继承;
- 要有方法的重写;
- 父类引用指向子类对象,如:Animal a = new Dog(); – 小到大,向上转型;
- 多态中,编译看左边,运行看右边
3、入门案例
package cn.tedu.muiti;
//这个类用来测试多态
public class Test_Muiti {
public static void main(String[] args) {
//3、创建父类测试对象
Animal animal = new Animal();
animal.eat();
//4、创建子类测试对象
Dog dog = new Dog();
dog.eat();//重写前,使用的是父类的;重写后,使用的是子类的;
//5、创建多态测试对象
//口诀1:父类引用 指向 子类对象 -- 多态/向上转型
Animal animal2 = new Dog();
//口诀2:编译看左边,运行看右边
//编译看左边:想要保存成功,只能调用左边(父类)的功能 ---- 统一调用标准!!标准就是父类!!
//运行看右边:运行结果看子类的功能
animal2.eat();
}
}
//1、多态的前提:继承 + 重写
class Animal{
public void eat() {
// TODO Auto-generated method stub
System.out.println("...");
}
}
class Dog extends Animal{
//2、重写:子类的方法声明和父类一模一样
@Override //标志着这是在重写父类的方法
public void eat() {
System.out.println("真香。。");
}
}
控制台显示:
编译看左边:想要保存成功,只能调用左边(父类)的功能;
运行看右边:运行结果看子类的功能
4、多态的好处
(1)多态的使用
- 多态可以让我们不用关心某个对象到底是什么具体类型,就可以使用该对象的某些方法;
- 提高了程序的扩展性和可维护性;
(2)多态的使用特点
- 成员变量:使用的是父类的;
- 成员方法:由于存在重写现象所以使用的是子类的;
- 静态成员:随着对象而存在,谁调用的就返回谁的;
(3)测试案例
package cn.tedu.muiti;
public class Test_UseMulti {
public static void main(String[] args) {
//创建多态对象测试
Father f = new Son();
//1、多态中的成员方法怎么用??
//编译看左边,用父类提供的方法声明部分
//运行看右边,用子类提供的方法体 --- 多指方法 重写 现象
f.study();//天天向上
//2、多态中的成员变量怎么用? -- 父类的
System.out.println(f.sum);
//3、多态中的静态资源怎么用? -- 父类的
// System.out.println(f.name);
System.out.println(Father.name);
//4、测试一下静态方法能不能重写?? -- 静态资源不能重写,谁调用就是谁的
//因为静态资源是跟着类存在的
f.show();
Father.show();
}
}
//多态的前提:继承 + 重写
class Father{
int sum = 20;
static String name = "jack";
public void study() {
System.out.println("好好学习");
}
static public void show() {
System.out.println("Fa show...");
}
}
class Son extends Father{
int sum = 10;
static String name = "rose";
@Override
public void study() {
System.out.println("天天向上");
}
static public void show() {
System.out.println("son show...");
}
}
控制台显示:
由于多态综合了前面的封装和继承,所以需要多加练习更好的理解;
提供一个练习案例:
文末会提供练习的具体代码和答案!!!
/*
* 自己测试练习:
* --父类 --Teacher
* --子类 --Student
* --创建多态测试
* --成员变量,成员方法,静态资源
*/
设计多态的程序基本思路
假设现在有一个汽车类,我们可以根据汽车类创建很多汽车对象。
- 创建汽车类。提供启动、停止、运行功能;
- 创建子类,继承汽车类。覆盖/重写 启动和停止功能;
- 创建子类对象,进行子类的功能测试;
- 创建多态对象,进行功能测试;
十四、异常
1、概述
- 用来封装错误信息的对象;
- 组成结构:类型,提示,行号;
2、异常的继承结构
Throwable - 顶级父类
-- Error:系统错误,无法修复
-- Exception:可修复的错误
--RunTimeException
--ClassCastException
--ClassNotFoundException
3、异常处理
- 程序中遇到了异常,通常有两种处理方式:捕获或者向上抛出;
- 当调用了一个抛出异常的方法时,调用位置可以不做处理继续向上抛出也可以捕获异常。
不建议向上抛出,尽量捕获,不要选择抛出,要不然开发者就刺激了;
- 捕获方式:
try{
需要捕获的代码
}catch(异常类型 异常名){
处理方案
}
- 抛出方式:
在会发生异常的方法上添加代码:throws
异常类型 ;例如:
public static void main(String[] args) throws Exception{
}
4、测试
package cn.tedu.exception;
import java.util.Scanner;
//这个类用来测试异常的暴露
public class Test_Exception {
public static void main(String[] args) {
//method();//暴露异常
// method2();//捕获异常
//尽量捕获,不要选择抛出,要不然开发者就刺激了
try {
method3();
} catch (Exception e) {
// 开发阶段,上线的时候会被注释掉
e.printStackTrace();//通常用来排除错误
System.out.println("执行失败");//项目上线时给出的提示
}
}
//抛出异常:在会出错的方法上添加代码 throws 异常类型
//直接抛出Exception也是体现了多态,因为根本不关心具体的子类类型,会把子类当做父类来看,写出通用代码
public static void method3() throws Exception{
//接收用户输入的两个整数
int a = new Scanner(System.in).nextInt();
int b = new Scanner(System.in).nextInt();
//做除法运算
System.out.println(a/b);
}
//1、捕获异常 try{有可能发生异常的代码}catch(异常类型 异常名){解决方案}
private static void method2() {
try {
//接收用户输入的两个整数
int a = new Scanner(System.in).nextInt();
int b = new Scanner(System.in).nextInt();
//做除法运算
System.out.println(a/b);
} catch (Exception e) {//2、当try里的代码发生异常时,会给出捕获方案
//Exception就是多态的体现,好处是不关心具体的子类类型,会把子类当做父类来处理,写出通用代码
System.out.println("请输入正整数");
}
}
//暴露异常
public static void method() {
//接收用户输入的两个整数
int a = new Scanner(System.in).nextInt();
int b = new Scanner(System.in).nextInt();
//做除法运算
System.out.println(a/b);
}
}
访问控制符(背过就可以)
用来控制一个类,或者类中的成员的访问范围。
类 | 包 | 子类 | 任意 | |
---|---|---|---|---|
public | √ | √ | √ | √ |
protected | √ | √ | √ | |
default | √ | √ | ||
private | √ |
多态自我测试的答案
package cn.tedu.muiti;
/*
* 自己测试练习:
* --父类 --Teacher
* --子类 --Student
* --创建多态测试
* --成员变量,成员方法,静态资源
*/
public class MyTest {
public static void main(String[] args) {
//创建多态对象测试
Teacher t = new Student();
System.out.println(t.age);//30 --父类
Teacher.hei();//180老师 --父类
System.out.println(t.name);//tea --父类
t.study();//正在做题 --子类
//只有重写的方法才可以运行看右边
//如果,你非要用 子类的特有功能,多态对象不可能!!此时,只能创建子类对象。
// t.name//报错,因为t是多态对象,只能使用父类的功能,对于子类特有功能,多态对象无能为力
//方法一:创建子类对象 -- 建议使用
Student s = new Student();
System.out.println(s.name);
//方法二:向下转型 -- 多态叫做向上转型 -- 不建议使用
Student s2 = (Student) t;//右侧的t是父类 类型,给左侧的子类类型 s2赋值时,--需要强转
System.out.println(s2.name);
}
}
//Teacher类
class Teacher{
//成员变量
int age = 30;
//静态成员变量
static String name = "tea";
//方法
public void study() {
System.out.println("正在讲课");
}
//静态方法
static public void hei() {
System.out.println("180老师");
}
}
//Student类
class Student extends Teacher{
//成员变量
int age = 18;
//静态成员变量
static String name = "stu";
//方法
public void study() {
System.out.println("正在做题");
}
//静态方法
static public void hei() {
System.out.println("160学生");
}
}
涉及到向上转型和向下转型!!!
向上转型和向下转型
- 在JAVA中,继承是一个重要的特征,通过extends关键字,子类可以复用父类的功能,如果父类不能满足当前子类的需求,则子类可以重写父类中的方法来加以扩展;
- 在应用中就存在着两种转型方式,分别是:向上转型和向下转型。
比如:父类Parent,子类Child
向上转型:
- 父类的引用指向子类对象
Parent p=new Child();
- 说明:向上转型时,子类对象当成父类对象,只能调用父类的功能,如果子类重写了父类的方法就根据这个引用指向调用子类重写方法。
向下转型(较少): - 子类的引用的指向子类对象,过程中必须要采取到强制转型;
Parent p = new Child();//向上转型,此时,p是Parent类型;
Child c = (Child)p;//此时,把Parent类型的p转成小类型Child
//其实,相当于创建了一个子类对象一样,可以用父类的,也可以用自己的
说明:向下转型时,是为了方便使用子类的特殊方法,也就是说当子类方法做了功能拓展,就可以直接使用子类功能。
向下转型不建议使用,还不如直接创建子类对象
【友情提示】
- 本篇文章到此又要告一段落了,学到现在得你是不是满脑瓜问号了呢???
- 兔八哥友情提示------勤复习,多总结,自己找每个特点之间的联系,也许画一个思维导图是个不错的选择呢!!
- 思维导图 ---- 敬请期待,等写完面向对象会第一时间上传思维导图的哦(づ ̄3 ̄)づ╭❤~
【下篇预告】
- 抽象类
- 接口
- …
转载:https://blog.csdn.net/qq1808814025/article/details/105458831
查看评论