面向对象编程的几个基本概念
Object
拥有一组状态( s t a t e state state,即 f i e l d s fields fields)和行为( b e h a v i o r behavior behavior,即 m e t h o d method method)。
Classes
每一个对象都有一个类用来描述其状态和行为,其中 M e t h o d s Methods Methods和 f i e l d s fields fields统称为 m e m b e r s members members(成员方法和成员变量)。
注:静态方法无法调用非静态成员(方法和变量),且该错误在编译阶段可被发现。
Interface
- 一个接口可以扩展( e x t e n d s extends extends)其他接口,一个类可以实现( i m p l e m e n t s implements implements)多个接口。
封装(encapsulation)和信息隐藏(information hiding)
可以在不妨碍调用者的情况下,在后期将私有变为公有,但不能进行相反操作!
Overriding(覆盖/重写)
-
即子类重新实现父类中的方法,要求方法名称、参数、返回值都与父类中被重写的方法一致,且方法可见度(visibility)只能增强不能减弱。(编译阶段报错)
错误代码:
class Book { protected int getPrice() { return 30; } } public class ComputerBook extends Book { int getPrice() { return 10; } // error }
-
子类可以通过super关键字调用父类中被重写的方法。(父类中其余未被重写的方法可以通过super关键字调用,也可以直接调用。)
注:调用父类的构造方法时,必须是构造方法的第一行,否则编译阶段会报错。
正确调用方式举例:
public class cat extends animal { private int age; private String color; public cat(int age, String color) { super(age); // must be the first statement of the construct this.color = color; } /* other methods... */ }
-
final修饰符
- A final field:一旦初始化后不能再次被赋值的变量。
- A final method:不能被子类重写的方法。
- A final class:不能被继承的类。
多态(Polymorphism)的三种类型
Ad hoc polymorphism——Overloading(方法重载)
Overloading(重载) | Overriding(重写) | |
---|---|---|
参数列表 | 必须改变 | 不能改变 |
返回值 | 可以改变 | 不能改变 |
抛出异常 | 可以改变 | 可以减少或者消除异常,不能抛出新的或者更广泛的检查性异常 |
调用 | 实际被调用的版本在编译阶段(at compile time)由引用类型(reference type)决定 | 实际被调用的是哪一个版本的方法在运行时(at runtime)由对象类型(object type)决定 |
例子:
class Animal {
public void eat() {
System.out.println("I'm a animal. I like eating everything!");
}
}
class Horse extends Animal {
public void eat(String food) {
System.out.println("I'm a horse. I like eating " + food);
}
public void eat() {
system.out.println("I'm a horse. I like eating grass!");
}
}
Parametric polymorphism——Generic programming(泛型编程)
-
Parametric polymorphism(参数多态性):指方法针对多种类型时具有同样的行为,此时可用统一的类型表达多种类型。
-
类中如果声明了一个或多个泛型变量,则为泛型类。
class ClassName <T,E,...> { private T var; ... }
普通类中的泛型方法:
public class GenericTest { public void normalMethod(...){...} public <T> T genericMethod(...) { T var; ...; } }
泛型类中的泛型方法:
class GenericTest<T> { // 下面的T同所在类的类型变量一致,show1不是泛型方法 public void show1(T t) { System.out.println(t.toString()); } // 下面的E是新的类型变量,只适用于此方法,show2是泛型方法 public <E> void show2(E t) { System.out.println(t.toString()); } // 下面的T是新的类型变量,同类的类型变量无关(即使名字一样) // show3是泛型方法 public <T> void show3(T t) { System.out.println(t.toString()); } }
-
静态方法不能使用所在泛型类定义的泛型变量,如果静态方法要使用泛型的话,必须将静态方法也定义成泛型方法。
-
类型擦除:Java中的泛型,只在编译阶段有效。在编译过程中,正确检验泛型结果后,会将泛型的相关信息擦出,并且在对象进入和离开方法的边界处添加类型检查和类型转换的方法。也就是说,泛型信息不会进入到运行时阶段。所以不能使用 i n s t a n c e o f instanceof instanceof来检查泛型的类型。
Subtyping polymorphism
即一个变量名字可以代表多个类的实例(子类型)。
- java中的子类型一定要确保其规格说明不弱于超类型。
- java只支持单继承,但支持多实现。