接口、多态、异常

---------------------- android培训 java培训 、期待与您交流! ----------------------  
英语角:
interface 接口
implements 实现
ArithmeticException 算术异常
java.lang java语言。lang:语言(language)的缩写。

一、接口
1、格式: interface {  }
接口中的成员修饰符是固定的。接口中的成员都是public的。
成员常量:public static final
成员函数:public abstract
interface Inter
{
	public static final int NUM = 3;
	public abstract void show();
}
//只要定义的是接口,常量和方法的修饰符就是固定的。即使漏写了修饰符也没有关系。会自动添加。但是阅读性不好



   2、多实现
接口可以被类多实现,也是对多继承不支持的转换形式。java支持多实现。

class A
{
	void show()
	{
		System.out.println("a");
	}
}
class B
{
	void show()
	{
		System.out.println("b");
	}
}
class C extends A,B{}
/*
此时如果主函数中建立了一个C类对象,并调用show()方法
	C c = new C();
	c.show();
	那么,由于c继承了A,B,两个父类中都有show方法,这时子类不知道继承哪一个。所以出现安全隐患。
Java语言中:java只支持单继承,不支持多继承。但是java保留这种机制。并用另一种体现形式来完成表示。叫多实现。
	所谓的多实现相当于是扩展子类的功能。这样即使实现的多个接口中出现相同的方法也没有关系,因为抽象方法并没有方法体。子类对接口中的方法进行复写,想要什么功能就怎么复写,而且不会出现安全隐患。请看下面的程序。
*/
interface InterA
{
	public static final int NUM = 3;
	public abstract void show();
}

interface InterB
{
	public abstract void show();
}

class Demo
{
	public void function(){}
}

class Test extends Demo implements InterA,InterB
{
	public void show()
	{
		System.out.println("haha");
	}
}
//单继承确保证了程序的安全性。并用多实现扩展了子类的功能,是程序变得简洁,更具有复用性,是Java的一个优势!


3、接口的特点:
  • 接口是对外暴露的规则。
  • 接口是程序的功能扩展。 
  • 接口的出现降低耦合性。 
  • 接口可以用来多实现。 
  • 类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口。 
  • 接口与接口之间可以有继承关系。
 4、接口和抽象类的异同:
共  性: 都是不断抽取出来的抽象的概念
区别 1: 抽象类体现继承关系,一个类只能单继承
接口体现实现关系,一个类可以多实现
区别 2: 抽象类是继承,是 "is a "关系
接口是实现,是 "like a"关系
区别 3: 抽象类中可以定义非抽象方法,供子类直接使用  
接口的方法都是抽象,接口中的成员都有固定修饰符

 5、内部类
内部类的访问规则:

   
   
  • 内部类可以直接访问外部类中的成员,包括私有。之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this
  • 外部类要访问内部类,必须建立内部类对象。
访问格式: 1,当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中。 可以直接建立内部类对象。格式: 外部类名.内部类名 变量名 = 外部类对象.内部类对象; Outer.Inner in = new Outer().new Inner(); 2,当内部类在成员位置上,就可以被成员修饰符所修饰。比如:
   
   
  • private:将内部类在外部类中进行封装。
  • static:内部类就具备static的特性。当内部类被static修饰后只能直接访问外部类中的static成员。出现访问局限。
在外部其他类中,如何直接访问static内部类的非静态成员呢?
	new Outer.Inner().function();
在外部其他类中,如何直接访问static内部类的静态成员呢?
	Outer.Inner.function();
注意:当内部类定义了静态成员,该内部类必须是static的。当外部类中的静态方法访问内部类时内部类必须是static的。       当描述事物时,事物的内部还有事物,该事物用内部类来描述。因为内部事务在使用外部事物的内容。
内部类定义在局部时,

   
   
  • 不可以被成员修饰符修饰
  • 可以直接访问外部类中的成员,因为还持有外部类中的引用。但不可以访问它所在的局部中的变量。只能访问final修饰的局部变量。
