飞道的博客

Java -- 面向对象(三)

447人阅读  评论(0)

本篇的重点是介绍多态的使用,上篇中介绍的继承,子类和父类,其实将父类对象应用于子类的特征就是多态。虽然不好理解,建议关于多态的定义理解,看一下参考书,因为他是抽象的内容,而且多态的综合性非常强,一条语句可能就包含很多的知识点;建议多练习,新手的话多尝试逐字逐句分析代码的含义,使其抽象的内容做到有自己的理解方式;

十二、final

1、概念
  1. 是java提供的一个关键字;
  2. final是最终的意思;
  3. final可以修饰类,方法,成员变量;
  • 初衷是因为:java出现了继承后,子类可以更改父类的功能,当父类功能不许子类改变时可以利用final关键字修饰父类。
2、特点
  1. 被final修饰的类,不能被继承;
  2. 被final修饰的方法,不能被重写;
  3. 被final修饰的变量是个常量,值不能被更改;
  4. 常量的定义形式: 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、特点
  1. 多态的前提是继承;
  2. 要有方法的重写;
  3. 父类引用指向子类对象,如:Animal a = new Dog(); – 小到大,向上转型;
  4. 多态中,编译看左边,运行看右边
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. 创建子类,继承汽车类。覆盖/重写 启动和停止功能;
  3. 创建子类对象,进行子类的功能测试;
  4. 创建多态对象,进行功能测试;

十四、异常

1、概述
  • 用来封装错误信息的对象;
  • 组成结构:类型,提示,行号;
2、异常的继承结构
Throwable - 顶级父类
-- Error:系统错误,无法修复
-- Exception:可修复的错误
	--RunTimeException
		--ClassCastException
		--ClassNotFoundException
3、异常处理
  • 程序中遇到了异常,通常有两种处理方式:捕获或者向上抛出;
  • 当调用了一个抛出异常的方法时,调用位置可以不做处理继续向上抛出也可以捕获异常。

不建议向上抛出,尽量捕获,不要选择抛出,要不然开发者就刺激了;

  1. 捕获方式:
try{ 
    需要捕获的代码
}catch(异常类型  异常名){
    处理方案
}
  1. 抛出方式:
    在会发生异常的方法上添加代码: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
//其实,相当于创建了一个子类对象一样,可以用父类的,也可以用自己的

说明:向下转型时,是为了方便使用子类的特殊方法,也就是说当子类方法做了功能拓展,就可以直接使用子类功能。

向下转型不建议使用,还不如直接创建子类对象

【友情提示】

  1. 本篇文章到此又要告一段落了,学到现在得你是不是满脑瓜问号了呢???
  2. 兔八哥友情提示------勤复习,多总结,自己找每个特点之间的联系,也许画一个思维导图是个不错的选择呢!!
  3. 思维导图 ---- 敬请期待,等写完面向对象会第一时间上传思维导图的哦(づ ̄3 ̄)づ╭❤~

【下篇预告】

  • 抽象类
  • 接口

转载:https://blog.csdn.net/qq1808814025/article/details/105458831
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场