JAVA学习笔记-chap4-继承

第四章 继承

4.1 继承的概述

  • 继承的好处:
    1,提高了代码的复用性
    2,让类与类之间产生了关系,给第三个特征多态提供了前提。
  • 格式:
class 父类{}
class 子类 extends 父类{}

4.2继承的特点

  • 继承关系图
    继承关系

  • 继承类型

  • 需要注意:Java不支持多继承,但支持多重继承
    继承类型

  • 什么时候使用继承

  • 继承需要符合的关系是:is-a,父类更通用,子类更具体。当类与类之间存在着所属关系的时候,就定义继承。例:xxx是yyy中的一种。xxx extends yyy

4.3 super关键字

  • 本类的成员和局部变量同名this区分。
  • 子父类中的成员变量同名super区分父类
  • this和super的用法很相似。区别如下:
  • this:代表一个本类对象的引用
  • super:代表一个父类空间
  • 内存图解
    super内存图解

4.4 函数覆盖

  • 内存图解
    函数覆盖内存图解
  • 成员函数
  • 子父类中出现成员函数一模一样的情况,会运行子类的函数。
    这种现象,称为覆盖操作。这是函数子父类中的特性。
  • 一模一样: 返回值类型相同
    函数名一样
    参数列表一样
  • 函数的两个特性:
    1,重载(overload)。同一个类中。
    2,覆盖(override)。子类中。覆盖也称为重写,覆写。
  • 覆盖注意事项:
    1,子类方法覆盖父类方法时,子类权限必须要大于等于父类权限
    2,静态只能覆盖静态,或被静态覆盖
  • 什么时候使用覆盖操作
    当对一个类进行子类的扩展时,子类需要保留父类的功能声明,但是要定义子类中该功能的特有内容时,就使用覆盖操作完成。
  • 例:给电话增加来电显示姓名和照片功能:
class Phone
{
	void call()
	{}
	void show()
	{
		System.out.println("number");
	}
}
class NewPhone extends Phone
{
	void show()
	{
		System.out.println("name");
		System.out.println("pic");
		super.show();
	}
}
class ExtendsDemo3 
{
		public static void main(String[] args)
		{
					NewPhone p = new NewPhone();
					p.show();
		}
}

4.5 子类的实例化过程

  • 子父类中的构造函数的特点。
    在子类构造对象时,发现,访问子类构造函数时,父类也运行了。
  • 上述现象的原因是:在子类的构造函数中第一行有一个默认的隐式语句。super();
  • 子类的实例化过程:子类中所有的构造函数默认都会访问父类中的空参数的构造函数
  • 为什么子类实例化的时候要访问父类中的构造函数呢?
    因为子类继承了父类,获取到了父类中的内容(属性),所以在使用父类内容之前,
    要先看父类是如何对自己的内容进行初始化的。
    所以子类在构造对象时,必须访问父类中的构造函数。
    为了完成这个必须的动作,就在子类的构造函数中加入了super();语句。
  • 如果父类中没有定义空参数构造函数,那么子类的构造函数必须用super明确要调用
    父类中哪个构造函数。同时子类构造函数中如果使用this调用了本类构造函数时,
    那么super就没有了,因为super和this都只能定义在第一行。所以只能有一个。
    但是可以保证的是,子类中肯定会有其他的构造函数访问父类的构造函数
  • 注意:super语句必须要定义在子类构造函数的第一行。因为父类的初始化动作要先完成
  • 子类的实例化:
class Fu
{
	Fu()
	{
		super();
		show();
		return;
	}
	void show()
	{
		System.out.println("fu show");
	}
}
class Zi extends Fu
{
	int num = 8;
	Zi()
	{
		super();
		//-->通过super初始化父类内容时,子类的成员变量并未显示初始化。等//super()父类初始化完毕后,才进行子类的成员变量显示初始化。
		System.out.println("zi cons run");
		return;
	}
	void show()
	{
		System.out.println("zi show..."+num);
	}
}
class ExtendsDemo5 
{
	public static void main(String[] args) 
	{
		Zi z = new Zi();
		z.show();
	}
}
  • 内存图解
    子类实例化内存图解

4.6 final关键字

  • final可以修饰类,方法,变量
  • final修饰的类不可以被继承。即最终类。
  • final修饰的方法不可以被覆盖。可以让类中被final修饰的方法无法被覆盖。
  • final修饰的变量是一个常量。只能被赋值一次。
  • 内部类只能访问被final修饰的局部变量。
  • 为什么要用final修饰变量?
    其实在程序中如果一个数据是固定的,那么直接使用这个数据就可以了,但是这样阅读性差,所以给该数据起个名称。而且这个变量名称的值不能变化,所以加上final固定。实际开发中,代码一旦涉及到固定不变的值,一定要final化,这叫做专业性。
  • 写法规范
  • java中变量定义格式xxYyy,首字母小写,之后每个单词首字母大写,与函数名命名规范一样,只是函数带()。
  • java中常量定义格式XXX_XXX,所有字母大写,中间用下划线_连接。
  • public static 修饰的称为全局变量
  • public static final修饰的称为全局常量