匿名内部类:

     
     
  • 匿名内部类其实就是内部类的简写格式。
  • 定义匿名内部类的前提:内部类必须是继承一个类或者实现接口。
  • 匿名内部类的格式:new 父类或者接口(){定义子类的内容}
  • 其实匿名内部类就是一个匿名子类对象。而且这个对象有点胖。可以理解为带内容的对象。
  • 匿名内部类中定义的方法最好不要超过3个。
当要多次调用匿名内部类的方法时,可以给匿名内部类起个名字方便调用。应用多态,父类引用指向子类

abstract class AbsDemo
	{
		abstract void show();	
	}
public void function()
	{
AbsDemo d = new AbsDemo()
		{
			int num = 9;
			void show()
			{
				System.out.println("num="+num);
			}
			void abc()
			{
				System.out.println("haha");
			}
		};
		d.show();
		//d.abc();用父类引用建立的子类对象只能使用父类的方法,而不能使用子类特有的方法。
	}
 
注意:使用匿名内部类就是为了简化书写,覆盖方法,所以没有必要在匿名内部类中定义新的方法。
二、多态
1、多态概述
多态是指某一类事物的多种存在形态。 例:动物中猫,狗。
 猫这个对象对应的类型是猫类型 
猫 x = new 猫(); 
同时猫也是动物中的一种,也可以把猫称为动物。 
动物 y = new 猫(); 
动物是猫和狗具体事物中抽取出来的父类型。 父类型引用指向了子类对象。
  • 多态程序中体现:父类或者接口的引用指向或者接收自己的子类对象。
  • 多态好处和作用:多态的存在提高了程序的扩展性和后期可维护性
  • 多态的前提:1)需要存在继承或者实现关系。2)要有覆盖操作
  • 多态的弊端: 提高了扩展性,但是只能使用父类的引用访问父类中的成员

abstract class Student { public abstract void study(); abstract void sleep(); } class DoStudent { void func(Student s)//建立父类的引用,后期在产生新的子类都可以对其进行操作。 { s.study(); s.sleep(); } } /* 以上两块相当于把程序写完了,下面部分只是后期加进去的内容。 所以其实以后自己开发时,也要将这种思想贯彻到程序中。 多态将对象调用这件事简化了,从指挥每个人去做事转变为指挥所有人做自己的事。 思想:先抽象出相似事物的共同部分建立父类或者接口,再对具体的事情扩展详细内容,有利于程序的扩展性。 */ //------------------------------------------------------------------------------------------------- class BaseStudent extends Student { public void study() { System.out.println("Base Study!"); } public void sleep() { System.out.println("躺着睡。。。"); } } class AdvStudent extends Student { public void study() { System.out.println("Adva Study!"); } public void sleep() { System.out.println("坐着睡。。。"); } } class DuotaiDemo { public static void main(String[] args) { DoStudent ds=new DoStudent(); ds.func(new BaseStudent()); ds.func(new AdvStudent()); } }

2、在多态中成员函数的特点:

  • 在编译时期:参阅引用型变量所属的类中是否有调用的方法。如果有,编译通过,如果没有编译失败。
  • 在运行时期:参阅对象所属的类中是否有调用的方法。
  • 简单总结 就是:成员函数在多态调用时,编译看左边,运行看右边。如下面程序

class Fu { int num = 5; void method1() { System.out.println("fu method_1"); } void method2() { System.out.println("fu method_2"); } static void method4() { System.out.println("fu method_4"); } } class Zi extends Fu { int num = 8; void method1() { System.out.println("zi method_1"); } void method3() { System.out.println("zi method_3"); } static void method4() { System.out.println("zi method_4"); } }

//如果main函数如下:

class Interface { public static void main(String[] args) { Fu f = new Zi(); f.method1(); f.method2(); f.method3(); } }

//则编译会报错:找不到Method3()。因为父类中并没有method(3);
// 所以说在编译时期,参阅引用型变量(此例中为变量f)所属的类(f所属类是父类)中是否有调用的方法。如果有,编译
//通过,如果没有编译失败。

上例中如果main函数中程序如下:

class Interface { public static void main(String[] args) { Fu f = new Zi(); System.out.println(f.num); Zi z = new Zi(); System.out.println(z.num); } }

/*

输出结果为:5

                        8

如果在程序中把Zi和Fu类中的变量前面加上关键字static,输出结果相同。所以在多态中,成员变量的特点:无论编译和运行,都参考左边(引用型变量所属的类)。在多态中,静态成员函数的特点:无论编译和运行,都参考做左边。

*/

三、异常

1、异常:就是程序运行时出现的不正常情况

2、异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述。并封装成对象。其实就是java对不正常情况进行描述后的对象体现。

3、对于问题的划分有两种:一种是严重的问题,一种非严重的问题。    

对于严重的,java通过Error类进行描述。对于Error一般不编写针对性的代码对其进行处理。   

对与非严重的,java通过Exception类进行描述。

对于Exception可以使用针对性的处理方式进行处理。无论Error或者Exception都具有一些共性内容。比如:不正常情况的信息,引发原因等。

Throwable两个子类   

