java创建继承类_【Java基础】java继承类怎么创建 - 收获啦

基本概念

q-32196.html

q-32196.html多态父类 p = new 子类(); 向上转型

变量shape可以引用任何Shape子类类型的对象,这叫多态,即一种类型的变量,可以一用多种实际类型对象。

对于变量shape,它就有两个类型,Shape,称之为shape的静态类型;类型Circle、Line、ArrowLine,称之为shape的动态类型。

在ShapeManager的fraw方法中,shapes[i].draw()调用的是其对应动态类型的draw方法,这称之为方法的动态绑定。

q-32196.html

q-32196.html继承和多态每个类有且只有一个父类,没有声明父类的,其父类为Object,子类继承了父类非privater的属性和方法,可以增加自己的属性和方法,以及重写父类的方法实现

new过程中,父类先进行初始化,可通过supper调用父类响应的构造方法,没有使用supper的情况下,调用父类的默认构造方法。

子类变量和方法与父类重名的情况下,可通过supper强制访问父类的变量和方法。

子类对象可以赋值给父类引用变量,这叫多态;实际执行调用的是子类实现的,这叫动态绑定。

q-32196.html

q-32196.html继承的细节

q-32196.html

q-32196.html构造方法子类可以通过super调用父类构造方法

如果子类没有使用super调用父类构造方法,则会自动调用父类构造方法。

如果父类不存在默认构造方法(存在有参构造,不存在默认的无参构造),那么子类必须在构造方法中通过super调用父类有参构造方法,否则编译错误。

下面代码,第一次输出为0,第二次输出为123,。

在new过程中,首先初始化父类,父类构造方法调用test()方法,test()方法被子类重写了,则调用的子类的test()方法,子类方法访问子类实例变量a,这个时候子类的实例变量的赋值语句和构造方法还没有执行,所以输出为0;

注:父类中调用可被子类重写的方法,是一种不好的实践,容易引起混淆,应该只调用private的方法。public class Base(){

public Base(){

test();

}

public void test(){

System.out.println(a);

}}public class Child extends Base(){

private int a = 234;

public Child(){

}

public void test(){

System.out.println(a);

}}1234567891011121314151617

q-32196.html

q-32196.html静态绑定Base是Child的父类,分别访问其类中定义的静态方法和静态成员变量以及实例变量时(同名)【说明:静态变量和静态方法一般通过类名直接访问,但也可以通过类的对象访问。】

通过b(静态类型Base)访问时,访问的是Base的变量和方法。

通过c(静态类型Child)访问时,访问的是Child的变量和方法。

上面两种情况称为静态绑定

静态绑定,即访问绑定到变量的静态类型。静态绑定在程序编译阶段即可,而动态绑定则要等到程序运行时

实例变量、静态变量、静态方法、private方法,都是静态绑定的。

q-32196.html

q-32196.html父子类型转换子类对象赋值给父类型的引用变量,这叫做向上转型。

父类型的变量赋值给子类型的变量,向下转型,【不一定转换成功】

一个父类的变量能不能转换为一个子类的变量,取决于这个父类变量的动态类型(即引用的对象类型)是不是这个子类或这个子类的子类。

判断一个父类的变量是否是某个子类的对象 :instanceof关键字。 A instanceof B

q-32196.html

q-32196.html继承访问权限protectedprotected可以被子类和通包类调用,可被子类重写。

q-32196.html

q-32196.html可见性重写重写方法时,一般不会修改方法的可见性,但重写时,子类方法不能降低夫父类方法的可见性。

父类public,子类public; 父类protected,子类protected或public

继承反应is-a的关系,子类对象也属于父类,子类支持父类对外的行为,子类对父类进行扩充。

q-32196.html

q-32196.html防止继承finalfinal关键字加在类上,无法被继承。

加方法上,无法被重写

加在变量上,为常量

q-32196.html

q-32196.html类继承的细节

q-32196.html

q-32196.html子类继承父类细节。

实例化子类对象时(new Child()时),父类子类静态代码块、实例化代码块、构造方法、运行顺序。父类静态代码块(仅一次)

子类静态代码块(仅一次)

父类实例化代码块

父类构造方法

子类实例化代码块

