继承与多态
@since
在Java源代码中,代表当前方法需要java几的版本使用
main方法
main方法只是一个静态的,有String[] 做参数的,没有返回值的方法。 它的特殊性在于java可以把main方法作为程序的入口
String对象的特点
String对象最重要的特点:不可变(immutable)。String用来存储字符的数据是private的,而且不提供任何修改内容的方法,所以String对象一旦生成,其内容就是完全不可能被修改的
StringBuilder
StringBuilder是一个非常方便的用来拼接和处理字符串的类,和String不同的是,他是可变的
StringBuilder的方法,都是返回this自引用,所以我们可以和jquery对象的方法一样,一直点下去
继承
继承
- 继承是一种is - a的关系
- 继承的语法是类名后面使用extends 加 要继承的类名
- JAVA中只允许一个类有一个直接的父类,即所谓的单继承。但是一个类可以有多个子类
- 子类继承了父类的方法和属性,使用子类的引用可以调用父类的共有方法与共有属性。不能继承私有方法和属性。可以继承public和缺省(如何子类和父类的包名是一样,是可以继承缺省的,如果包名不一样是不可以的)
- 就好像子类的引用可以一物二用,既可以当作父类的引用使用,又可以当做子类的引用使用
组合
组合是一种has - a的关系
与继承相似,都是解决代码复用的功能。
语法是在子类中,加一个需要重用代码的类的属性,然后使用的时候,初始化复用类,实现代码的复用
###继承与组合的选择。
- 继承是is - a的关系,组合是has - a的关系。如何选择,就看X到底是Y的一种,还是只是组合了Y。举个例子就是:手机到底是手电筒的一种,还是组合了一个可以当手点的闪光灯。
- 继承不是组合,继承不只是为了简单的拿来父类的属性和方法。如何仅仅如此,那么组合也能做到,优先考虑组合,因为继承可能会带来其他问题
- 与组合相比,继承更像是“融合”。所谓即合二为一,可以互相影响,父类影响子类,子类也可以影响父类(重写)
覆盖(继承的终极奥义)
通过使用和父类**方法签名一样,而且返回值也必须一样(返回值可以是父子关系),可以让子类覆盖掉父类的方法。也就是说,子类并不是只把父类的方法拿过来,而且可以通过覆盖来替换掉其中不适合子类的方法
- 子类的修饰符类型要大于或者等于父类修饰符类型
- 子类抛出的异常要小于或者等于父类
- 子类的返回值默认要小于等于父类返回值
class A{}
class B extends A{}
abstract class Animal
{
String name;
public Animal() {
}
public Animal(String name) {
this.name=name;
}
abstract A run();
}
class Dog extends Animal
{
@Override
public B run() {
return new B();
}
}
B是A的子类
Dog类是Animal的子类,Dog类继承了Animal类以后要实现其父类的抽象方法run();父类抽象方法中run()的返回值类型时A类的,所以子类Dog在实现父类的run()方法时,返回值要小于等于父类的返回值类型,即可以是A类的对象,也可以是A子类的对象,比如B类的对象;
覆盖可以覆盖父类的方法。同一个方法,不同的行为,这就是多态
super
- super可以调用父类的方法和属性(必须满足访问控制符的控制)。
- super的用法就像是一个父类的引用。但是它本质并不是父类的引用,所以super和this自引用是不一样的。
super调用父类构造方法
- 使用super调用父类的构造方法,必须是子类构造方法的第一个语句(和this一样)
- super调用构造方法,不可以使用super访问父类的属性和方法,不可以使用子类的成员变量和方法
- 可以使用静态变量和方法
重载和重写的区别
/ | 重写(Overriding) | 重载(Overloading) |
---|---|---|
类的数量 | 父子类、接口和实现类 | 本类 |
方法名称 | 一致 | 一致 |
参数类型 | 一定不能修改 | 必须修改 |
返回类型 | 一定不能修改 | 可以修改 |
异常 | 可以减少或删除,但不能扩展 | 可以修改 |
多态
覆盖是用引用调用方法。重载是调用别的方法用引用作为参数
继承中父类与子类的引用赋值关系
- 子类引用可以给父类赋值,父类引用可以指向子类对象以及子类的子类对象
- 引用类型决定了能进行哪些操作(比如父类引用指向子类对象,那么这个引用只能调用父类的方法,不能调用子类的), 实际执行的是指向对象的内容
- 父类引用指向子类对象,那么可以将父类引用强制转换成子类对象
关于继承中多态的模式
- 父类引用指向子类对象,可以调用只在父类的方法(继承)
- 父类引用指向子类对象,可以调用子类覆盖了父类的方法(覆盖,多态)
- 父类引用指向子类对象,在1和2这两种情况下。如果这个方法的代码中又调用了别的方法,那么会遵循这个规则。举个例子,如果父类有m1,m2两个方法。子类覆盖了m2方法。那么如果调用m1,则m1中调用的m2会是子类中定义的m2
动态多态:覆盖
在继承覆盖环境中, 引用类型决定了能进行哪些操作,实际执行的是指向对象的内容
静态多态:重载
- 重载调用哪个方法,和参数的引用类型相关,和引用实际指向的类型无关。如无完全匹配,则会根据继承关系,沿着参数类型向根节点查找(静态方法和成员方法,重载找方法的顺序是一样的)
- 因为调用时参数类型是确定的,所以,在编译期间就可以明确的知道哪个方法会被调用。如果有多重可能,则会编译错误。
- 引用本身是null也没关系,确定调用哪个方法只需要引用的类型。这叫做静态多态。
instanceof 操作符
可以判断一个引用指向的对象是否是某一个类型或者其子类
继承里面的静态方法
(环境:类名.静态方法)子类可以定义和父类签名一样的静态方法,返回值也必须一样,否则会错误。也可以不定义,不定义的话,子类的引用调用的就是父类的这个静态方法
访问修饰符
final
- final修饰类:不可以被继承
- final修饰方法:不可以被子类覆盖
- final修饰变量:不可以被赋值, 只能在声明的时候或者构造函数里面赋值,并且两个中 只能赋值一次,同时赋值会报错。
- final修饰引用变量:其引用不能重新指向一个新的对象,但是通过引用可以修改对象的内容