              1--Error    

              2--Exception

4,异常的处理java 提供了特有的语句进行处理,包括三部分。

       try{ 需要被检测的代码}

      catch(异常类 变量){处理异常的代码;(处理方式) }

      finally{一定会执行的语句;}

5,对捕获到的异常对象进行常见方法操作。   

        getMessage():获取异常信息。/ by zero

         toString():异常名称,异常信息。java.lang.ArithmeticException: / by zero

        printStackTrace();//异常名称,异常信息,异常出现的位置。

       其实jvm默认的异常处理机制,就是在调用printStackTrace方法。打印异常的堆栈的跟踪信息。

         java.lang.ArithmeticException: / by zero

        at Demo.div(ExceptionDemo.java:7)

        at ExceptionDemo.main(ExceptionDemo.java:19)

 6、处理异常的方法:

class Demo
{
	int div(int a,int b)throws Exception//由于编程者知道程序在运行时会存在问题,
	//便在功能上通过throws的关键字声明了该功能有可能会出现问题,这一步叫做“抛出”。
	//抛出以后如果没有后续操作编译不能通过,一定要进行处理(捕捉或抛出)才能使用,以提高安全性。	
	{									
		return a/b;
	}
}
class  ExceptionDemo1
{
	public static void main(String[] args) //throws Exception  第一种解决办法,抛出将问题抛给JVM
	{
		Demo d = new Demo();
		try     //第二种方法 用try catch捕捉。
		{
			int x = d.div(4,0);
			System.out.println("x="+x);
		}
		catch (Exception e)
		{
			System.out.println(e.toString());
		}
		System.out.println("over");
	}
}

 7、对多异常的处理。

声明异常时,建议声明更为具体的异常。这样处理的可以更具体。

对方声明几个异常,就对应有几个catch块。不要定义多余的catch块。

如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面。(如下)  

catch (ArithmeticException e)//子类一
		{
			System.out.println(e.toString());
			System.out.println("被零除啦!!!");
		}
		catch (ArrayIndexOutOfBoundsException e)//子类二
		{
			System.out.println(e.toString());
			System.out.println("角标越界啦!!");
		}
		catch(Exception e)//父类
		{
			System.out.println("有异常:"+e.toString());
		}

throws和throw的区别:

      throws使用在函数上。throw使用在函数内。

