黑马程序员 面向对象(二)继承、接口、多态和异常

                  黑马程序员  面向对象(二)继承、接口、多态和异常

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

1.继承

(1)定义:抽取类与类之间的共性的内容并封装在单独的一个类中,其他类可以不用单独再定义这些内容,只要继承该类即可。

(2)特点:(a)提高代码的复用性;(b)让类与类之间产生关系,有了这个关系,才有了多态的特性

(3)注意:

(a)千万不要为了获取其他类的功能,简化代码而继承;必须是类与类之间有所属关系才可以继承。所属关系:is a。

(b)Java只支持单继承,不支持多继承。因为多继承容易带来安全隐患,当多个父类中定义了相同函数,但函数内容不同时,子类对象不确定要进行哪一个。但是java保留这种机制,并用另一种体现形式来完成表示,多实现

(4)继承格式:class A extends B

那么A就属于子类,B就属于父类。

(5)子父类出现后,类成员的特点:

变量:如果子类中出现非私有的同名成员变量时,子类要访问本类中的变量用this(本类对象的引用),子类要访问父类中的同名变量用super(父类对象的引用)。

//继承示例
class Fu
{
	int num=5;
}
class Zi extends Fu
{	//因为子类继承父类,相当于子类存在一个int num=5
	void show()
	{	
		System.out.println(super.num);
		System.out.println(this.num);
	}
}
class ExtendsDemo  
{
	public static void main(String[] args) 
	{
		Zi z=new Zi();
		z.show();
	}
}

(6)子父类中函数的特点(覆盖)

当子类继承父类,沿袭了父类的功能,到子类中,但是子类虽具备该功能,但是功能的内容却和父类不一致,这时,没有必要定义新功能,而是使用覆盖特殊,保留父类的功能定义,并重写功能内容

(7)覆盖

(a)子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编绎失败

(b)静态只能覆盖静态

(c)注意:

重载:只看同名函数的参数列表。

重写:子父类方法要一模一样。

//子类覆盖父类示例
class Fu2
{
	void show()
	{
		System.out.println("show1");
	}
}
class Zi2 extends Fu2
{	//子类覆盖父类内容并拓展自身内容
	void show()
	{	
		System.out.println("show2");
		System.out.println("show3");
	}
}
class ExtendsDemo2  
{
	public static void main(String[] args) 
	{
		Zi2 z=new Zi2();
		z.show();
	}
}

(8)子父类中的构造函数

在对子类对象进行初始化时,父类的构造函数也会运行,那是因为子类的构造函数默认第一行有一条隐式语句super();super()会访问父类中空参数的构造函数,而且子类中所有的构造函数默认第一行都是super()。

(9)为什么子类一定要访问父类中的构造函数?

因为父类中的数据,子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。

结论:

(a)子类的所有的构造函数,默认都会访问父类中空参数的构造函数,因为子类中每一个构造函数的第一行都有一句隐式语句super()

(b)当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数。当然,子类的构造函数第一行也可以手动指定this语句访问本类中的构造函数

注意:

(a)super或this语句一定定义在子类构造函数的第一行

(b)子类的一个构造函数中不可以同时存在this()和super(),但子类中至少有一个构造函数中存在super()。

(b)子父类之间的构造函数不存在覆盖,因为子类和父类名称不可能相同。

//子父类中的构造函数示例
class FuStudent
{	
	private String name;
	FuStudent()
	{
		System.out.println("study");
	}
	FuStudent(String name)
	{
		this.name=name;
		System.out.println("name="+this.name);
	}
}
class ZiStudent extends FuStudent
{	
	ZiStudent()
	{	//super();
		System.out.println("sport");	
	}
	
	ZiStudent(String name)
	{
		super(name);
	}
}
class ExtendsDemo3  
{
	public static void main(String[] args) 
	{
		ZiStudent z=new ZiStudent();
		ZiStudent z2=new ZiStudent("李四");
		
	}
}