子类构造方法public class Base {

public static int s;

private int a;

static {

System.out.println("基类静态代码块,s:" + s);

s = 1;

}

{

System.out.println("基类实例代码块,a:" + a);

a = 1;

}

public Base(){

System.out.println("基类构造方法,a:" + a);

a = 2;

}

protected void step(){

System.out.println("base s: " + s + ", a:" + a);

}

public void action(){

System.out.println("start");

step();

System.out.println("end");

}}public class Child {

public static int s;

private int a;

static {

System.out.println("子类静态代码块,s:" + s);

s = 10;

}

{

System.out.println("子类实例代码块, a:" + a);

a = 10;

}

public Child(){

System.out.println("子类构造方法,a" + a);

}

protected void step(){

System.out.println("child s:" + s +",a :" + a);

}}

public static void main(String[] args) {

System.out.println("---new Child()");

Child c = new Child();

System.out.println("\n---c.action()");

c.action();

Base b = c;

System.out.println("\n---b.action()");

b.action();

System.out.println("\n---b.s:" + b.s);

System.out.println("\n---c.s:" + c.s);123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354

输出:基类静态代码块,s:0子类静态代码块,s:0---new Child()基类实例代码块,a:0基类构造方法,a1

子类实例代码块, a:0子类构造方法,a:10---c.action()start

child s:10,a :10end---b.action()start

child s:10,a :10end---b.s:1---c.s:10123456789101112131415161718192021

q-32196.html

q-32196.html对象创建过程分配内存

对所有实例变量赋默认值

执行实例初始化代码分配的内存包括本类和所有父类的实例变量,但不包括任何静态变量。

实例初始化代码的执行从父类开始,再执行子类的。

任何类执行初始化代码之前,所有的实例变量都已设置完默认值。

每个对象除了保存类的实例变量外,还保存着实际类信息的引用

q-32196.html

q-32196.html方法调用的过程

c.action();查看c的对象类型,找到Child类型,在Child类型中找action方法,发现没有,去父类中查找;

父类Base中找到方法action,开始执行action方法;

action先输出了start,然后发现需要调用step()方法,就从Child类型开始寻找step()方法;

在Child类型中找到了step()方法,执行Child中的step()方法,执行完后返回action方法;

继续执行action方法,输出end;

寻找执行的实例方法的时候,从对象的实际类型信息开始查找,找不到时去父类型信息中查找。

b.action();这句代码输出与c.action相同,称为动态绑定。

动态绑定实现机制时根据对象的实际类型查找要执行的方法,子类型中找不到的时候再查找父类。

如果继承层次比较深,调用效率会降低。因此使用一种称为虚放发表的方法优化调用的效率。

虚方法表,就是在类加载时为每个类创建一个表,记录该类的随想所有动态绑定的方法(包括父类的方法)及地址,但一个方法只有一条记录,子类重写了父类方法后只会保留子类的。

a194d531b7f26530a01b39bbb8ac421b.png

q-32196.html

q-32196.html变量访问的过程对变量的访问是静态绑定的,无论是类变量还是实例变量。

b.a访问的是Base类定义的实例变量a

c.a访问的是Child类定义的实例变量a

q-32196.html

q-32196.html继承优缺点

q-32196.html

q-32196.html继承破坏封装

继承可能破坏封装,而封装可以说是程序设计的第一原则。继承没有反映出is-a关系。封装?封装就是隐藏实现细节,提供简化接口

继承可能破坏封装:子类和父类之间可能存在着实现细节的依赖。

封装的破坏:

父类不能随意增加公开方法,因为给父类增加就是给所有子类增加。

子类可能必须要重写该方法才能确保方法的正确性。

对父类而言,让子类继承和种些方法,可能是哪个是随意修改内部实现的自由。

对子类而言,通过继承实现是没有安全保障的,因为父类修改内部实现细节,它的功能就可能会被破坏。

应对继承的双面性:给方法加final修饰符,父类就保留了随意修改这个方法内部实现的自由

给类加final,父类就保留了随意修改这个类实现的自由

优先使用组合而非继承使用组合可以抵挡父类变化对子类的影响,从而保护子类,应该优先使用组合

正确使用继承

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值