类的三大特性
封装性、继承性、多态性
封装
封装性是通过访问控制来实现的。
访问:
- 对于类来说:访问就是使用类的成员域(属性/成员变量)或成员方法,从当前类派生出子类或者通过类的构造方法生成实例对象等;
- 对于成员域来说:访问就是读取该成员域的值,或者改变该成员域的值;
- 对于成员方法来说:访问就是调用该成员方法;
- 对于构造方法来说:访问就是通过构造方法创建实例对象;
访问控制方式:public,protected,默认模式,private。
私有模式的成员变量和成员方法不会被继承。
一般建议将类的构造方法的访问控制方式设置为public(公共模式)。将有特殊限制的成员变量的访问控制方式设置成private(私有模式),这时,可以添加两个成员方法(get和set方法)分别来读取和设置这个具有特殊限制的成员变量的值。在set方法中还可以对不合理的参数进行修正。
public class Pet {
public Pet(){
System.out.println("父类的构造方法被调用了");
}
//封装数据,类的属性私有
private String name;
private int age;
// 通过调用get方法获取数据,set方法设置初始值以及安全性验证
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
继承
继承性是实现软件可重用性的一种重要手段,通过在关键字extends后面添加父类名,指定当前定义的类的父类;还可以在关键字implements的后面添加接口名称列表,指定当前定义的类所实现的各个接口。通过这种方式,使得当前定义的类可以继承其父类或所实现接口的成员域或成员方法,即在当前定义的类与其父类或所实现的接口之间建立起一种继承关系(is a)。这种继承关系具有传递性。
注意点:
- 如果在当前定义的类中含有选项“extends 父类名”,则由该选项指定的父类是当前定义的类的直接父类,否则,当前定义的类的直接父类是类java.lang.Object。(Object类是所有类的父类)
- 选项“extends 父类名”只能指定一个父类名(单继承),所以每个类(类java.lang.Object除外)有且仅有一个直接父类。
- 继承之后,子类拥有父类的所有成员变量和成员方法。(根据访问控制的方式决定)
- super关键字,有继承关系后,可以通过super关键字可以访问父类的成员变量和成员方法。super关键字只能出现在子类的成员方法或构造方法中。成员方法被子类重写,通过super可以访问未重写的成员方法。
- 在类的定义中,当前定义的类与其直接父类之间在构造方法方面存在约束关系,即当前定义的类的构造方法必须调用其直接父类的构造方法,而且该调用语句必须是当前定义的类的构造方法的第一条语句。在子类默认的无参构造方法中,有默认的调用父类的构造方法的语句,只是没有显现出来。(不能同时用super和this调用构造方法。要么super();调用父类的构造方法,要么this();调用当前类的构造方法。)
示例:
父类:Pet
public class Pet {
public Pet(){
System.out.println("父类的构造方法被调用了");
}
}
子类:Cat
public class Cat extends Pet{
public Cat(){
System.out.println("子类的构造方法被调用了");
}
}
Application类,放主方法。创建对象的时候会调用构造方法,我们在构造方法内加入输出语句。
public class Application {
public static void main(String[] args) {
Cat cat = new Cat();
}
}
如果在当前定义的类的构造方法中没有显示写上调用父类构造方法的语句,则java虚拟机一般会自动在当前定义的类的构造方法的第一条语句前自动地,隐式地添加调用不含任何参数的直接父类构造方法的语句( super(); )。虽然这条语句没有显式地出现在源程序中,但是如果这时直接父类中没有不含任何参数的构造方法,在编译时将出现编译错误。
多态
多态性包括静态多态性和动态多态性。
-
静态多态性:指的是在同一类中同名方法在功能上的重载,也包括一个类对其父类同名方法在功能上的重载。
-
动态多态性:指的是在子类和父类的类体中均定义了具有基本相同声明的非静态成员方法,这是也称为子类的成员方法对其父类基本相同声明的成员方法的重写(覆盖)。
区别之一:因为存在类型转换机制,从而造成无法在编译时识别一个引用表达式(引用变量名)所指向的实例对象是该引用表达式的类型的实例对象,还是其子类型的实例对象。所以在动态多态性的方法调用中无法在编译时识别具体调用的成员方法,一般需要在运行时才能被Java虚拟机识别。
利用动态多态性使得可以通过父类型的引用调用子类型的成员方法,这里要求该父类型的引用所指向的实例对象实际上是其子类型的实例对象,而且调用的子类型的成员方法是对其父类型同名成员方法的重写。
多态存在的条件:
- 有继承关系
- 子类重写父类的方法
- 父类的引用指向子类的对象
重写
重写:子类对父类的非静态方法进行重写。
为什么要进行重写:父类的方法子类不一定需要。
注意点:
-
需要有继承关系!
-
方法名必须相同,参数列表必须相同。
-
方法体不同(实现代码不同)。
-
重写可能会抛出异常。
示例:Cat子类重写Pet父类的say()方法。
父类:Pet
public class Pet {
public void say(){
System.out.println("阿基里嘛");
}
}
子类:Cat
public class Cat extends Pet{
@Override //重写的注释
public void say() {
System.out.println("Giao!");
}
}
Application类
public class Application {
public static void main(String[] args) {
Cat cat = new Cat();
cat.say();
//父类的引用指向了子类
Pet pet = new Cat();
pet.say();
}
}
父类方法被重写了,如果子类要访问原来的成员方法,可以通过super关键字。