1.封装性
- Java通过访问控制来实现封装性,访问控制通过4个访问修饰符实现,分别是
public
(公共),protected
(保护),default
(默认),private
(私有)。 - Java对类和类成员有不同的访问控制方式,对于类来讲,类能使用的访问修饰符为
public
和default
,public
可以使所有软件包使用,即可被任何类进行调用,而default
(默认不写),仅能使在同一个包下的类使用,别的包无法访问。 - 需要注意,一个Java文件中可以有多个类,但只能有一个
public
类(主类),这个类的名字与文件名相同,且main函数也应该在这个类下。
类成员的访问控制方式(如下表):
可见度 | private | default | protected | public |
---|---|---|---|---|
同一个类下 | 允许访问 | 允许访问 | 允许访问 | 允许访问 |
同一个包下 | 允许访问 | 允许访问 | 允许访问 | |
不同包的子类 | 允许访问 | 允许访问 | ||
不同包的非子类 | 允许访问 |
2.继承性
(1)extend关键字
- 子类继承父类运用
extend
关键字类继承。 - 子类是父类一个专门化,它继承了父类的所有变量和方法,并可以自己拓展变量和方法。
- 继承具有传递性,如A拥有子类B,B拥有子类C,则A是C的父类。
使用继承需要遵循几个原则
- Java只支持单重继承,不支持多继承。
- 子类只能继承父类中非
private
的成员变量。 - 子类的成员变量与父类的成员变量重名时,子类的变量会覆盖父类的变量,而不是被继承。
- 子类只能继承父类中非
private
的成员方法。 - 子类的成员方法名与父类的成员方法名相同时,子类的成员方法会覆盖父类的成员方法,而不是继承。
Java为什么子类到父类的“向上转型”能被允许?
如:
1 | JPeople p1 = new JStudent()//子类JStudent向父类JPeople转型 |
所以子类是父类的一个超集,所以子类具有比父类多的成员变量和成员方法(至少包含所有父类需要的变量和方法)。在“向上转型”时,最可能发生的就是一些变量与方法的丢失,但子类包含所有父类的变量和方法,因此“向上转型”被允许。
(2)super关键字
- 表示对某个类的父类的引用
- 主要分为两种:
- 对于被子类隐藏(覆盖)的变量和方法的调用。
- 对于父类构造方法的调用。
如果要避免某个父类的方法被子类经常,可以使用final关键字,使得子类无法继承这个方法(即子类不能出现与父类这个方法同名的函方法的出现),若要使得一个类不能被继承,可以在类前面加final关键字,使得这个类无法被继承。
构造函数的继承
子类可以使用super关键字来对父类的构造方法进行调用,示例如下:
1 | super(参数列表) |
这里调用的父类构造方法的参数列表必须与super
中的参数列表完全对应,且子类的构造方法只能执行一行super
(参数列表)(即无法同时调用多个父类构造方法),当父类的构造方法调用结束后会重新执行子类构造方法剩余的语句。
子类与父类的构造方法之间存在约束关系,构造方法的继承性主要体现以下几个原则:
- 按继承关系,构造方法是从顶向下进行调用的。
- 如果子类没有构造函数,会默认调用父类的无参构造方法,如果父类没有无参构造方法,则程序会报错。
- 如果子类有构造方法,那么会先调用父类的构造方法,然后再调用子类的构造方法。
- 如果子类有构造方法,但在方法中没有
super
关键字,会默认调用父类的无参构造方法。因此,当父类有有参构造方法,就会没有默认无参构造方法,当遇到第4条情况时,调用无参构造方法时,系统会报错,故在编写程序时为防止出错,都会再写一个无参构造方法。
- 若要调用父类的有参构造方法,在编写
super
(参数列表)语句时,需将它放在子类构造方法的第一行。
3.多态性
多态性是指同名的若干方法(含有不同的参数个数,参数类型,参数顺序,以及返回类型),主要分为两种:
- 方法重载:即在一个类中拥有相同的方法名,但含有不同的参数个数,参数类型,参数顺序,方法通过参数不同调用不同的方法。
注意:返回类型不同的同名方法不是方法重载。
- 方法覆盖:又可以称为动态多态性,即子类方法对于父类的方法进行重新定义。
1.子类中重写的方法必须与父类方法要有相同的名字,参数列表和放回类型。
- 子类覆盖的方法不能缩小父类方法的访问权限。
- 方法覆盖只存在与父类与子类中,在同一个类中,那叫方法重载。
- 父类的静态方法不能重载为非静态方法,父类的非静态方法不能重载为静态方法。
- 父类的私有方法不能被继承,因为私有方法只能在本类中使用,无法被子类覆盖。
- final修饰的方法无法被子类覆盖,覆盖功能虽然很强大,但有时要避免方法覆盖,可以用关键字final。
方法覆盖的“向上转型”机制
当一个被覆盖的方法被父类引用调用时,Java根据当前被引用对象的类型来决定哪个版本的方法。
4.抽象类
定义:抽象类是专门设计用来给子类继承的,抽象类中包含成员变量,构造方法,一般方法,抽象方法。抽象类中抽象方法以分号结尾,且不含方法体,必须被子类重载。
- 抽象类中必须包含抽象方法,也可以包含成员变量,一般方法等,子类必须重载抽象类中的所有抽象方法。
- 如果一个类不是抽象类,就不能在这个类中定义抽象方法。
- 抽象类可以有构造方法,但抽象类不会有实例,也不能构造方法来直接生成实例,一般可以通过子类实例化。
- 如:
JShape s=new JRectangle(10,20)
,该实例化过程也属于“向上转型”。 - 对于类不能同时使用
abstract
和final
关键字,对于方法不能同时使用static
和abstract
关键字。动态调度机制只对方法名有效,对变量名没有效果,也就是说当父类当变量与子类的变量重名时,调用的还是父类的变量。
5.接口
定义:接口是程序早期建立的一组协议,它没有被具体实现,这样便于设计更合理的类层次,使代码更灵活。
在Java语言中,一个类只能有一个父类,但可以多重继承多个接口。
接口是一个特殊的类,由常量与抽象方法组成。
接口的定义有以下几个知识点要掌握:
- 接口具有多重继承,一个接口可以继承多个父接口,父接口之间用逗号分割。
- 系统默认接口中的所有变量都加上了
public
,static
,final
修饰符。 - 系统默认接口中所有方法都加上了
public
,abstract
修饰符。 - 接口只包含常量定义和抽象方法。
- 接口本身具有抽象类,因此不需要使用
abstract
关键字,接口的访问控制权限有public
和default
默认权限,不具有protected和private权限。 - 接口不含构造方法,由于接口没有构造方法,因此不能通过接口来生成接口的实例对象。
- 接口的实现:
为实现一个接口,在类定义中加入implements
关键字,然后创建接口定义的方法。由于接口是一个抽象类,因此当一个类实现一个接口时,必须重写接口中的所有方法,即方法覆盖。
当一个类实现了一个继承了另一个接口的接口,这个类必须实现接口继承列表中的所有方法,即接口A继承了接口B,接口B继承了接口C,类实现接口A,则这个类需要实现接口A,B,C中的所有方法。
接口与抽象类的区别
- 一个接口可以继承多个接口,而抽象类不能。
- 抽象类内部可以有变量和一般方法,但接口中只能含有常量和抽象方法。
- 一个类和它所实现的接口不构成继承体系,即接口不是类体系的一部分,几个不相关的类可以实现同一个接口,而抽象类是类继承体系的一部分,一般位于类的最顶层。
- 接口可以通过实现多个接口实现多重继承,能够抽象出不相关类之间的相似性,而抽象类不行。
- 要一个类只能
extend
一个父类,但可以implements
多个接口。
有没有一个类实现了一个接口,但没实现接口中的所有方法?
(1)可以使这个类的父类实现了接口的方法,这个类继承了父类的方法,无需重新实现
(2)这个类是一个抽象类。
6.抽象类
Java语言允许一个类的定义在另一个类中,这个类就叫做内部类,如果类B被定义在类A的内部,那么类B就无法被外部类所调用,但它可以调用类A的成员,包括private成员。
按照内部类是否显现类名,把它分为实名内部类和匿名内部类。
实名内部类
实名内部类相比与一般类增加类protected
(保护模式)private
(私有模式)两种访问权限。
- 实名内部类可以使用static关键字,通过static修饰符的实名内部类叫做静态实名内部类,由于static修饰可以不通过对象来调用,所以静态实名内部类实例对象的格式如下:
new 外部类名.实名内部类名(构造方法调用参数列表)
2. 没有static修饰符的内部类叫做不具有静态属性的实名内部类,这种类的特点是若它的成员变量有static关键字,那么必须加final修饰,它的成员方法不能加static修饰,创建对象格式如下:
外部实例对象.new 实名内部类名(构造方法调用参数列表)
内部类可以和外部类同名的成员变量(调用内部类成员使用this.**,调用外部类成员外部类名.this.**),外部类可以通过实例化内部类得到其对象,并能使用内部类的成员,内部类可以直接在外部类的方法中进行定义。
匿名内部类
匿名内部类也是内部类的一种,其主要特征是不具有类名,且类布局有抽象和静态属性,也不能派生出子类,格式如下:
1 | new 父类名(父类型的构造方法的调用参数列表){ |
内部类总给人一种神秘的感觉,它的作用主要可以总结成以下几点:
- 进一步实现多继承,一个类内部可以使用定义多个内部类。
- 能更好的解决接口和父类中方法的同名冲突。
- 隐藏程序实现的细节。
- 内部类可以无条件的访问外部类的成员。
泛型类
泛型类的本质是参数化类型,也就是所操作的数据类型被指定为一个参数,当这种参数类型用在类中时,该类就被称为泛型类。(与C++中的模版类似)
Class类
Java运行是系统一直对所有的对象进行运行是类型标识。这项信息记录了每个对象所属的类。Java虚拟机通常使用运行时类型信息选准正确方法去执行,用来保存这些信息类型的类就叫做Class类。