Java中的三大特征
隐藏和封装
封装是面向对象的三大特征之一(另外两个是继承和多态),它指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。
使用访问控制符
构造器
使用构造器执行初始化
构造器最大的用处就是在创建对象时执行初始化。
注意:如果我们没有给Java类提供任何构造器,则系统会为了这个类提供一个无参数的构造器,这个构造器的执行体为空,不做任何事情。Java类中至少包含一个构造器。
构造器重载
同一个类中具有多个构造器,多个构造器的形参列表不同,即被称为构造器重载。
类的继承
继承是面向对象的三大特征之一。Java中的继承具有单继承的特点,每个子类只有一个直接父类。
继承的特点
Java的继承通过extends关键字来实现,实现继承的类被称为子类,被继承的类被称为父类,有的也称其为基类、超类。
重写父类的方法
子类包含与父类同名方法的现象被称为是方法重写,也被称为方法覆盖。
重载发生在同一个类的多个同名方法之间,而重写发生在子类和父类的同名方法之间。
super限定
如果需要在子类方法中调用父类被覆盖的实例方法,则可使用super限定来调用父类被覆盖的实例方法。
如果在构造器中使用super,则super用于限定该构造器初始化的是该对象从父类继承得到的实例变量,而不是该类自己定义的实例变量。
调用父类构造器
子类不会获得父类的构造器,但子类构造器里可以调用父类构造器的初始化代码。
在一个构造器中调用同一个类中另一个重载构造器使用this调用来完成,在子类构造器中调用父类构造器使用super调用来完成。
多态
Java引用变量有两个类型:一个是编译时类型,一个是运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就可能出现所谓的多态。
class BaseClass {
public int book = 6;
public void base() {
System.out.println("父类中的普通方法");
}
public void test() {
System.out.println("父类的被覆盖的方法");
}
}
public class SubClass extends BaseClass{
public String book = "Java";
public void test() {
System.out.println("子类的覆盖父类的方法");
}
public void sub() {
System.out.println("子类的普通方法");
}
public static void main(String[] args) {
//编译时类型和运行时类型不同,多态发生
BaseClass ploys = new SubClass();
//输出6
System.out.println(ploys.book);
//调用从父类继承来的base方法
ploys.base();
//执行当前类的test方法
ploys.test();
//error
//ploys.sub();
}
}
}
当把一个子类对象直接赋给父类引用变量时,BaseClass ploys = new SubClass();当运行时调用该引用变量的方法时,其方法行为总是表现出子类方法的行为特征,而不是父类方法的行为特征。这就可能出现:相同类型的变量、调用同一个方法时呈现出多种不同的行为特征,,这就是多态。
多态的体现
父类的引用引向了自己的子类对象。
前提
必须是类与类之间有关系,要么继承,要么实现存在覆盖。
好处
提高了程序的扩展性。
弊端
只能使用父类的引用访问父类的成员。
注意
对象的实例变量不具备多态性。
instanceof运算符
instanceof运算符的前一个操作数通常是一个引用类型变量,后一个操作数通常是一个类(也可以是接口),它用于判断前面的对象是否是后面的类,或者其子类、实现类的实例。如果是,返回true,否则返回false。
注意
instanceof运算符前面的操作数的编译时类型要么与后面的类相同,要么与后面的类具有父子继承关系。
继承与组合
使用继承的注意点
继承严重的破坏了父类的封装性。
为了保证父类有良好的封装性,不会被子类随意改变,设计父类应当有如下规则:
- 尽量把父类的所有成员变量都设置成private访问类型,不要让子类直接访问父类的成员变量。
- 不要让子类可以随意访问、修改父类的方法。例:父类中仅为辅助其他的工具方法,应该使用private访问控制符修饰,让子类无法访问该方法;如果父类中的方法需要被外部类调用,则必须有public修饰,但又不希望子类重写该方法,可以使用final修饰符来修饰该方法;如果希望父类的某个方法被子类重写,但不希望被其它类自由访问,则可以使用protected来修饰该方法。
- 尽量不要在父类构造器中调用将要被子类重写的方法。