java 静态代码块 继承_详解Java中代码块和继承

概念

1、代码块

局部代码块

用于限定变量生命周期,及早释放,提高内存利用率

静态代码块

对类的数据进行初始化,仅仅只执行一次。

构造代码块

把多个构造方法中相同的代码可以放到这里,每个构造方法执行前,首先执行构造代码块。

2、继承

继承是已有的类中派生出新的类,新的类能够吸收已有类的数据属性和行为,并能扩展新的功能。

代码块的执行顺序

public class Test{

public String name;

public int age;

static{

System.out.println("这是静态代码块");

}

{

System.out.println("这是构造代码块");

}

public Test(){

System.out.println("这是无参构造函数");

}

public Test(String name,int age){

this.name = name;

this.age = age;

System.out.println("这是有参数构造函数");

}

}

class TestDemo{

public static void main(String args[]){

Test t1 = new Test();

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

Test t2 = new Test("funga",24);

}

}

大家思考下,在执行上面的main方法之后,打印出来的结果会是怎样的呢?

这是静态代码块

这是构造代码块

这是无参构造函数

------------------------------------

这是构造代码块

这是有参数构造函数

执行解析:当我们使用new Test()去创建Test类对象的时候,类加载器会加载Test类,加载的时候会执行静态代码块(如果有静态变量、静态方法也会被初始化),创建对象的时候,首先会执行构造代码块,然后执行无参构造函数。

当我们使用new Test()去创建Test类对象的时候,该类已经载入虚拟机,所以不会再执行静态代码块,但是构造代码块每次在创建对象之前都会执行,之后执行对象的构造函数。

继承

public class Father{

private String name;

public int age;

public static String SUCCESS = "成功";

public Father(String name,int age){

this.name = name;

this.age = age;

System.out.println("构造函数说:我叫" + name + ",我" + age + "了");

}

public static void say(String word){

System.out.println(word);

}

public void intr(){

System.out.println("我叫" + name + ",我" + age + "了");

}

}

public class Son extends Father{

}

class TestDemo2{

public static void main(String args){

Son s = new Son();

}

}

想想,我们执行上面main方法执行结果是什么呢?

解析:没错,编译就不会通过,为什么呢?因为子类只继承父类的默认构造函数,即无参数构造函数,当父类没有默认构造函数,子类不能从父类继承,所以,我们将子类作如下修改看看能否成功?

public class Son extends Father{

public Son(){};

}

这次,我们在子类中显示增加了一个无参数的构造方法,请问这样是否可以通过编译了呢?

解析:当我们编译的时候还是报错了,为什么呢?因为,子类构造函数中必须会调用父类的构造函数,如果没有显示调用,默认调用父类无参构造函数,这里父类没有无常构造,所以编译又报错了,所以,正确的写法,是通过super关键字,在子类构造方法中显示调用父类的有参构造方法。

public class Son extends Father{

public Son(){

super("funga",25);

};

public Son(String name,int age){

super(name,age);

}

}

下面我们来看看子类调用父类的变量和方法情况:

class TestDemo{

public static void main(String args[]){

Son s = new Son();

//下面这句是编译出错的,父类的私有成员变量(函数)是不能被继承的

// System.out.prinlnt(s.name);

System.out.println(s.age);

System.out.println(s.SUCCESS);

s.intr();

s.say("hahaha");

Son.intr();

}

}

解析:子类不能继承父类的私有变量和函数,所以也无法直接使用(调用)。父类的静态变量(函数),子类也也可以通过对象或者类调用。

代码块和继承

public class Fu{

static {

System.out.println("这是父类的静态代码块");

}

{

System.out.println("这是父类的构造代码块");

}

public Fu(){

System.out.println("这是父类的构造函数");

}

}

public class Zi extends Fu{

static {

System.out.println("这是子类的静态代码块");

}

{

System.out.println("这是子类的构造代码块");

}

public Zi(){

System.out.println("这是子类的构造函数");

}

}

/*

测试类

*/

class TestDemo{

public static void main(String args[]){

Zi z = new Zi();

System.out.println("--------------分割线-----------------");

Zi z2 = new Zi();

}

}

结合上面代码块执行原理和继承的知识,我们执行测试类,会得到怎样的输出结果呢?

分析:这次我们先分析,再执行看结果:

1、当通过new Zi()创建Zi类对象的时候,会加载Zi类,当加载Zi类的时候优先加载Fu类,那么就会执行Fu类的静态代码块,输出“这是父类的静态代码块”,继而加载Zi类,输出“这是子类的静态代码块”

2、当加载完Fu类和Zi类之后,创建Zi类对象的时候,会优先执行Fu类的构造代码块和构造方法,也就是会输出“这是父类的构造代码块”和“这是父类的构造函数”,之后执行自身的构造代码块和构造函数,输出“这是子类的构造代码块”和“这是子类的构造函数”

3、执行第二个new Zi()的时候,Fu类和Zi类都已经加载,所以静态代码块不会被执行。后面的步骤与上面2一样。所以,输出的结果应该是下面这样的:

这是父类的静态代码块

这是子类的静态代码块

这是父类的构造代码块

这是父类的构造函数

这是子类的构造代码块

这是子类的构造函数

--------------分割线-----------------

这是父类的构造代码块

这是父类的构造函数

这是子类的构造代码块

这是子类的构造函数

后记

实际开发中,我们不用这么折腾自己,弄的这么复杂,但是些知识点有必要理解,加深对Java技术的认识,懂了总比不懂要好,你说呢?

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值