4.7 抽象类

  • 抽象类的特点
  • 方法只有声明没有实现时,该方法就是抽象方法,需要被abstract修饰。
  • 抽象方法必须定义在抽象类中。该类必须也被abstract修饰
  • 抽象类不可以被实例化。因为调用抽象方法没意义。
  • 抽象类必须有其子类覆盖了所有的抽象方法后,该子类才可以实例化。否则,这个子类还是抽象类。
  • 抽象类细节
  • 抽象类中有构造函数吗?
    有,用于给子类对象进行初始化。
  • 抽象类可以不定义抽象方法吗?
    可以。但是很少见,目的就是不让该类创建对象。AWT的适配器对象就是这种类。
    通常这个类中的方法有方法体,但是却没有内容
    例:
abstract class Demo
{
	void show1()
	{}

	void show2()
	{}
}
  • 抽象关键字不可以和哪些关键字共存?
    private 不行。抽象方法必须被子类覆盖,但是私有后子类无法获取方法,因此无法完成对方法的覆盖
    static 不行。如果成员是静态,就不需要创建对象,直接用类名可以调用方法,抽象方法运行无意义,因为抽象方法无方法体。
    final 不行。矛盾。
  • 抽象类和一般类的区别。
    相同点:抽象类和一般类都是用来描述事物的,都在内部定义了成员。
    不同点:1,一般类有足够的信息描述事物。
    抽象类描述事物的信息有可能不足。
    2,一般类中不能定义抽象方法,只能定义非抽象方法。
    抽象类中可定义抽象方法,同时也可以定义非抽象方法。
    3,一般类可以被实例化。
    抽象类不可以被实例化。
  • 抽象类一定是个父类吗?
    是的。因为需要子类覆盖其方法后才可以对子类实例化。

4.8接口

  • 当一个抽象类中的方法都是抽象的时候,这时可以将该抽象类用另一种形式来定义和表示,就是 接口 interface。
  • 定义接口使用的关键字不是class,是interface。编译后仍为.class文件。
  • 格式
interface { }
  • 接口中的成员修饰符是固定的。(可省略,编译器会自动加上,但阅读性较差)
  • 成员常量:public static final
  • 成员函数:public abstract
  • 发现接口中的成员都是public的(权限最大)
  • 类与类之间是继承关系,类与接口之间是实现关系。接口的出现将"多继承"通过另一种形式体现出来,即“多实现”。一个类可以实现多个接口。
  • 接口不可以实例化。只能由实现了接口的子类并覆盖了接口中所有的抽象方法后,该子类才可以实例化。否则,这个子类就是一个抽象类。
  • 因为接口中的方法为抽象方法,没有方法体,所以当两个接口方法同名时,子类覆盖方法不会出现不确定性。
  • 接口的出现避免了单继承的局限性
  • 接口与接口之间是继承关系,而且接口可以多继承,因为接口中的方法没有方法体
interface A
{
	public abstract void show();
}

interface Z
{
	public abstract void show();
}

class Test implements A,Z//多实现
{
	public void show()
	{}
	class Q
{
	public void method()
	{}
}

class Test2 extends Q implements A,Z
{
	public void show()
	{}
	}
	interface CC
{
	void show();
}

interface MM
{
	void method();
}

interface QQ extends CC,MM//接口与接口之间是继承关系,而且接口可以多继承。因为接口中的方法没有方法体
{
	void function();
}

class WW implements QQ
{
//覆盖3个方法。
	public void show(){}
	public void method(){}
	public void function(){}
}

4.8.1 接口的特点

  • 接口是对外暴露的规则(public)
  • 接口是程序的功能扩展
  • 接口的出现降低耦合性
  • 接口可以用来多实现
  • 类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口
  • 接口与接口之间可以有继承关系

4.8.2 接口与抽象类

  • 共性:都是不断抽取出来的抽象的概念
  • 区别:
    1,抽象类体现继承关系,一个类只能单继承
    接口体现实现关系,一个类可以多实现
    2,抽象类是继承,是"IS-A"关系
    接口是实现,是"LIKE-A"关系
    3,抽象类中可以定义非抽象方法,供子类直接使用
    接口的方法都是抽象的,接口中的成员都有固定修饰符

4.9 多态

多态的定义:某一类事物的多种存在形态

