多态的概念、对象上下转型、多态的应用、异常(异常概念、异常分类、java异常处理机制、try...catch...finally、throw和throws、自定义异常)

多态的概念:

  • 多态性是指同一个操作作用于某一类对象,可以有不同的解释,产生不同的执行结果。
  • 多态存在的三个必要条件: 需要存在继承或实现关系 同样的方法调用而执行不同的操作、运行不同代码(重写) 在运行时父类或者接口的引用变量可以引用其子类的对象。
  • 多态的作用: 多态通过分离做什么和怎么做,从一个角度将接口和实现进行分离。 多态消除了类型之间的耦合关系 多态的存在提高了程序的拓展性和后期的可维护性。
abstract class Animal
{
	abstract void eat();
}
class dog extends Animal
{
	void eat()
	{
		System.out.println("狗啃骨头");
	}
}
class cat extends Animal
{
	void eat(){
		System.out.println("猫吃鱼");
	}
}
public class Main {
	public static void main(String[] args) {
		Animal an1=new dog();//在运行时父类或者接口的引用变量可以引用其子类的对象。向上转型
		Animal an2=new cat();
		an1.eat();
		an2.eat();
	}
}

对象的上下转型:

  • 由子类转换父类,在继承图上是向上移动的,一般称为向上转型
  • 向上转型是从一个较专用类型向通用类型转换,所以总是安全的,也就是说,子类是父类的超集
  • 向上转型过程中,类接口中唯一可能发生的事情是丢失方法,而不是获取方法
  • 与之相反的操作是向下转型,不安全(可能需要instanceof操作符协助)
  • instanceof运算符用来在运行时通过返回值来指出对象是否有特定类或者它的子类的一个实例。典型使用场合:在对对象做下转型之前,没有其他有关对象信息时务必使用instanceof来判断一下,以避免抛出ClassCastException异常。用法如下:
result=object instanceof class
result:布尔类型
object:必选项,任意对象表达式
class:必选项,任意已定义的对象类
说明:如果object是class或其子类的一个实例(引用),则instance运算符返回true
      如果不是或者object是null,则返回false
  • 对象的上下转型举例:
abstract class Animal
{
	abstract void eat();
}
class dog extends Animal
{
	void eat()
	{
		System.out.println("狗啃骨头");
	}
	void sleep()
	{
		System.out.println("狗狗睡觉");
	}
}
class cat extends Animal
{
	void eat(){
		System.out.println("猫吃鱼");
	}
}
public class Main {
	public static void main(String[] args) {
		Animal an1=new dog();//在运行时父类或者接口的引用变量可以引用其子类的对象。
		Animal an2=new cat();
		an1.eat();
		//an1.sleep();向上转型过程中,类接口中唯一可能发生的事情是丢失方法。这里就无法调用sleep方法
		//我感觉这里是因为父类没有该方法,而子类有这个方法,所以这个方法会丢失。
		an2.eat();
		
		//cat cat1=(cat)an1;这样强制向下转型会抛出异常
		
		if(an1 instanceof cat){
			System.out.println("可以转型");
			cat cat1=(cat)an1;//在这里并没有输出,因为an1并不是cat或其子类的一个实例(引用),
		}
		if(an2 instanceof cat){
			System.out.println("可以转型");
			cat cat1=(cat)an2;//在这里有输出,因为an2是cat的一个实例
		}
	}
}
  • 不使用多态代码示例:
class School
{
	CaiSeDaYinJi c1;
	HeiBaiDaYinJi h1;
	void AnzhuangDaYinJi(CaiSeDaYinJi c1)
	{
		this.c1=c1;
	}
	void AnzhuangDaYinJi(HeiBaiDaYinJi h1)
	{
		this.h1=h1;
	}
	void ShiYongCaiSeDaYinJi(String context)
	{
		c1.print(context);
	}
	void ShiYongHeiBaiDaYinJi(String context)
	{
		h1.print(context);
	}
}
abstract class DaYinJi
{
	String name;
	public DaYinJi(String name) {
		this.name=name;
	}
	abstract void print(String context);
}
class CaiSeDaYinJi extends DaYinJi
{
	public CaiSeDaYinJi(String name) {
		super(name);
	}
	void print(String context) {
		System.out.println(this.name+"彩色打印:"+context);
	}
}
class HeiBaiDaYinJi extends DaYinJi
{
	public HeiBaiDaYinJi(String name) {
		super(name);
	}
	void print(String context) {
		System.out.println(this.name+"黑白打印:"+context);
	}	
}
public class Main {
	public static void main(String[] args) {
		CaiSeDaYinJi c1=new CaiSeDaYinJi("惠普1");
		HeiBaiDaYinJi h1=new HeiBaiDaYinJi("惠普2");
		School s=new School();
		s.AnzhuangDaYinJi(c1);
		s.AnzhuangDaYinJi(h1);
		s.ShiYongCaiSeDaYinJi("使用彩色打印打印");
		s.ShiYongHeiBaiDaYinJi("使用黑白打印打印");	
	}

}
  • 将上述代码改为多态的形式进行编写,方便代码功能的添加使代码耦合性更强。
