黑马程序员java之多态和异常

------- <a href="http://www.itheima.com" target="blank">android培训</a>、<a href="http://www.itheima.com" target="blank">java培训</a>、期待与您交流! ----------


Java之面向对象:多态和异常


多态


体现:父类引用或者接口的引用指向了自己的子类对象。

//Animal a = new Cat();

多态的好处:提高了程序的扩展性。

多态的弊端:当父类引用指向子类对象时,虽然提高了扩展性,但是只能访问父类中具备的方法,不可以访问子类中特有的方法。出现了访问的局限性


多态的前提:

   1:必须要有关系,比如继承、或者实现。

   2:通常会有覆盖操作。


package pract;


abstract class Animal{
	//父类方法
	abstract void eat();
	
}

public class Dog extends Animal  {
	//覆盖父类方法
	public void eat(){
		System.out.println("吃骨头");
	}
	//子类中特有方法
	public void sleep(){
		System.out.println("趴着睡");
	}


	public static void main(String[] args) {
		// 父类引用指向子类对象。
		Animal a = new Dog();//类型提升。 向上转型。
		a.eat();
		Dog d = (Dog)a;//强制将父类的引用。转成子类类型。向下转型。
		d.sleep();
		
	}

}

多态在子父类中的成员上的体现的特点:

   无论编译和运行,成员变量参考的都是引用变量所属的类中的成员变量。

   成员函数,编译看引用型变量所属的类,运行看对象所属的类。

   调用静态的方法引用是哪个类的引用调用的就是哪个类中的静态方法。

package pract;

class Father{
	
	 static int num = 10;
	 int a = 11;
	 public  void show(){
		 
		 System.out.println("这是父类的方法num="+num + ",a="+a);
	 }
	 public static void method(){
		 System.out.println("这是父类静态方法");
	 }
}
public class Son extends Father {
	static int num = 20;
	int a = 22;
	public  void show(){
		System.out.println("这是子类的方法num="+num+",a="+a);
	}
	public static void method(){
		 System.out.println("这是父类静态方法");
	 }
	
	public static void main(String[] args) {
		// 父类引用指向子类子类对象
		Father f = new Son();
		System.out.println(f.num);	//10
		f.show();//这是子类的方法num=20,a=2
		f.method();	//这是父类静态方法
				
		Son s = new Son();
		System.out.println(s.num);	//20
		s.show();//这是子类的方法num=20,a=22
		s.method();	//这是父类静态方法
			
	}	

}

内部类:如果A类需要直接访问B类中的成员,而B类又需要建立A类的对象。这时,为了方便设计和访问,直接将A类定义在B类中。就可以了。A类就称为内部类。内部类可以直接访问外部类中的成员。而外部类想要访问内部类,必须要建立内部类的对象。


为什么内部类可以直接访问外部类中的原因:

那是因为内部中都持有一个外部类的引用。这个是引用是 外部类名.this  

内部类可以定义在外部类中的成员位置上,也可以定义在外部类中的局部位置上。当内部类被定义在局部位置上,只能访问局部中被final修饰的局部变量。


当内部类定义在外部类中的成员位置上,可以使用一些成员修饰符修饰 privatestatic

直接访问内部类格式:外部类名.内部类名 变量名外部类对象.内部类对象;

Outer.Inner in = new Outer.new Inner();

package pract;

public class Outer{
	int num = 4;	
	class  Inner {
		void show(){
			System.out.println("inner show run "+num);			
		}
	}
	public void method(){
		Inner in = new Inner();//创建内部类的对象。
		in.show();//调用内部类的方法。 
	}
	public static void main(String[] args) {
		Outer o = new Outer();
		o.method();//inner show run 4
	}
}


匿名内部类

匿名内部类的格式: new 父类或者接口(构造函数){定义子类的内容}.方法

匿名内部类中定义的方法最好不要超过3个。

package pract;

class InnerTest{
	/**
	 * 1
		new Object(){
			void show(){
				System.out.println("show run");				
			}
		}.show();
		
		2
		Object obj = new Object(){
			void show(){
				System.out.println("show run");
			}
		};
		obj.show();
		1和2的写法正确吗?有区别吗?说出原因。
	 * */
	public static void main(String[] args){
		new Object(){
			void show(){
				System.out.println("show run");				
			}
		}.show();
		
		/*
		 * 写法是正确,1和2都是在通过匿名内部类建立一个Object类的子类对象。
		区别:
		第一个可是编译通过,并运行。
		第二个编译失败,因为匿名内部类是一个子类对象,当用Object的obj引用指向时,
		就被提升为了Object类型,而编译时检查Object类中是否有show方法,所以编译失败。
		 **/
	}
}

异常:就是不正常。程序在运行时出现的不正常情况。是对问题的描述。将问题进行对象的封装。


异常体系:

   Throwable

       |--Error

       |--Exception

           |--RuntimeException


异常体系的特点:异常体系中的所有类以及建立的对象都具备可抛性。

               也就是说可以被throwthrows关键字所操作。

               只有异常体系具备这个特点。

--------------

throwthrows的用法:

throw定义在函数内,用于抛出异常对象。