  • 例:动物中猫,狗。
  • 猫这个对象对应的类型是猫类型
 Cat x = new Cat( );
  • 同时猫也是动物中的一种,也可以把猫称为动物
 Animal y = new Cat( );
  • 动物是猫和狗具体事物中抽取出来的父类型
  • 父类型引用指向了子类对象
  • 多态的好处:提高了代码的扩展性,前期定义的代码可以使用后期的内容
  • 多态的弊端:前期定义的内容不能调用后期子类的特有内容
  • 多态的前提
  • 必须有关系,继承,实现
  • 要有覆盖
  • 转型
  • 向上转型
Animal a = new Cat();/*自动类型提升,猫对象提升为动物类型,但是特有功能无法访问
							作用是为了限制对子类特有方法的访问,提升代码扩展性。*/
  • 向下转型
Cat c = (Cat)a;//作用是为了调用子类中的特有方法。
  • Instanceof:用于判断对象的具体类型。只能用于引用数据类型判断。
  • 通常在向下转型前用于健壮性的判断。
  • 例:
public static void method(Animal a)//Animal a = new Dog();
{
	a.eat();
	if (a instanceof Cat)    //instanceof:用于判断对象的具体类型,即判断a是否属于Cat类型
	{
		Cat c = (Cat)a;
		c.catchMouse();
	}
}
  • 多态的特点
  • 成员函数
  • 编译时:参考引用型变量所属的类中是否有调用的函数。有,编译通过,没有,编译失败。
  • 运行时:参考的是对象所属的类中是否有调用的函数。
  • 简单说:编译看左边,运行看右边
  • 成员变量
  • 编译时:参考引用型变量所属的类中是否有调用的成员变量,有,编译通过;没有,编译失败。
  • 运行时:参考引用型变量所属的类中是否有调用的成员变量,并运行该所属类中的成员变量。
  • 简单说:编译和运行都参考等号的左边。只看引用变量所属的类

内部类

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

  • 访问特点
  • 内部类可以直接访问外部类中的成员,包括私有成员
  • 而外部类要访问内部类中的成员必须要建立内部类的对象
  • 直接访问外部类中的内部类中的成员。
Outer.Inner in = new Outer().new Inner();
in.show();
  • 如果内部类是静态的。 相当于一个外部类
Outer.Inner in = new Outer.Inner();
in.show();
  • 如果内部类是静态的,成员是静态的。
Outer.Inner.function();//function()为内部类中的静态方法
  • 如果内部类中定义了静态成员,该内部类也必须是静态的。否则编译不通过
  • 内部类可以存放在局部位置上
  • 内部类在局部位置上只能访问局部中被final修饰的局部变量。
  • 匿名内部类
  • 匿名内部类。就是内部类的简写格式。
  • 必须有前提:内部类必须继承或者实现一个外部类或者接口。
  • 匿名内部类其实就是一个匿名子类对象。
  • 格式:new 父类or接口(){子类内容}
  • 当函数参数是接口类型时,而且接口中的方法不超过三个时,可以用匿名内部类作为实际参数进行传递
  • 例题:
    注释符内部代码为什么编译失败?
class Outer
{
	void method()
	{
		new Object()
		{
			public void show()
			{
				System.out.println("show run");
			}
		}.show();
		
		/*
		Object obj = new Object()
		{
			public void show()
			{
				System.out.println("show run");
			}
		};
		obj.show();
		*/
	}
}
class InnerClassDemo6 
{
	public static void main(String[] args) 
	{
		new Outer().method();
	}
}

因为匿名内部类这个子类对象被向上转型为了Object类型。
这样就不能再使用子类的特有方法了。

  • 对象的初始化过程
    对象初始化内存图解

异常

异常的定义:异常是在运行时期发生的不正常情况

  • 在Java中用类的形式对不正常情况进行了描述和封装对象。描述不正常的情况的类,就称为异常类

  • 以前正常流程代码和问题处理代码相结合,现在将正常流程代码和问题处理代码分离。提高阅读性

  • 其实异常就是Java通过面向对象的思想将问题封装成了对象。用异常类对其进行描述。不同的问题用不同的类进行具体的描述。比如角标越界、空指针等等。

  • 异常的体系

  • Throwable

  • Error 一般不可处理的

    • 通常出现重大问题如:运行的类不存在或者内存溢出等。
    • 不编写针对代码对其处理
  • Exception 可以处理的

    • 在运行时运行出现的一些情况,可以通过try catch finally
    • Exception和Error的子类名都是以父类名作为后缀
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值