2.final关键字

(1)final可以修饰类,方法,变量。

(2)final修饰的类不可以被继承。

(3)final修饰的方法不可以被覆盖。

(4)final修饰的变量是一个常量,只能被赋值一次,常量的书写规范所有字母都大写,如果由多个单词组成,单词间通过“_”连接。

(5)内部类只能访问final修饰的局部变量。


3.抽象类(abstract)

(1)定义:当多个类中出现相同函数,但是函数主体不同,这时可以抽取函数定义,注意,只抽取函数定义,不抽取函数主体。这个类和函数用abstract来修饰。

(2)抽象类的特点:

(a)抽象方法一定在抽象类中。

(b)抽象方法和抽象类都必须被abstract关键字修饰。

(c)抽象类不可以用new创建对象。因为调用抽象方法没意义。

(d)抽象类中的抽象方法要被使用,必须由子类复写所有的抽象方法后,建立子类对象调用,如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。

(3)抽象类和一般类的区别:

(a)抽象类比一般类多了个抽象函数的定义。

(b)抽象类不可以实例化。

(4)注意:抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。

/*抽象类练习
假如我们在开发一个系统时需要对员工进行建模,员工包含3个属性,姓名、工号、以及工资。
经理也是员工,除了含有员工属性外,还有一个奖金属性,请使用继承的思想设计出员工和经理
类。要求类中提供必要的方法进行属性访问*/
//设置抽象类,类中有抽象方法
abstract class Employee
{
	//设置员工属性
	private String name;
	private String id;
	private double pay;
	Employee(String name,String id,double pay)
	{
		this.name=name;
		this.id=id;
		this.pay=pay;
		System.out.println("姓名:"+this.name+";工号:"+this.id+";工资:"+this.pay);
	}
	public abstract void work();//抽象方法
}
class Manager extends Employee
{
	private int bonus;
	//经理也有员工的基本属性
	Manager(String name,String id,double pay)
	{
		super(name,id,pay);//调用父类的方法
		
	}
	//
	public void bonus(int bonus)
	{
		this.bonus=bonus;
		System.out.println("奖金:"+this.bonus);
	}
	public void work()//覆写抽象方法
	{
		System.out.println("工作内容是:Manager work");
	}
}
class Pro extends Employee
{
	Pro(String name,String id,double pay)
	{
		super(name,id,pay);
	}
	public void work()//覆写抽象方法
	{
		System.out.println("工作内容是:Pro work");
	}
}
class  AbstractDemo
{
	public static void main(String[] args) 
	{
		Manager m=new Manager("李四","A2015001",5000);
		m.bonus(1000);
		m.work();
		Pro p=new Pro("张三","b2015002",3000);
		p.work();
		Pro p1=new Pro("杨五","b2015003",3000);
		p1.work();
	}
}

4.接口(interface)

(1)概述:接口是抽象类的延伸,可以将它看作是纯粹的抽象类,接口中的所有方法都没有方法体。

(2)接口使用interface来表示,子类中用implements实现。格式为: interface 接口名{}。子类名 implements接口名{}

(3)接口中的成员修饰符是固定的。

成员常量:public static final

成员函数:public abstract

(提示:在编写程序时这些修饰符可以省略,因为编译时java会自动添加,但是为了程序的阅读性,建议写上。

记住:接口中的成员都是public的)

(4)接口的出现将“多继承”通过另一种形式体现出来,即“多实现”。

(5)接口是不可以创建对象的,因为有抽象方法。需要被子类实现,子类对接口中的抽象方法全部覆盖后,子类才可以实例化。否则子类是一个抽象类。

(6)接口与接口之间存在多继承。

(7)继承:子类和父类的关系是is a;

     接口:子类和父类的关系是like a;

(8)特点:

(a)接口是对外暴露的规则。

(b)接口是程序的功能扩展。

(c)接口可以用来多实现。

(d)类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口

