继承按照我们中文通俗的理解是不需要付出努力,就获得别人的能力或资产,比如继承父辈的家产,继承父辈的表达能力,继承父辈的外貌等等。在类里面的继承,可以理解不需要重新开发代码,就能复用父类的方法和域。
在继承关系里面,可以分为父类和子类,子类继承父类,那子类就有了跟父类一样对外的方法和属性,但是子类也可以拥有自己对外的方法和属性,就好比你继承了父辈的全部家产,但是还可以拥有属于自己的资产一样。所有继承是一个is-a的关系。java类继承用extends来表述继承关系。例如:class Manager extends Emloyee{}
子类除了可以继承父类方法以外,也可以覆盖父类方法,把这个覆盖父类方法的行为称之为override.值得注意的是,在覆盖方法时,允许子类覆盖方法的返回类型定义为原类型的子类型。例如:public class Employee{ public Employee getBuddy(){……} }//父类Employee
public class Manager extends Employee {
public Manager getBuddy(){……}
//子类override getBuddy方法,返回类型为原类型的子类型
}
--那么继承是如何实现,内部实现原理是怎么样的?
1、每个对象在调用方法的时候,实际上方法存在一个隐式参数,例如:Manager mg=new Manager();
mg.getBuddy(); //getBuddy实际上存在一个隐式参数,当前对象的引用,执行是会将对象引用传
进去,变成mg.getBuddy(mg);
2、每个类,虚拟机都会为每个类预先创建一个方法表(method table),用来记录所有方法所对应的内存地址。在调用方法的时候,直接去找方法对应的内存地址进行执行,如果是单纯的继承,相当于默认给子类创建一个跟父类类似的method table。
例如:Employee:
getName->Employee:getName()
getBuddy->Employee:getBuddy()
Manager:
getName->Employee:getName()
getBuddy->Manager:getBuddy()
因此,对于不同的子类对象调用子类方法时,会从子类方法表中,查询该方法的地址,如果子类覆盖父类方法,那么对应的方法的地址也被修改了,进而实现多态。
--如何阻止继承:
final,如果将类定义为final,那么该类就不能被其他类继承,值得注意的是,如果类被定义成final,其方法也自动被定义为final,但是属性域并没有被自动定义成final.