1、继承-概述
继承是面向对象的第二大特征,其他两个是封装和多态。使用的是extends关键字,格式:class A{} class B extends A。
继承就是把类之间共性的特征抽取出来但是两个类之间必须存在某种联系,然后才可以进行继承。
例如:学生和工人,他们都有名字和年龄,但是他们都是人,所以可以把名字和年龄封装到Person类中,然后类Student和类Worker继承类Person,那么就可以不用写年龄和姓名属性,那么就会继承过来,前提:属性权限不能是私有的。
class Person{
String name;
int age;
}
class Student extends Person{
}
class Workerextends Person{
}
优点:提高了代码的复用性;让类与类之间产生了关系,才有了多态的特性。
注意:千万不要为了获取其它类的功能简化代码而继承,必须是有类与类之间有所属关系才可以继承,所属关系is a。
2、单继承
Java只支持单继承,不支持多继承。即一个孩子只能有一个父亲。
因为多继承容易带来安全隐患:当多个父类中定义了相同功能,当功能内容不同时,子类对象不确定要运行哪一个。但是java保留这种机制。并用另一种体现形式来完成表示。多实现。
class Person
{
String name;
int age;
}
class Student extends Person
{
void student()
{
System.out.println("good study");
}
}
class Worker extends Person
{
void worker()
{
System.out.println("good work");
}
}
3、聚集关系
聚合:如球员和球队的关系
组合:如手和人,手是人身体的一部分。
4、子父类中变量的特点
如果子父类中出现了非私有的同名变量时,子类要访问本类中的变量,用this。;子类要访问父类中的同名变量,用super。
this代表本类对象的引用,super代表父类对象的引用。
public class Fu {
public String name="父类";
public void show(){
System.out.println(name);
}
}
public class Zi extends Fu {
public String name = "子类";
public void show() {
System.out.println("默认调用:"+name);
System.out.println("父类的 super:"+super.name);
}
public static void main(String[] agrs) {
Zi z = new Zi();
z.show();
}
}
结果:
默认 调用:子类
父类的 super:父类
5、子父类中函数的特点
覆盖:当子类出现和父类一模一样的函数时,父类函数被覆盖,子类对象调用该函数,会运行子类函数的内容
作用:当子类沿袭父类功能,但子类虽具备该功能却和父类不一致时,使用覆盖特性
注:子类覆盖父类,必须保证子类权限大于父类权限,才能覆盖,否则编译失败。
子父类方法要一模一样,包括返回值类型。
public class Fu {
public void show(){
System.out.println("父类这样展示");
}
}
public class Zi extends Fu {
public void show() {
System.out.println("子类重写父类的show()方法,自己的show()");
}
public static void main(String[] agrs) {
Zi z = new Zi();
z.show();
}
}
结果:子类重写父类的show()方法,自己的show()
6、子父类中构函数的特点-子类实例化过程
子父类中构造函数的特点:
子类的构造函数的第一行隐式有一行语句:super();
在对子类对象进行初始化时,父类的构造函数也会运行,那是因为子类的构造函数默认第一行有一条隐式语句super();
super();会访问父类中空参数的构造函数,而且子类中所有的构造函数默认第一行都是super();
为什么子类一定要访问父类中的构造函数:因为父类中的数据子类可以直接获取,所以子类对象在建立时,需要先看父类是如何对这些数据进行初始化的,所以子类在对象初始化时要先访问以下父类的构造函数,如果要访问父类中指定的构造函数,可以子类的构造函数第一行手动的定义super(参数);访问父类构造函数的方式。
子类的实例化过程:
public class Fu {
public Fu() {
System.out.println("父类无参构造方法");
}
}
public class Zi extends Fu {
public Zi(){
//这里省略了 super();
System.out.println("子类无参构造方法");
}
public static void main(String[] agrs) {
Zi z = new Zi();
}
}
结果:
父类无参构造方法
子类无参构造方法
结论:子类中所有的构造函数默认都会访问父类中空参数的构造函数,因为子类每一个构造函数的第一行都有一句隐式的super();当父类中没有参数的构造函数,子类必须手动的通过super语句形式来指定要访问的父类中的构造函数。
当然,子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数,子类中至少有一个构造函数会访问父类中的构造函数。
7、final
(1)作为一个修饰符,可以修饰类,变量,函数。
(2)被final修饰的类不可以被继承,为了避免被继承,屏蔽子类复写功能。继承对封装是一个挑战。
(3)被final修饰的方法不可以被重写。
(4)被final修饰的变量是一个常量只能赋值一次,即可以修饰成员变量,也可以修饰局部变量。当在描述事物时,一些数据的出现的值是固定的,这时为了增强阅读性,都给这些值起个名字方便阅读,而这个值不需要改变,所以加final修饰,作为常量,常量的书写规范所有字母都大写,如果有多个单词组成,单词间通过下划线连接。
(5)内部类定义在类中的局部位置上是,只能访问该局部被final修饰的局部变量。
class Demo {
public final double PI = 3.14;// 这样一般大写,不可以被修改,一般都是把对象是统一的,切不能不修改的变量
public final void show() {// 此方法不能被重写
System.out.println("helloworld");
}
public void print() {// 此方法可以被重写
System.out.println("print()");
}
}
class DemoZi extends Demo {
public void print() {// 此方法可以被重写
System.out.println("DemoZiprint()");
}
public static void main(String[] agrs) {
DemoZi zi = new DemoZi();
zi.show();
zi.print();
}
}
结果:
hello world
DemoZi print()
8、抽象类
当多个类中出现了相同功能,但是功能主体不同,这时可以进行向上抽取,这时只抽取功能定义,而不抽取功能主题。
抽象:就是所谓的看不懂。
特点:
(1)抽象方法一定定义在抽象类中。
(2)抽象方法和抽象类都必须被abstract关键字修饰。
(3)抽象类不可以被new关键字创建对象,因为调用抽象方法没有意义。
(4)抽象类的抽象方法要被使用,必须由子类复写出所有的抽象方法后,建立子类对象调用。
如果子类覆盖了部分抽象方法,那么该子类还是一个抽象类。
**
* 描述人的类
*/
abstract class Person {
private String name;
public Person(String name) {
this.name = name;
}
/*
* 人都要工作,只是工作的方式不一样学生要工作,那就是学习,工人要工作:那是上班但是他们之间不饿能存在继承关系,否则他们之间的关系就乱了。
* 那么定义成抽象方法,那么子类就必须重写此方法,不会存在不重写就会继承父类的方法体内容(因为父类中抽象方法没有方法体)
*/
public abstract void work();
}
class Work extends Person {
public Work(String name) {
super(name);
}
@Override
public void work() {
System.out.println("工人工作");
}
}
class Student extends Person {
public Student(String name) {
super(name);
}
public void work() {
System.out.println("学生工作");
}
}
9、与一般类的区别
抽象类和一般类没有太大的不同,该如何描述事物就如何描述事物,只不过该事务中出现了一些看不懂的东西,这些不确定的部分也是该事务的功能,需要明确出现,但是无法定义主体。通过抽象方法来表示。
抽象类比一般类多了抽象方法(函数)。
抽象类不可以被实例化。作用就是不让该类建立对象。
抽象类中可以不定义抽象方法,这样做仅仅是不让该类建立对象。
10、接口
接口:初期理解可以认为是一个特殊的抽象类,当抽象类中的方法都是抽象的,那么该类可以通过接口的方式来表示。interface用来定义接口。
接口定义时的特点:
(1)接口中常见定义:变量,抽象方法。
(2)接口中成员都有固定修饰符,
常量:public static final
方法:public abstract
记住:接口中的成员都是public的。
接口是不可以创建对象的,因为有抽象方法,需要被子类实现,子类对接口中的抽象方法全都覆盖后,子类才可以被实例化,否则子类是一个抽象类。
interface编译后也是一个class文件。
11、多实现
接口可以被类多实现。也是对多继承不支持,对接口可以进行多实现。
实现接口:implements
一个类在继承一个类的同时,可以实现多接口。
类与类之间是继承关系,类与接口之间是实现关系,接口与接口之间是继承关系。
java只有在接口和接口之间可以实现多继承。
13、接口的特点
接口是对外暴漏的规则
接口是程序的功能扩展
接口可以用来多实现;类与接口之间是多实现关系,而且类可以在继承一个类的同时实现多接口
接口与接口之间可以有多继承
14、接口的实现举例
可以将不是共有的功能放到接口中,谁具有此接口中的功能,谁就实现它。
可以定义规则,例如电脑上的USB接口,只要是USB接口,那么就可以插入,不管是什么设备,USB就是一个接口,那么还有设备就是其子类。