(e)接口与接口之间是继承关系,而且可以存在多继承。而因为接口的函数都是抽象的。


5.多态

(1)定义:某一类事物的多种存在形态。

例:动物中猫,狗。

猫这个对象对应的类型是猫类:猫 x=new 猫();

同时猫也是动物中的一种,也可以把猫称为动物

动物 y=new 猫();

(2)多态的体现:父类的引用也可以接收自己的子类对象。

(3)多态的前提:必须是类与类之间有关系,要么继承,要么实现。通常还有一个前提,存在覆盖。

(4)多态的好处:多态的出现大大的提高程序的扩展性。

(5)多态的转型:

Animal a=new Cat();//类型提升,向上转型。

Cat c=(Cat)a;//强制将父类的引用,转成子类类型,向下转型。

注意:千万不要将父类对象转成子类类型。

如:Animal a=new Animal();Cat c=(Cat)a;这是错误的!

我们能转换的是父类引用指向了自己的子类对象,该引用可以被提升,也可以被强制向下转换。

(6)判断某一类型引用指向的对象属于什么类型的时候,用instanceof。

如:if(a instanceof Cat) //a指向的对象是否Cat类型的

(7)多态中成员函数的特点:成员函数在多态调用时,编译看工边,运行看右边。

(8)多态中,成员变量的特点:无论编译和运行,都参考左边(引用型变量所属的类)

(9)在多态中,静态成员函数的特点:

无论编译还是运行,都参考左边。


6.object:是所有对象的直接或者间接父类。该类中定义的内容是所有对象都具备的功能。


7.内部类

(1)定义:将一个类定义在另一个类的里面,对里面那个类就称为内部类(内置类,嵌套类)

(2)访问特点

(a)内部类可以直接访问外部类中的成员,包括私有成员。之所以可以直接访问外部类中的成员,是因为内部类中持有了一个外部类的引用,格式:外部类名.this

(b)而外部类要访问内部类中的成员必须要建立内部类的对象

//内部类示例
class Outer     //外部类
{
	private int num=5;
	class Inner    //内部类
	{
		void running()
		{
			System.out.println("num="+Outer.this.num);
		}
	}
	void method()
	{
		Inner i=new Inner();   //创建内部类对象
		i.running();
	}
}
class InnerDemo 
{
	public static void main(String[] args) 
	{
		Outer o=new Outer();     //创建外部类对象
		o.method();
	}
}

(3)访问格式:

(a)当内部类定义在外部类的成员位置上,而且非私有,可以在外部其他类中。可以直接建立内部类对象。

格式:外部类名.内部类名 变量名=外部类对象.内部类对象;

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

(b)当内部类在成员位置上,就可以被成员修饰符所修饰。

比如,private:将内部类在外部类中进行封装。

      static:内部类就具备static的特性。

当内部类被static修饰后,只能直接访问外部类中的static成员。出现了访问局限。

在外部其他类中,如何直接访问static内部类的非静态成员呢?

new Outer.Inner.function();

在外部其他类中,如何直接访问static内部类的静态成员呢?

Outer.Inner.function();

注意:当内部类中定义了静态成员,该内部类必须是static的。

(4)内部类定义规则:当描述事物时,事物的内部还有事物,该事物用内部类来描述。因为内部事物在使用外部事物的内容。

(5)内部类定义在局部时:

(a)不可以被成员修饰符修饰。

(b)可以直接访问外部类中的成员,因为还持有外部类中的引用。但是不可以访问它所在的局部中的变量,只能访问被final修饰的局部变量。

(6)匿名内部类

(a)匿名内部类其实就是内部类的简写格式。

(b)定义匿名内部类的前提:内部类必须是继承一个类或者实现接口

(c)匿名内部类的格式:new父类或者接口(){定义子类的内容}

(d)其实匿名内部类就是一个匿名子类对象。而且这个对象可以理解为带内容的对象。

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

