继承
class 父类 {
}
class 子类 extends 父类 {
}
- 子类拥有父类非private的属性,方法。
- 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
- 子类可以用自己的方式实现父类的方法。
- Java的继承是单继承
- 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系)。
- 所有的类都是默认继承于 java.lang.Object
super
可以通过super关键字实现对父类成员的访问。
- 调用父类的构造方法;
- 调用父类的方法;
- 访问父类的数据域。
this
this关键字是指向自己的一个引用。
final
- final类:不能被继承
- final方法:不能被子类重写
构造函数
父类的构造函数不能被继承。
子类在使用构造器初始化的时候一定会先调用父类的构造器,显式地或隐式地:
- 如果父类有无参构造器,那么子类构造器在执行的时候会默认调用该无参构造器,而不用显式的调用
- 如果父类没有无参构造器或者想要调用父类的有参构造器,需要在子类构造器的第一行显式地使用super来调用:
super();
或
super(参数列表);
静态方法中不能使用 super 关键字。
overload
重载(overloading) 是在一个类里面可以存在多个同名方法。
- 被重载的方法必须改变参数列表(参数个数或类型或顺序不一样);
- 被重载的方法可以改变返回类型;
- 被重载的方法可以改变访问修饰符;
- 被重载的方法可以声明新的或更广的检查异常;
- 方法能够在同一个类中或者在一个子类中被重载。
- 无法以返回值类型作为重载函数的区分标准。
override
重写是子类对父类的允许访问的方法的实现过程进行重新编写, 返回值和形参都不能改变。
- 参数列表、返回类型必须完全与被重写方法的相同;
- 访问权限不能比父类中被重写的方法的访问权限更低。
例如:如果父类的一个方法被声明为public,那么在子类中重写该方法就不能声明为protected。 - 声明为final的方法不能被重写。
- 声明为static的方法不能被重写,但是能够被再次声明。
- 子类和父类在同一个包中,那么子类可以重写父类所有方法,除了声明为private和final的方法。
- 子类和父类不在同一个包中,那么子类只能够重写父类的声明为public和protected的非final方法。
- 重写方法不能抛出新的检查异常或者比被重写方法申明更加宽泛的异常。
例如: 父类的一个方法申明了一个检查异常 IOException,但是在重写这个方法的时候不能抛出 Exception 异常,因为 Exception 是 IOException 的父类,只能抛出 IOException 的子类异常。 - 构造方法不能被重写。
- 如果不能继承一个方法,则不能重写这个方法。
当需要在子类中调用父类的被重写方法时,要使用super关键字:
class Animal{
public void move(){
System.out.println("动物可以移动");
}
}
class Dog extends Animal{
public void move(){
super.move(); // 应用super类的方法
System.out.println("狗可以跑和走");
}
}
public class TestDog{
public static void main(String args[]){
Animal b = new Dog(); // Dog 对象
b.move(); //执行 Dog类的方法
}
}
动物可以移动
狗可以跑和走
多态
多态是同一个行为具有多个不同表现形式或形态的能力。
多态就是同一个接口,使用不同的实例而执行不同操作。
多态存在的三个必要条件:
- 继承
- 重写
- 父类引用指向子类对象
比如:
Parent p = new Child();
当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,再去调用子类的同名方法。
public static void main(String[] args) {
Animal a = new Cat();
a.eat(); // 调用的是 Cat 的 eat
Cat c = (Cat)a; // 向下转型
c.work(); // 调用的是 Cat 的 work
}
这整个过程被也称为虚函数调用,该方法被称为虚函数。
虚函数:当从父类中继承的时候,虚函数和被继承的函数具有相同的签名。但是在运行过程中,运行系统将根据对象的类型,自动地选择适当的具体实现运行。虚函数是面向对象编程实现多态的基本手段。
在Java语言中, 所有的方法默认都是”虚函数”. 只有以关键字 final 标记的方法才是非虚函数. 以下是 Java 中虚方法的一个例子:
public class Animal {
public void eat() { System.out.println("I eat like a generic Animal."); }
public static void main(String[] args) {
List<Animal> animals = new LinkedList<Animal>();
animals.add(new Animal());
animals.add(new Wolf());
animals.add(new Fish());
animals.add(new OtherAnimal());
for (Animal currentAnimal : animals) {
currentAnimal.eat();
}
}
}
public class Wolf extends Animal {
public void eat() { System.out.println("I eat like a wolf!"); }
}
public class Fish extends Animal {
public void eat() { System.out.println("I eat like a fish!"); }
}
public class OtherAnimal extends Animal {}
输出:
I eat like a generic Animal.
I eat like a wolf!
I eat like a fish!
I eat like a generic Animal.
抽象类
用abstract关键字来标识抽象类与抽象方法。
抽象类不能被实例化,如果被实例化,就会报错,编译无法通过。
只有抽象类的非抽象子类可以创建对象。抽象方法只是声明,不包含方法体
public abstract double computePay();
- 包含抽象方法的类一定要声明为抽象类
- 任何子类必须重写父类的抽象方法,除非这个子类也是抽象类。
- 构造方法,类方法(用static修饰的方法)不能声明为抽象方法。
封装
封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。
要访问该类的代码和数据,必须通过严格的接口控制。
封装的优点:
1. 良好的封装能够减少耦合。
2. 类内部的结构可以自由修改。
3. 可以对成员变量进行更精确的控制。
4. 隐藏信息,实现细节。
在java中如何实现封装:
- 修改属性的可见性来限制对属性的访问(一般限制为private)
public class Person {
private String name;
private int age;
}
- 对每个值属性提供对外的公共方法访问,也就是创建一对赋取值方法,用于对私有属性的访问
public class Person{
private String name;
private int age;
public int getAge(){
return age;
}
public String getName(){
return name;
}
public void setAge(int age){
this.age = age;
}
public void setName(String name){
this.name = name;
}
}
采用 this 关键字是为了解决实例变量(private String name)和局部变量(setName(String name)中的name变量)之间发生的同名的冲突。
此时要访问类中的private数据只能通过public的set/get方法来访问。
接口
接口是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,除非此类为抽象类。
接口与类的区别:
- 接口不能用于实例化对象。
- 接口没有构造方法。
- 接口中所有的方法必须是抽象方法。
- 接口不能包含成员变量,除了 static 和 final 变量。
- 接口不是被类继承了,而是要被类实现。
- 一个类只能继承一个类,但是可以实现多个接口
接口与抽象类的区别:
- 抽象类可以有构造方法 接口不行
- 抽象类可以有普通成员变量 接口没有
- 抽象类可以有非抽象的方法 接口中的方法全都是抽象方法
- 抽象类的访问类型都可以 接口只能是 public abstract
- 一个类可以实现多个接口 但只能继承一个抽象类
声明接口
[可见度] interface 接口名称 [extends 其他的类名] {
// 声明变量
// 抽象方法
}
- 接口是隐式抽象的,当声明一个接口的时候,不必使用abstract关键字。
- 接口中每一个方法也是隐式抽象的,声明时同样不需要abstract关键子。
- 接口中的方法都是公有的。
interface Animal {
public void eat();
public void travel();
}
实现接口
当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。
类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。
class MammalInt implements Animal
- 类在实现接口的方法时,不能抛出强制性异常,只能在接口中,或者继承接口的抽象类中抛出该强制性异常。
- 类在重写方法时要保持一致的方法名,并且应该保持相同或者相兼容的返回值类型。
- 如果实现接口的类是抽象类,那么就没必要实现该接口的方法。
接口继承
一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用extends关键字,子接口继承父接口的方法。
public interface Sports
{
public void setHomeTeam(String name);
public void setVisitingTeam(String name);
}
public interface Football extends Sports
{
public void homeTeamScored(int points);
public void visitingTeamScored(int points);
public void endOfQuarter(int quarter);
}
java中的类不允许,但是接口允许多继承:
public interface Hockey extends Sports, Event