版权声明:本文为博主原创文章,转载注明出处即可。 https://blog.csdn.net/bskfnvjtlyzmv867/article/details/86647879
多态调用
- 将 一个方法调用 和 一个方法主体 关联起来被称作绑定。绑定分为前期绑定与后期绑定,多态方法的具体调用依靠前期绑定是不行的,编译器不知道对象的具体类型无法具体调用,所以只能依靠后期绑定,也叫动态绑定、运行时绑定;
- Java除了
final
方法和static
方法(private
方法属于final
方法)之外,其他方法的调用默认就是后期绑定。final
方法意味着不想被子类覆盖,这样可以有效的“关闭”动态绑定,或者说告诉编译器不需要对其动态绑定,这样编译器会对final
方法调用生成更有效的代码(但实际上有效不到哪去,所以不要以优化性能特意加final
); - 子类是不继承父类的
static
变量和方法的,因为这是属于类本身的,所以说没有多态这一特性,但是子类是可以访问的。子类和父类中同名的static
变量和方法都是相互独立的,并不存在任何的重写的关系。public class Main { public static void haha() { System.out.println("hehe"); } } public class ExtendMain extends Main { // 不是重写 public static void haha() { System.out.println("haha"); } public static void main(String[] args) { Main h = new ExtendMain(); h.haha(); ExtendMain hh = new ExtendMain(); hh.haha(); } } // 输出 // hehe // haha
- 子类覆盖父类的方法,加上
final
也是覆盖,对于父类方法的调用是动态绑定,而对于子类final
方法的调用则直接前期绑定即可;public class Main { public void haha() { System.out.println("hehe"); } } public class ExtendMain extends Main { @Override public final void haha() { System.out.println("haha"); } public static void main(String[] args) { Main h = new ExtendMain(); h.haha(); // 动态绑定 ExtendMain hh = new ExtendMain(); hh.haha(); // 前期绑定 } } // 输出 // haha // haha
- 子类不会覆盖父类的私有方法,私有相当于
final
,因为对子类不可见,所以即使子类看似定义了像覆盖父类的方法,也不会发生多态; - 对于成员变量/域,也是没有多态的,任何域的访问操作都将由编译器解析,因此不会多态。
构造器与多态
- 构造函数其实相当于
static
的,因此也没有多态一说; - 子类对象构造器的调用顺序为:先自顶向下调用父类的构造器,然后按照声明顺序调用成员的初始化方法,最后再调用构造器的主体。当然,在第一步调用父类构造器的时候也要按着三步走;
- 看一个例子:
class Glyph { void draw() { System.out.println("Glyph draw"); } Glyph() { System.out.println("Glyph before draw"); draw(); System.out.println("Glyph after draw"); } } class SubGlyph { private int radius = 1; SubGlyph(int r) { radius = r; System.out.println("SubGlyph radius = " + radius); } void draw() { System.out.println("SubGlyph.draw radius = " + radius); } public static void main(String[] args) { new SubGlyph(5); } } // 输出 // Glyph before draw // SubGlyph.draw radius = 0 为什么等于0? // Glyph after draw // SubGlyph radius = 5