//匿名内部类示例
interface Inter
{
	void show();
}
class Outer
{
	static Inter method()
	{    //建立匿名内部类对象
		return new Inter()
		{
			public void show()
			{
				System.out.println("show time");
			}
		};
	}
}
class InterDemo
{
	public static void main(String[] args) 
	{
		Outer.method().show();
	}
}

8.异常

(1)异常的体系

(a)Throwable

     Error:通常出现重大问题如:运行的类不存在或者内存溢出等。

           不编写针对代码对其处理

Exception:在运行时运行出现的一般情况,可以通过                        try,catch,finaly。

Exception和Error的子类名都是以父类名作为后缀。

(2)异常的定义:就是程序在运行时出现不正常情况。

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

(4)异常的处理

java提供了特有的语句进行处理。

try{需要被检测的代码;}

catch(异常类 变量)

{

处理异常的代码;(处理方式)

}

finally{一定会执行的语句}

(5)System.out.println(e.getMessage());// by zero(只说明异常信息)

System.out.println(e.toBtring());//会说明异常名称和异常信息

e.printStackTrace();//会说明异常名称,异常信息和异常出现位置。其实jvm默认的异常处理机制,就是在调用printStackTrace(打印异常的堆栈的跟踪信息)方法。(注意:printStackTrace是没有返回值的,所以不用打印语句,直接调用即可)

(6)在函数上声明异常,便于提高安全性,让调用进行处理。不处理编译失败。

//异常示例
class Demo
{
	int div(int a,int b)throws Exception//异常声明,进行抛出。
	{
		return a/b;
	}
}
class ExceptionDemo 
{    //主函数没有再抛出,而是对异常进行处理
	public static void main(String[] args) 
	{
		Demo d=new Demo();
		//检测
		try
		{
			int x=d.div(4,0);
			System.out.println("x="+x);
		}
		//处理
		catch (Exception e)
		{
			System.out.println(e.toString());
		}
		
		System.out.println("over");

	}
}

(7)多异常处理

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

(b)函数声明几个异常,就对应有几个catch块。如果多个catch块中的异常出现继承关系,父类异常catch块放在最下面。

(8)catch具体处理方式:不要简单定义一句e.printStackTrace(),也不要简单的书写一条输出语句(练习只为了方便理解)。

(9)如何定义异常信息?

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

(10)自定义异常:必须是自定义继承Exception。

(11)继承Exception原因:异常体系有一个特点:因为异常类和异常对象都被抛出。他们都具备可抛性,这个可抛性是Throwable这个体系中独有特点。

(12)只有这个体系中的类和对象才可以被throw和throws操作

(13)throws和throw的区别:

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

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

throw后面跟的是异常对象。

(14)Exception中有一个特殊的子类异常RuntimeException运行时异常。如果在函数内容抛出该异常,函数上可以不用声明;如果在函数上声明了该异常,调用者可以不用进行处理。之所以不用在函数声明,是因为不需要让调用者处理。当该异常发生,希望程序停止,因为在运行时,出现了无法继续运算的情况,希望停止程序,对代码进行修正。

(15)自定义异常时:如果该异常的发生,程序无法再继续进行运算,就让自定义异常继承RuntimeException。

(16)对于异常分两种:

(a)编译时被检测的异常。

(b)编译时不被检测的异常(RuntimeException以用其子类)


9.包(package)

(1)对类文件进行分类管理

(2)给类提供多层命名空间

(3)写在程序文件的第一行

(4)类名的全称是:包名.类名

(5)包也是一种封装形式

(6)在程序开头先定义包名:package pack。编绎时可以自动生成文件夹来存放类文件,格式为:javac -d 文件夹路径 类名.java。

总结:

包与包之间进行访问,被访问的包中的类以及类中的成员,需要public修饰。

不同包中的子类还可以直接访问父类中被protected权限修饰的成员。

            public     protected    default       private

同一个类中    ok         ok           ok            ok

同一个包中   ok          ok           ok

子类          ok          ok

不同包中      ok



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值