      throws后面跟的异常类。可以跟多个。用逗号隔开。throw后跟的是异常对象。

自定义异常的特点:

class FuShuException extends Exception //之所以继承Exception是因为异常类和异常对象都能被抛出。
				      //他们都具备可抛性。这个可抛性是Throwable这个体系中独有特点。
{
	private int value;
	FuShuException(String msg,int value)
	{
		super(msg);
		this.value = value;
	}
	public int getValue()
	{
		return value;
	}
}
class Demo
{
	int div(int a,int b)throws FuShuException //函数内出现问题,函数上一定要给出对应的申明异常。
	{
		if(b<0)
			throw new FuShuException("出现了除数是负数的情况------ / by fushu",b);
				//此处会出现异常,如果除数小于0除法运算无法运行,
				//所以让程序停掉,手动通过throw关键字抛出一个自定义异常对象。
		return a/b;
	}
}
class  ExceptionDemo2
{
	public static void main(String[] args) 
	{
		Demo d = new Demo();
		try
		{
			int x = d.div(4,-9);
			System.out.println("x="+x);		
		}
		catch (FuShuException e)
		{
			System.out.println(e.toString());
			System.out.println("错误的负数是:"+e.getValue());
		}
		System.out.println("over");
	}
}


8、自定义异常:

因为项目中会出现特有的问题,而这些问题并未被java所描述并封装对象。所以对于这些特有的问题可以按照java的对问题封装的思想,将特有的问题进行自定义的异常封装。当在程序中出现视为是错误的是无法进行运算的内容时就需要对这个问题进行自定义的描述。当在函数内部出现了throw抛出异常对象,那么就必须要给对应的处理动作。

要么在内部try catch处理。要么在函数上声明让调用者处理。一般情况在,函数内出现异常,函数上需要声明。

如何定义异常信息呢?

因为父类中已经把异常信息的操作都完成了。所以子类只要在构造时,将异常信息通过super语句传递给父类。那么就可以直接通过getMessage方法获取自定义的异常信息。

自定义异常:必须是自定义类继承Exception。

       异常体系有一个特点:因为异常类和异常对象都被抛出。他们都具备可抛性。这个可抛性是Throwable这个体系中独有特点。只有这个体系中的类和对象才可以被throws和throw操作。

RuntimeException 运行时异常

对于异常分两种:

  1,编译时被检测的异常。  

  2,编译时不被检测的异常(运行时异常。RuntimeException以及其子类)

RuntimeException 运行时异常是Exceptoin中一个特殊的子类异常。

  • 如果在函数内容抛出该异常,函数上可以不用声明,编译一样通过。
  • 如果在函数上声明了该异常。调用者可以不用进行处理。编译一样通过;

自定义异常时,如果该异常的发生,无法在继续进行运算,就让自定义异常继承RuntimeException。

如果是继承RuntimeException那么异常是不需要在函数上申明的,也就是说对于程序中的throws语句可要可不要。并且也不需要提供处理(即抛或者try)。但是Throws语句如果要了的话(也即对函数声明了)那么一定要与RuntimeException对应。而不能写成Throws Exception。这样的写法可谓牛头不对马嘴。也即你抛出的是编译时异常,catch的却是运行时异常。这样是不可以的!

9、覆盖时的异常特点

异常在子父类覆盖中的体现;



1,子类在覆盖父类时,如果父类的方法抛出异常,那么子类的覆盖方法,只能抛出父类的异常或者该异常的子类。
2,如果父类方法抛出多个异常,那么子类在覆盖该方法时,只能抛出父类异常的子集。
3,如果父类或者接口的方法中没有异常抛出,那么子类在覆盖方法时,也不可以抛出异常。如果子类方法发生了异常。就必须要进行try处理。绝对不能抛。
Exception 
	|--AException
		|--BException
	|--CException
	如果父类抛出A异常,那么子类只能抛出A异常或者B异常。而不能抛出C异常。请看如下程序:

class Fu
{
	void show()throws AException
	{	
	}
}
class Test
{
	void function(Fu f)
	{
		try
		{
			f.show();
		}
		catch (AException e)//父类中处理的是A异常
		{

		}
		
	}
}
class Zi extends Fu
{
	void show()throws CException//抛出C异常
	{		
	}
}
class  
{
	public static void main(String[] args) 
	{
		Test t = new Test();
		t.function(new Zi());
	}
}

由于父类中有A异常,并且处理了A异常,当子类继承父类的show()方法时如果抛出C异常,该异常无法被处理,因为子类只有处理A异常的功能。所以编译不能通过,此时,如果子类中有新的异常只能处理而不能抛。


  
  


  
  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值