throws定义在函数上,用于抛出异常类,可以抛出多个用逗号隔开。


当函数内容有throw抛出异常对象,并未进行try处理。必须要在函数上声明,都在编译失败。

注意,RuntimeException除外。也就说,函数内如果抛出的RuntimeExcpetion异常,函数上可以不用声明。


--------------

如果函数声明了异常,调用者需要进行处理。处理方法可以throws可以try

异常有两种:

   编译时被检测异常error

       该异常在编译时,如果没有处理(没有抛也没有try),编译失败。

       该异常被标识,代表这可以被处理。

   运行时异常(编译时不检测)exception

       在编译时,不需要处理,编译器不检查。

       该异常的发生,建议不处理,让程序停止。需要对代码进行修正


异常处理语句:

try{

   需要被检测的代码

}

catch (){

   处理异常的代码;

}

finally{

   一定会执行的代码;

}


注意:

1finally中定义的通常是 关闭资源代码。因为资源必须释放。

2finally只有一种情况不会执行。当执行到System.exit(0);fianlly不会执行。

package pract;

/**
有一个圆形和长方形。
都可以获取面积。对于面积如果出现非法的数值,视为是获取面积出现问题。
问题通过异常来表示。
现有对这个程序进行基本设计。

*/

//自定义一个异常NoValueException,后面详细介绍。
class NoValueException extends RuntimeException	
{
	NoValueException(String message)
	{
		super(message);
	}
}

interface Shape//创建了一个求面积的接口
{
	void getArea();//求面积方法
}

class Rec implements Shape//接口用实现不用多说了吧!继承用extends
{
	private int len,wid;

	Rec(int len ,int wid)//能抛出 NoValueException所以需要try处理。
	{
		if(len<=0 || wid<=0)
			throw new NoValueException("出现非法值");

		this.len = len;
		this.wid = wid;
	}

	public void getArea()//覆盖的面积方法
	{
		System.out.println(len*wid);
	}
}


class Circle implements Shape
{
	private int radius;
	public static final double PI = 3.14;

	Circle(int radius)//假如传递的数字不正确,就会抛出NoValueException异常
	{
		if(radius<=0)
			throw new NoValueException("输入格式不正确");
		this.radius = radius;
	}

	public void getArea()
	{
		System.out.println(radius*radius*PI);
	}
}



public class ExceptionTest1 {
	public static void main(String[] args) {
		//处理异常方式try-catch-finally
		try {
			Rec r = new Rec(3,4);
			r.getArea();
			
		} catch (NoValueException e) {
			// 对异常进行处理
			throw new RuntimeException("请重新输入");
		}
		finally{
			System.out.println("over");
		}
		
		try {
			Circle c = new Circle(-8);
			c.getArea();
		} catch (NoValueException e) {
			// 异常自己不能解决,重新抛出一个异常
			throw new RuntimeException("圆半径输入错误,请重新输入");
		}
		finally{
			//做关闭资源动作,此题是输出over
			System.out.println("over");
		}
		
	}

}

//运行结果如下
12
over
over
Exception in thread "main" java.lang.RuntimeException: 圆半径输入错误,请重新输入
	at pract.ExceptionTest1.main(ExceptionTest1.java:85)
//通过对结果进行分析我们还可以发现try-catch- finally中,先运行try在运行finally,如果发生异常,最后运行catch

--------------

自定义异常:

  定义类继承Exception或者RuntimeException

  1,为了让该自定义类具备可抛性。

  2,让该类具备操作异常的共性方法。

  当要定义自定义异常的信息时,可以使用父类已经定义好的功能。

  异常异常信息传递给父类的构造函数。

  classMyException extends Exception

  {

     MyException(String message)

     {

        super(message);

     }

  }

自定义异常:按照java的面向对象思想,将程序中出现的特有问题进行封装。

--------------

异常的好处:

  1,将问题进行封装。

  2,将正常流程代码和问题处理代码相分离,方便于阅读。

异常的处理原则:

  1,处理方式有两种:try或者 throws

  2,调用到抛出异常的功能时,抛出几个,就处理几个。

     一个try对应多个catch

  3,多个catch,父类的catch放到最下面。

  4catch内,需要定义针对性的处理方式。不要简单的定义printStackTrace,输出语句。

     也不要不写。

     当捕获到的异常,本功能处理不了时,可以继续在catch中抛出。

     try

     {

        thrownew MyException ();

     }

     catch (MyException e)

     {

        throwe;

     }

     如果该异常处理不了,但并不属于该功能出现的异常。

     可以将异常转换后,在抛出和该功能相关的异常。

     或者异常可以处理,当需要将异常产生的和本功能相关的问题提供出去,

     当调用者知道。并处理。也可以将捕获异常处理后,转换新的异常。

     try

    {

        thrownew MyException ();

     }

     catch (MyException e)

     {

        // MyException处理。

        thrownew BException();

     }


异常的注意事项:

  在子父类覆盖时:

  1,子类抛出的异常必须是父类的异常的子类或者子集。

  2,如果父类或者接口没有异常抛出时,子类覆盖出现异常,只能try不能抛。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值