Java-面向对象篇下《二》
1.继承的概念
-
面向对象的特点之一,可以实现对类的复用。可以通过以下两种方法实现
-
a.合成/聚合关系(包含其他类):将一个类当作另一个类的属性。
-
b.派生类:一个类继承另一个类,实现继承的类称为派生类,被继承类称为父类,基类,超类。
-
父类的成员方法和成员变量被子类继承,但是父类的构造方法没有被继承。
-
在Java中只支持单继承,和C++多继承不一样。
2.super关键字
1.super可以访问父类的成员变量
2.super可以调用父类的成员方法
3.super可以在子类构造方法里调用父类的构造方法
注意:super只能在成员方法和构造方法里使用,不能在static方法里使用(和this一样),
在构造方法中使用必须放在第一行。
3.this和super关键字比较(都不能在static方法中调用)
4.方法覆盖
-
方法覆盖只存在子类和父类之间
-
子类覆盖父类的方法时,访问权限不能缩小,可以扩大,其他写法一样
-
父类的静态方法不能被子类覆盖为非静态方法
5.访问权限
类的访问修饰符
-
public:任何包中的类(即一切的类)都可以访问该类
-
默认值:同一包中的类可以访问该类
成员的访问修饰符
-
private:只对本类可见,对子类不可见
-
默认值:对同一包中的类可见
-
protected:对同一包中的类和所有子类可见
-
public:对一切类可见
注意:访问成员的前提是首选能访问成员所在的类
6.重写和重载的比较
7.对象的多态性
多态是指引用类型在不同情况下的多种形态,也可以理解为通过指向父类的指针调用不同子类中覆盖的方法
-
一个基类的引用类型变量可以"指向"其子类的对象。
-
一个基类的引用不可以访问其子类中新增加的成员(属性和方法)。
-
instanceof : 对象 instanceof 类名/接口 //判断该对象是否是该类/该类的子类/实现该接口。
-
子类对象可以当作父类对象来使用称为向上转型,反之称为向下转型。
8.抽象类和抽象方法(abstract)
抽象类(abstract修饰):任何声明为abstract的抽象类无法实例化,除非其子类全部覆盖其抽象方法,
这样子类就不是抽象类,不一定要包含抽象方法,但是有抽象方法的类必须声明为抽象类。
抽象方法(abstract修饰):没有方法体的成员方法。不可以用abstract修饰构造方法。
抽象类的子类:1.抽象父类有抽象方法:
a.非抽象的子类:子类覆盖重写父类所有的抽象方法
b.抽象的子类:父类中的抽象方法只要有一个没有覆盖重写而继承了必须声明为abstract类
2.抽象父类没有抽象方法:
a.非抽象的子类:不用abstract修饰子类且不添加抽象方法即可(此时可以实例化)
b.抽象的子类:可以用abstract修饰,或者添加抽象方法再声明为抽象类。
注意:抽象方法被可视化的修饰符修饰的只有两个即public ,protected,即除了"默认访问修饰符"
"public","protected"修饰抽方法,其余的(private ,static ,final)不可以修饰。
9.abstract,final,static比较
10.接口(interface)
接口:比抽象类还抽象的抽象类,是抽象方法和常量值的定义的集合。没有变量和方法的实现。
接口常量:默认public static final 属性(注意:不接受其他修饰符), type name=value;
接口方法:默认public abstract 属性(注意:不接受其他修饰符),returnType methodName (paramlist)
接口的实现类(implements):实现接口的类必须覆盖所有接口的方法,否则成为抽象类。可实现多个接口
接口的好处:
-
解决了Java的单一继承带来的局限性,也解决了C++多重继承带来的问题,
-
多重继承的危险会导致子类继承同一方法的不同实现。而接口里的方法都没有实现,所以多重继承的问题。
-
通过接口实现不相关类的相同行为,而无需考虑这些类之间的关系。
-
通过接口了解对象的交互界面,而无需了解对象所对应的类
11.抽象类和接口的比较
12.多态性
封装是为了保护属性的操作,继承是为了扩展类的功能
多态是由封装性和继承性引出面向对象程序设计语言的另一个特征。
多态的体现:方法的重载和重写
1.1 静态多态性(编译时多态):由方法重载(overload)实现
1.2 动态多态性(运行时多态):子类对象可以作为父类对象使用,有方法重写(overridder)实现
13.对象的多态性
对象的多态性主要分为两种:
1.向上转型:
父类 父类对象=子类实例;//程序自动完成
注意使用规则:
操作的是父类对象,所以无法访问子类新增加的成员(属性和方法)。
子类中覆盖的方法和同名的成员变量
a.成员变量(包括静态的变量)和静态成员方法:编译和运行都看左边(看父类的)
b.非静态的成员方法:编译看左边的,运行看右边的(子类覆盖的方法)。
2.向下转型:
子类 子类对象=(子类)父类对象;//需要强制转换
14.内部类(等价于一个非静态的成员方法即不可声明static变量)
在类的内部里再定义另外一个类,则这个类称为内部类。
外部类的成员被内部类所知,而内部类的成员不被外部所知,只能实例化内部类来访问其成员
优点:可以方便的访问外部类的私有属性(最大优点),减少编译后字节码文件的大小
缺点:使程序结构不清晰。
14.1 成员内部类(即实例内部类)
-
成员内部类中不能定义static变量
-
成员内部类持有外部类的引用
-
文件管理方面:编译后会产生“外部类名$内部类名.class”的文件
-
外部实例化类的格式:
-
Outer out=new Outer(); Outer.Inner in=out.new Inner();
14.2 静态内部类(外部类)
用static声明的内部类,称为静态内部类,相当于外部类。可以通过外部类.内部类来访问
-
静态内部类不会持有外部类的引用。创建时可以不用创建外部类。
-
静态内部类可以访问外部的静态变量,如果要访问外部类的成员变量必须通过实例化外部类访问
-
外部实例化类的格式
-
Outer.Inner in=new Outer.Inner();
14.3 局部内部类(在方法中定义的内部类)
-
可以访问外部类的成员,要想访问方法中局部变量必须为final类型才可以访问
-
局部内部类不能加private ,protected,public中任一个修饰符
-
不能包含静态成员。
14.4 匿名内部类
-
如果一个内部类在整个操作中只使用一次的话,可以定义为匿名内部类
-
没有名字的内部类,这是Java为了方便我们编写程序而设计的一个机制。有时候有的内部类
-
只需要创建一个对象即可,以后再也不会用到这个类了。
-
匿名内部类是在抽象类和接口的基础上发展起来的。它可以是继承某个类,或是实现某个接口
-
在文件管理上:编译后会产生“外部类名$编号.class”,编号为1,2,3....n,表示第几个匿名内部类
格式:
new 父类或者抽象父类或者接口名()
{ 实现方法}.调用相应的方法;
总结:
多态:非静态方法-编译时看左边,运行时看右边。静态方法和成员变量-都看左边
(非静态)内部类:相当于一个非静态的方法,不能在里面定义静态变量,且内部类默认持有外部类的引用。
(静态)内部类:相当于外部类,不持有外部类的引用。
静态代码块->构造代码块->构造方法