封装
- 一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法
- 封装的优点
- 良好的封装能够减少耦合
- 类内部的结构可以自由修改
- 可以对成员变量进行更精确的控制
- 隐藏信息,实现细节
-
实现方式:属性私有+
setter()/getter()
继承
- 子类继承父类的特征和行为,继承是面向对象的基石
- java 不支持多继承,实现接口可视为弱继承
- 非私有、静态的属性和方法属于类,不能被继承,但能用子类名访问
- 非私有、非静态的属性和方法可以被继承
-
父类的私有属性
- 子类具有拥有权,但是不具有使用权
- 可以使用父类继承来的 setter/getter 方法,访问该属性
-
构造方法不能被继承,在继承中
- 父类没有定义构造方法或定义了无参数的构造方法,子类不须要定义构造方法
- 父类只有带参数的构造方法时,子类也不能有无参构造,必须定义带参构造,且要在第一行通过 super 显式调用父类构造方法
-
final 修饰的成员
- final 修饰的属性可以被继承
- final 修饰的方法可以被继承,不能被重写
分析内存后发现,当一个子类被实例化的时候,默认会先调用父类的构造方法对父类进行初始化,即在内存中创建一个父类对象,然后在父类对象的外部放上子类独有的属性,两者合起来成为一个子类的对象
所以,子类继承了父类的所有属性和方法或子类拥有父类的所有属性和方法是对的,只不过父类的私有属性和方法,子类是无法直接访到的,这也是 private 修饰符所控制的
多态
- 多态:同一个行为具有多个不同表现形式或形态的能力,是对象多种表现形式的体现
-
条件:
- 有继承关系
- 有方法的重写
- 父类引用指向子类对象
属性没有多态的概念,在 java中 只有普通实例方法才可以实现多态
非 private、static 修饰的方法可以实现运行时的多态
多态的优点:解耦、可替换性、可扩充性、接口性、灵活性、简化性
public class Test {
public static void main(String[] args) {
show(new Cat()); // 以 Cat 对象调用 show 方法
show(new Dog()); // 以 Dog 对象调用 show 方法
Animal a = new Cat(); // 向上转型
a.eat(); // 调用的是 Cat 的 eat
Cat c = (Cat)a; // 向下转型
c.work(); // 调用的是 Cat 的 work
}
public static void show(Animal a) {
a.eat();
// 类型判断
if (a instanceof Cat) { // 猫做的事情
Cat c = (Cat)a;
c.work();
}
else if (a instanceof Dog) { // 狗做的事情
Dog c = (Dog)a;
c.work();
}
}
}
abstract class Animal {
abstract void eat();
}
class Cat extends Animal {
public void eat() {
System.out.println("吃鱼");
}
public void work() {
System.out.println("抓老鼠");
}
}
class Dog extends Animal {
public void eat() {
System.out.println("吃骨头");
}
public void work() {
System.out.println("看家");
}
}
重写和重载
-
overwrite:重写,也叫覆盖、覆写,override。
- 参数列表必须完全与被重写方法的相同
- 返回类型与被重写方法的返回类型可以不相同,但是必须是父类返回值的派生类( java5 及更早版本返回类型要一样,java7 及更高版本可以不同)
- 访问权限不能比父类中被重写的方法的访问权限更低。例如:如果父类的一个方法被声明为 public,那么在子类中重写该方法就不能声明为 protected
- 父类的成员方法只能被它的子类重写
- 声明为 final 的方法不能被重写
- 声明为 static 的方法不能被重写,但是能够被再次声明
- 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为 private 和 final 的方法
- 子类和父类不在同一个包中,那么子类只能够重写父类的声明为 public 和 protected 的非 final 方法
- 重写的方法能够抛出任何非强制异常,无论被重写的方法是否抛出异常。但是,重写的方法不能抛出新的强制性异常,或者比被重写方法声明的更广泛的强制性异常,反之则可以
- 构造方法不能被重写
- 如果不能继承一个方法,则不能重写这个方法
-
overload:重载
- 被重载的方法必须改变参数列表(参数个数或类型不一样)
- 被重载的方法可以改变返回类型
- 被重载的方法可以改变访问修饰符
- 被重载的方法可以声明新的或更广的检查异常
- 方法能够在同一个类中或者在一个子类中被重载
- 无法以返回值类型作为重载函数的区分标准
区别 重载 重写 参数列表 必须不同 必须相同 返回类型 可以不同 相同或为其派生类 抛出异常 可以不同 可以减少,不能更多 访问权限 可以不同 可以放宽,不能更严
转型
-
向上转型 upcast
-
向上转型即父类引用指向子类对象,使该引用具有子类特性和父类共性
Son s = new Son(); Father f = s;
-
子类重写了父类的非静态方法,用
s
和f
访问时,实际调用的都是子类中的对应方法 -
静态方法不能被重写,但是子类可以声明同名方法,用
s
访问时,访问到的是子类成员,用f
访问时,访问到的是父类成员,这被称之为“隐藏”,并非覆盖 -
子类可以声明和父类相同的成员变量,且不会覆盖父类属性,这也是一种“隐藏”。在使用变量时,具体是父类还是子类的成员,取决于方法所在类
-
-
向下转型 downcast
使用强制类型转换
(Son)f
可以访问的子类的所有属性和方法
抽象类
- 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类
- 抽象类中可以有非抽象方法,但抽象方法一定在抽象类中
- 抽象类不能实例化对象,必须被继承
- 抽象方法必须被子类重写,除非子类也是抽象类
- 抽象类中的抽象方法只是声明,不包含方法体
- 构造方法、静态方法不能声明为抽象方法 ,因为静态方法是类的,抽象方法价值在于要被重写,而重写是基于对象的
接口
-
接口和类区别
- 类描述对象的属性和方法。接口则包含类要实现的方法
- 接口没有构造方法
- 接口不能用于实例化对象 ,但可以声明引用,实现多态
-
接口和抽象类
- 只能继承一个抽象类,但可以实现多个接口
- 接口中的成员变量是 public static final
- 接口中的方法是 public abstract ,不能有非抽象方法,抽象类可以
- 接口不能有静态代码块,抽象类可以
- 抽象类可以有静态方法,接口在 jdk8 之前不可以
-
接口特性
- 一个接口可以继承多个接口 ,不支持实现接口
- 接口中每一个方法也是隐式抽象的,接口中的方法会被隐式的指定为 public abstract
- 接口中可以含有变量,但是接口中的变量会被隐式的指定为 public static final 变量
- 接口中的抽象方法只是声明,不包含方法体
- 接口中的抽象方法必须被重写,除非实现类是抽象的
-
jdk8 接口新特性:
-
接口中能使用 default 修饰方法,称默认方法或扩展方法
默认方法可以有方法体,不一定要被重写
如果实现两个接口有同名的默认方法,则必须要在实现类中重写
-
接口中能使用静态方法,可以有方法体,使用方式接口名 . 方法名
-