java的三大特性:

  • 继承
    java的单继承模式,只能有一个父类,与接口不同,你可以实现多个接口;可以将继承看作是遗传关系,子代继承了父亲的基因,但是由于基因突变或者自身的学习又拥有他自己的特性,父亲可能有多个后代,每个后台都继承了父亲的基因,那么父亲就基因就可以看作他们的共同特性,这就是继承,保留父类的某些方法和属性,同时也可以有自己的方法和属性,父类为他们提供共同特性,,这样设计就大大提高了代码的利用率;接口可以把他看作是一种技能,你每实现一个接口就相当于你学习了以一种技能,这就是接口.
  • 封装
    对某一事物的相同特性进行抽取
  • 多态
    java的多态是java语言特性中最具代表性的特性之一,也是区别于很多面向过程语言和其他语言的重要依据,说了这么多,也不晓得多态是个啥玩意儿,接下来就让我用一个栗子来解释一哈
class Father{
int age = 40;
void eat(){
System.out.println("我需要吃饭");
   }
void work(){
System.out.println("我要上班");
   }
}

class Son extends Father{
int age = 18;
void work(){
System.out.println("我要上学");
   }
void play(){
System.out.println("我要玩游戏");
   }
}

public class Test{
public static void main(String[] args){
Father f = new Son();
System.out.println(f.age);//结果为40
f.eat();//我需要吃饭
f.work();//我要上学
f.play();//编译失败
   }
}

以上的栗子可以用一句话来概括:
编译看父类,运行看子类;很多人也是这么记的,但是这样记也会存在一些问题.比如说什么编译需要看父类,而运行看子类?我们知道就是指的方法嘛.那为什么方法需要编译看父类,运行看子类呢?是不是所有的方法都是这样呢?带着这些疑问,我觉得我们有必要好好探究一下java中的多态指的是什么,又是根据什么原理实现的?
方法调用涉及到绑定机制,所谓绑定就是方法与方法主体建立的一种关系.在java中的方法调用实现的是动态绑定(后期绑定),c中实现的静态绑定(前期绑定)

前期绑定:

就是在编译时期就已经将方法与实体进行绑定了,也就是说在编译过程中就晓得这个方法是属于哪个对象的了

后期绑定:

在编译时期是不知道该方法是属于哪个对象的,但是编译器还是会做简单的安全性检查,看看在我声明的这个引用对象中是否存在该方法,如果不存在就通过不了编译器;注意这里,我们会对该声明的引用对象做基础的安全性检查,但是编译器不会也不可能知道该方法究竟是由哪个对象调用的,这需要在运行时期,通过java中的方法调用机制判断到底是基类调用还是子类调用方法,找到实体对象,调用该方法,至于java中的方法调用机制是怎样实现的?虚拟机提取对象的实际类型的方法表;虚拟机搜索方法签名;调用方法
会通过实际对象计算出一个值存储在对象中,在通过虚拟机对比该值,判断是否是同一类型,是,就调用该对象的方法了
当然也不是所有方法都实行的后期绑定,当然所有的属性肯定都不是后期绑定,属性和下列一些特定修饰的方法属于前期绑定
1.被final修饰的方法,我们都知道被final修饰的方法是不能被重写的,也就是说他是惟一的不能改值,因此java中被final修饰的方法就会告诉编译器我不会被重写,所以你帮我直接绑定吧.将方法声明为final类型,一是为了防止方法被覆盖,二是为了有效地关闭java中的动态绑定
2.被static修饰的方法,被static修饰的方法可以被类名直接调用,也是属于类的,直接与类绑定,不需要找实际对象
3.被private修饰的方法,实际上就是final,只不过是隐式的,private的方法只能被本类使用,很明显不能被继承也不能被重写,因此也就跟本类绑定在一起了
4.构造器,构造器也不能被继承

如果一个方法不可被继承或者继承后不可被覆盖,那么这个方法就采用的静态绑定。

多态实现的具体过程:

1:编译器检查对象的声明类型和方法名
假设我们调用x.f(args)方法,并且x已经被声明为C类的对象,那么编译器会列举出C类中所有的名称为f的方法和从C类的超类继承过来的f方法
2:接下来编译器检查方法调用中提供的参数类型
如果在所有名称为f的方法中有一个参数类型和调用提供的参数类型最为匹配,那么就调用这个方法,这个过程叫做“重载解析”。
3:当程序运行并且使用动态绑定调用方法时,虚拟机必须调用同x所指向的对象的实际类型相匹配的方法版本。