class School
{
	DaYinJi d1;
	void AnzhuangDaYinJi(DaYinJi d1)
	{
		this.d1=d1;
	}
	void ShiYongDaYinJi(String context)
	{
		d1.print(context);
	}
}
abstract class DaYinJi
{
	String name;
	public DaYinJi(String name) {
		this.name=name;
	}
	abstract void print(String context);
}
class CaiSeDaYinJi extends DaYinJi
{
	public CaiSeDaYinJi(String name) {
		super(name);
	}
	void print(String context) {
		System.out.println(this.name+"彩色打印:"+context);
	}
	
}
class HeiBaiDaYinJi extends DaYinJi
{
	public HeiBaiDaYinJi(String name) {
		super(name);
	}
	void print(String context) {
		System.out.println(this.name+"黑白打印:"+context);
		
	}	
}
public class Main {
	public static void main(String[] args) {
		CaiSeDaYinJi c1=new CaiSeDaYinJi("惠普1");
		HeiBaiDaYinJi h1=new HeiBaiDaYinJi("惠普2");
		School s=new School();
		s.AnzhuangDaYinJi(c1);
		s.ShiYongDaYinJi("使用彩色打印");
		s.AnzhuangDaYinJi(h1);
		s.ShiYongDaYinJi("使用黑白打印");
	}
}

异常:

  • 异常概念、异常分类、java异常处理机制、try…catch…finally、throw和throws、自定义异常

异常的概念:

  • 什么是异常? 所谓的异常是指在程序运行的过程中发生的一些不正常事件(如:除0溢出,数组下标越界,所要读取的文件不存在)。
  • 异常导致的后果? java程序的执行过程中如出现异常事件,可以生成一个异常类对象,该异常对象封装了异常事件的信息,并将其被提交给java运行时系统,这个过程称为抛出异常,不处理的话会直接导致程序直接中断。
  • 如何防止程序中断? 设计良好的程序应该在程序异常发生时提供处理这些异常的方法,使得程序不会因为异常的发生而阻断或产生不可预见的结果。
  • java异常的分类:分为errorExceptionerror: 这个异常时系统运行java虚拟机的异常,和代码没有关系,这种异常我们一般处理不了,基本上都是要去检查操作系统和检查运行环境。Exception: 这个异常我们能够处理,分为IOExceptionRuntimeException
  • 除了上面的异常分类之外我们还将异常分为以下类别:
异常类型包括来源处理
受检查异常(checkException)Exception及其子类(不包括RuntimeException)由代码控制能力之外的因素导致的运行时错误必须要处理,否则通不过编译
非受查异常(uncheckedException)Error和RuntimeException及其子类RuntimeException一般代表编程错误可以不用处理
  • 受检查异常: 比如说:去读取磁盘上某个文件,文件不存在或者要连接某个服务器而连不上,因为这些原因产生的异常就要处理,否则程序可能会运行到一半时崩了。
  • 非受查异常: 比如说:java虚拟机运行时的异常或者程序代码里面类似除数等于0这样的异常或者多态处理上下转型时的异常,这些都是编程时由于代码问题而导致的编程错误,这种异常可以不用处理。
  • java异常处理机制: Try-catch-finally, try: 监控区域,执行可能产生异常的代码。catch: 捕获、处理异常。finally: 善后处理,无论是否发生异常,代码总能执行。try{}语句块中放的代码是要检测的java代码,可能会抛出异常,也可能会正常执行。catch(异常类型){}块是当java运行时系统接收到try块中所抛出异常对象时,会寻找能处理这一异常catch块来进行处理(可能有多个catch块)。finally{}不管系统有没有抛出异常都会去执行,除了在之前执行了System.exit(0);一般用来释放资源。这几部分代码块里面的代码变量是不相关的,相当于局部变量吧。
  • Java里try catch的简单用法: ①try+catch: 程序的流程是:运行到try块中,如果有异常抛出,则转到catch块去处理。然后执行catch块后面的语句。②try+catch+finally: 程序的流程是:运行到try块中,如果有异常抛出,则转到catch块,catch块执行完毕后,执行finally块的代码,再执行finally块后面的代码。如果没有异常抛出,执行完try块,也要去执行finally块的代码。然后执行finally块后面的语句。③try+finally: 程序的流程是:运行到try块中,如果有异常抛出的话,程序转向执行finally块的代码。那末finally块后面的代码还会被执行吗?不会!因为没有处理异常,所以遇到异常后,执行完finally后,方法就已抛出异常的方式退出了。
  • 下面是java异常处理的示例代码:
