------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
一、继承
1、定义
继承是java的三大特征之一。多个类具有相同的特性时,就可以继续向上抽取,成为这些类的基类,而这些类可以继承基类的共性数据,也可以有自己的特性数据。这就是继承。例如:学生和教师都具有人的基本属性:姓名,年龄,住址。同时又分别有自己的特性行为,学生具有学习的特性,教师具有教课的特性。人就成为教师类和学生类的父类。
教师类和学生类继承人的类。
java中表达继承,使用关键字extends
学生类 教师类与Person类的继承关系
Persons
|----------Student
|----------Teacher
注意:不要为了获取其他类中的功能而盲目继承。必须是具有共性抽取出来的内容才可以使用继承关系。继承关系是is a.谁是谁其中的一种。
2、继承的优点
1)提高了代码的复用性。
2)让类与类之间产生了关系,有了这个关系,才有了多态的特性。
注解:java不支持多继承,只支持单继承。因为多继承容易引发安全隐患,当多个父类中定义相同功能,但功能内容不同,子类对象不确定要运行哪一个功能。java不支持多继承,但java将多继承的特性在接口中采用多实现来弥补,且避免其弊端。所以,java在继承方面大大优先于c++
3、继承的应用
java虽然不支持多继承,但是支持多层继承,也就是说会形成一个一个的继承体系。
A
|----B
|----C
|-----D
|------E
所以当我们学习API文档中的类时,已经是一个很庞大的继承体系了,那么如何这个继承体系的功能呢?
想要使用体系,要先查阅体系中父类的描述。因为父类中定义的是该体系中共性功能。通过了解共性功能,就可以知道该体系的功能了。这个体系就可以基本使用了。
那么在具体调用时,要创建最子类的对象。为什么呢?
1 因为有可能父类不能创建对象,如抽象类
2 创建子类,可以使用更多的功能,包括基本的,也包括特有的。
简单一句话,查阅父类功能,创建子类对象使用功能。
4、子父类中成员的特点
A变量
当子类出现与父类同名的成员变量时,调用子类该成员变量,用this,调用父类成员变量,用super
super和this的作用几乎一致。super是指向父类的当前对象。this指向的是子类的当前对象。
在内存中的情况是:一new对象,jvm就会在堆内存中开辟两个变量的空间,在方法区内存中加载子类class文件时,会先加载父类的class文件,先初始化父类,然后才初始化本类。此时,super和this都指向的是创建的子类对象。这就叫做多态。
总结:多态就是父类引用指向了子类对象。
B成员函数
这里的成员函数会有一个新特性就是覆盖。
覆盖:当父类和子类出现相同的函数名及参数列表,但函数内定义的功能却不尽相同。此时,若用子类对象调用该函数,调用的是子类的函数,似乎是把父类的同名函数给覆盖一样。
如: 父类中有show方法,子类也有show方法,语句
子类对象.show();运行的是子类show方法中的函数体。其实,父类的show方法还在内存,只是没有运行。覆盖只是形象的说法。
运行结果:
覆盖的应用:
当子类继承父类,沿袭了父类的功能,到子类中,但是子类虽然具备该功能,但是功能的内容却和父类不一致,这时,没有必要定义新功能,而是使用覆盖特性,保留父类的功能定义,并重写功能内容。这有利于功能扩展。
注意事项
1)子类覆盖父类,必须保证子类权限大于等于父类权限,才可以覆盖,否则编译失败
2)子类不能覆盖父类private的功能 ,因为子类都不知道父类这种功能。
3)静态只能覆盖静态
C 构造函数
示例
结果:
出现这情况的原因是,在子类构造函数内第一行有一条隐式语句super();也就是,你不写,系统会自动帮你加上。
super()会自动访问父类空参数的构造函数,如果父类中没有定义空参数的构造函数,就会出现错误。
如果父类定义的构造函数是有参数的呢,那就需要在子类构造函数的第一行显式地写
super(参数)来访问父类。
为什么子类一定要访问父类中的构造函数?
因为父类中的数据,子类可以直接获取,所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的,所以子类在对象初始化时,要先访问一下父类中的构造函数。如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。
例如:
注意 super语句一定定义在子类构造函数的第一行
结论
子类的所有构造函数,默认都会访问父类中空参数的构造函数,因为子类每一个构造函数的第一行都有一句隐式的super();当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问的构造函数。当然,子类的构造函数第一行也可以手动指定this语句访问本类的构造函数。子类中至少会有一个构造函数访问父类。而父类构造函数的第一行也有隐式super(); 它也会访问它的父类。在java中,有一个所有类的父类,就是Object。
5、final关键字
Final 最终的意思。作为修饰符。
它的特点是:
1) final可以修饰类,方法,变量
2) final修饰的类不可以被继承
继承的好处: 提高复用性,多态
弊端: 它打破了封装性。不再被隐藏起来,因为父类的方法都被复写了。
为了避免被继承,被子类复写功能。在类前加final。
3) final修饰的方法不可以被覆盖
4)final修饰的变量是一个常量。只能被赋值一次
在描述事物时,一些数据的出现,值是固定的,这时,为了增强阅读性,都给这些值起个名字,方便与阅读,而这个值不需要改变,所以加final修饰。
例如 final double PI =3.1415926;
作为常量,书写规范是所有字母都大写,如果由多个单词构成,单词间通过下划线连接。
一般被finail修饰的常量,还要加上static,就是共享。
public static final double PI=3.1415926;全局常量
权限最大,不会变。
5) 内部类定义在类中的局部位置上时,只能访问被final修饰的局部变量。
二、抽象类
1、抽象的定义
就是从事物中不断抽取出最共性的内容。例如:猫、狗都属于动物,但动物是一个抽象的概念,不是具体的实体。
2、抽象类:
所谓抽象类,就是只生命方法的存在而不去具体实现它的类。因为不知道该怎么实现。抽象类是无法被实例化的。
当多个类中出现相同功能,但是功能主体不同,这时,也可以进行向上抽取,这时,只抽取功能定义,而不抽取功能主体。这就是抽象类的来历。只声明方法,却没有具体的方法成为抽象方法。
java对于抽象用关键字abstract来表示。
3、抽象类的特点
1) 抽象方法一定在抽象类中,
2)抽象方法和抽象类都必须被abstract关键字修饰
3)不可以用new创建对象,因为调用抽象方法没意义。
4)中的抽象方法要被使用,必须由子类复写起所有的抽象方法后,建立子类对象调用。
如果子类只覆盖了部分抽象方法,那么该子类还是一个抽象类。前面也要用abstract修饰。
抽象类的好处 :强迫子类必须复写抽象类中的抽象方法
抽象类中也可以有非抽象方法。但必须有主体。
抽象类与一般类的区别
1 )抽象类和一般类没有太大的不同,该怎么样描述事物,还怎样描述事物,只不过该事物中一些看不懂的东西。这些不确定的部分,也是该事物的功能,需要明确出来,但是无法定义主体。通过抽象方法来表示
2) 抽象类比一般类多了抽象函数。就是在类中可以定义抽象方法。抽象类中可以不定义抽象方法。这样做可以不让本来实例化,也可以用于模块设计。java类库中就有这样的类
3) 抽象类不可以实例化。
4)象类虽然不能创建对象,但是也有构造函数。供子类实例化调用。
注解:被abstract修饰的函数不能同时被private、final、static修饰。
附:模版设计模式
在定义功能时,功能的一部分是确定的,但是有一部分是不确定的,而确定的部分在使用不确定的部分,这时,就将不确定的部分暴露出去,由该类的子类去复写完成。
它的好处 :提高扩展性 复用性
模版不一定是抽象类,有这种可能,不确定的部分是默认的
实例:用模版的方式实现功能,获取任意一段代码的运行时间。
三、接口
1、定义
接口:初期理解,可以认为是一个特殊的抽象类。当抽象类中的方法都是抽象的,那么该类可以通过接口的形式来表示。
定义类用class,定义接口就用interface。
格式:
Interface 接口名
{
}
子类实现接口格式
class 子类名 implements 接口名
{
}
格式特点:
1)接口中常见定义:一个常量,一个抽象方法
2)接口中的成员都有固定修饰符。 成员变量 public static final 即全局静态常量。 成员函数 public abstract
接口的出现,使多继承通过另外一种形式体现出来,即多实现,这也是java对多继承不支持的转换形式。也就是说,一个类可以实现多个接口。
形如: class A implements B,implements C,implementsD.....
2、接口的特点
1) 接口是对外暴露的规则
2) 接口是程序的功能扩展
3) 接口可以用来多实现。降低了耦合性,即紧密联系程度。
4) 类与接口之间是实现关系,而且类可以继承一个类的同时实现多个接口
5) 接口与接口之间可以有继承关系,但是不可以返回返回值不相同的同名抽象方法。
注意:
a. 接口是不可以创建对象的,因为有抽象方法,需要被子类实现,子类对接口中的抽象方法全部覆盖后,才可以实例化,不然,子类也必须是一个抽象类。
继承,是父类中非抽象数据,子类可以直接拿来用。而接口中,子类必须覆盖接口抽象方法,才可以被实例化。
b. 接口里面的方法都是public修饰的,所以,要子类要覆盖它,也必须是public修饰的。
3、接口与抽象类的区别
相同点:两者都是共性抽取出来的。
不同点:a.抽象类体现的是继承关系,而接口体现的是实现关系,一个类不可以多继承,但可以实现多个接口。
b.抽象类体现的是is a所属关系,而接口体现的是like a 像某种关系。
c.抽象类中可以定义非抽象方法,供子类直接使用。而接口中的方法全部都是抽象的。
d.抽象类中还可以有私有成员,而接口中全部是被public修饰的。
四、多态
定义:多态就是定义某一类事物的多种形态。
例如:动物是猫和狗的父类。猫和狗分别是动物中的种类。所以也可以把猫称为一只小动物。
代码表示:猫 a=new 猫(); 和 动物 a=new 猫();所表达的是一致的。
多态就是父类引用指向了子类对象。
1、多态的基本体现
父类的引用指向了自己的子类对象或者父类的引用也可以接收自己的子类对象。
2、多态的前提
1 )必须是类与类之间有关系,要么继承,要么实现。
2 )通常还有一个前提,就是存在覆盖。
3、 多态的好处
多态的出现,大大提高了程序的扩展性。
4、多态的弊端
多态的出现提高了扩展性,但是只能使用父类的引用访问父类中的成员。但是我们侧重的是扩展性。
5、多态转型
Animal a=new Cat();//这里面进行了一个 类型提升 子类型赋值给父类型。
我们也称之为 向上转型,这个动作是自动进行的。如果想要调用猫的特有方法抓老鼠的功能时,如何操作?
可以强制将父类的引用转成子类类型 叫做向下转型
Cat c=(Cat) a;
c.catchMouse();
千万不要出现这样的操作,就是将父类对象转成子类类型
我们能转换的是父类引用指向了自己的子类对象时,该引用可以被提升,也可以被转换。
规律:多态自始至终都是子类对象在做着变化
6、多态的出现代码的特点
多态使用时注意事项:
1)多态中,成员函数(非静态成员函数)的特点
编译时期,参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过,否则,编译失败。
运行时期,参阅对象所有的类中是否有调用的方法。
简单总结,成员函数在多态中,编译看左边,运行看右边。
2)多态中,成员变量的特点
多态中,成员变量出现同名的现象,成员变量的特点:无论是编译还是运行,都看左边,也就是参考引用型变量所属的类中的变量值
3)多态中,静态成员函数的特点
无论是编译还是运行,都参考左边,因为静态成员函数调用时,不需要对象的。当类被加载到内存,静态函数就已经随着类被加载在方法区内存中,不需创建对象,可以直接被类名访问,同时父类的静态函数一般是不被复写的。
类在方法区中的分配:静态成员在静态区,而this,super都在非静态区。
7、多态的应用
可以应用到定义一个工具类,将共同行为封装到类中。
多态将对象调用变得简单,以前是调用一个对象,现在可以调用一批对象。