import java.util.Scanner;
class Person
{
	String name;
}
public class Main {
	public static void main(String[] args) {
		int a=10;
		int b;
		int c;
		Scanner sc=new Scanner(System.in);
		Person p=null;
		System.err.println("请输入除数:");
		b=sc.nextInt();
		try{
			c=a/b;
			p.name="FHN";
		}
		catch(Exception e){ //Exception e这个是捕获所有的异常,有了这句就不用写下面的catch了
			System.out.println("空指针异常,请检查有没有初始化指针!");
		}
//		catch(NullPointerException e){
//			System.out.println("空指针异常,请检查有没有初始化指针!");
//		}
//		catch(ArithmeticException e){
//			System.out.println("除数为0,请检查输入的除数,重新输入!");
//			b=sc.nextInt();
//			c=a/b;
//			System.out.println("c="+c);
//		}
		finally{
			System.out.println("end");
		}
		System.out.println("end2");//如果在只用try和finally,在有异常时不会执行到这句,程序在这句之前就退出了
	}
}

throw和throws:

  • throw用于手动抛出异常,作为程序员可以在任意位置手动抛出异常。
  • throws用于在方法上标识要暴露的异常,抛出的异常交由调用者处理。
  • 两者区别: throw用在方法内,后面跟上要抛出的异常类对象。throws修饰在方法上,告诉调用者此方法可能会抛出异常,后面跟上可能要抛出异常类名。 throw:手动抛出异常。throws:声明方法可能要抛出异常。
  • 代码示例:
class Bar
{
	int age;
	public Bar(int age) {
		this.age=age;
	}
	void check ()throws IllegalArgumentException //throws修饰在方法上,告诉调用者此方法可能会抛出异常,后面跟上可能要抛出异常类名。
	{
		if(age<18){
			throw new IllegalArgumentException("年纪太小");//年纪太小,会在异常抛出时显示
		}
	}
}
public class Main {
	public static void main(String[] args) {
		Bar b=new Bar(15);
		try{
			b.check();
		}
		catch(IllegalArgumentException e){
			System.out.println(e.getMessage());
			e.printStackTrace();//显示异常的数据
		}
		System.out.println("end");
	}
}

自定义异常:

  • 常见异常:RuntimeException、IOException、SQLException、ClassNotFoundException
  • 自定义异常: java提供的异常体系不可能遇见所有加以报告的错误
  • 自定义异常类必须从已由的异常类继承。 建立新的异常类型最简单的方法就是让编译器产生默认构造方法。 对于异常来说,最重要的部分就是它的类名。 可以为异常类定义一个接受字符串参数的构造方法,字符串参数描述异常信息。
  • 下面是使用自己定义的异常类,来手动抛出异常的代码:
class Bar
{
	int age;
	public Bar(int age) {
		this.age=age;
	}
	void check ()throws AgeLess //throws修饰在方法上,告诉调用者此方法可能会抛出异常,后面跟上可能要抛出异常类名。
	{
		if(age<18){
			throw new AgeLess("年纪太小");//年纪太小,会在异常抛出时显示
		}
	}
}
class AgeLess extends Exception //AgeLesss是自己定义的异常类,继承自Exception,是首查异常
{
	private String message;
	public AgeLess(String message) {
		this.message=message;
	}
	public String getMessage() { //重写了父类的getMessage
		return this.message;
	}
}
public class Main {
	public static void main(String[] args) {
		Bar b=new Bar(15);
		try{
			b.check();
		}
		catch(AgeLess e){
			System.out.println(e.getMessage());
			e.printStackTrace();//显示异常的详细数据,这里是父类的方法
		}		
		System.out.println("end");
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值