1. 继承的概念

  继承在本职上是特殊——一般的关系,即常说的is-a关系。子类继承父类,表明子类是一种特殊的父类,并且具有父类所不具有的一些属性或方法。

2. 继承中的初始化顺序

  从类的结构上而言,其内部可以有如下四种常见形态:属性(包括类属性和实例属性)、方法(包括类方法和实例方法)、构造器和初始化块(包括类的初始化块和实例的初始化块)。对于继承中的初始化顺序,又具体分为类的初始化和对象的初始化。

类初始化:

  在jvm装载类的准备阶段,首先为类的所有类属性和类初始化块分配内存空间。并在类首次初始化阶段中为其进行初始化,类属性和类初始化块之间的定义时的顺序决定了其初始化的顺序。若类存在父类,则首先初始化父类的类属性和类初始化块,一直上溯到Object类最先执行。

对象初始化:

  在new创建对象时,首先对对象属性和初始化块分配内存,并执行默认初始化。如果存在父类,则先为父类对象属和初始化块先分配内存并执行初始化。然后执行父类构造器中的初始化程序,接着才开始对子类的对象属性和初始化块执行初始化。

  调用顺序:父类的类属性和类代码块-->子类的类属性和类代码块-->父类的对象属性和代码块-->父类的构造函数-->子类的对象属性和代码块-->子类的构造函数

3、举例说明

//先静态初始化并且只有一次!!然后构造代码块!!再构造方法!!
//声明一个继承自父类的子类时,先把父类的构造代码块及构造方法初始化然后初始化子类的构造代码块和构造方法 class Parent {
public static String p_StaticField = "父类--静态变量";
public String p_Field = "父类--变量";
// 代码块 // 构造函数 public Parent() {
System.out.println("父类--构造器");
}
{
System.out.println(p_Field);
System.out.println("父类--初始化块");
} // 静态初始化块
static {
System.out.println(p_StaticField);
System.out.println("父类--静态初始化块");
}
} public class StaticBlock extends Parent {
public static String s_StaticField = "子类--静态变量";
public String s_Field = "子类--变量";
{
System.out.println(s_Field);
System.out.println("子类--初始化块");
} // 静态初始化块
static {
System.out.println(s_StaticField);
System.out.println("子类--静态初始化块");
} public StaticBlock() {
System.out.println("子类--构造器");
} public static void main(String[] args) {
System.out.println("-------------------");
new Parent();
System.out.println("-------------------");
new StaticBlock();
}
}
/**Output
* 父类--静态变量
父类--静态初始化块
子类--静态变量
子类--静态初始化块
-------------------
父类--变量
父类--初始化块
父类--构造器
-------------------
父类--变量
父类--初始化块
父类--构造器
子类--变量
子类--初始化块
子类--构造器
*/

注:

1. 在对象初始化阶段,属性和方法均针对子类可以从父类继承过来的属性和方法而言,一般而言,都是针对父类中非private而言的。因为private修饰的为父类所特有的,子类没有继承过来,当new子类时,无须为其分配空间并执行初始化。当然了,父类的构造器子类也是不继承过来的,但构造器另当别论。

2. 类的初始化只执行一次,当对同一个类new多个对象时,类属性和类初始化块只初始化一次。

4、注意构造函数中的多态问题

  在父类构造函数内部调用具有多态行为的函数将导致无法预测的结果,因为此时子类对象还没初始化,此时调用子类方法不会得到我们想要的结果。

class Glyph {
void draw() {
System.out.println("Glyph.draw()");
}
Glyph() {
System.out.println("Glyph() before draw()");//
draw();
System.out.println("Glyph() after draw()");//
}
} class RoundGlyph extends Glyph {
private int radius = 1;// RoundGlyph(int r) {
radius = r;//
System.out.println("RoundGlyph.RoundGlyph(). radius = " + radius);//
} void draw() {
System.out.println("RoundGlyph.draw(). radius = " + radius);//
}
} public class PolyConstructors { public static void main(String[] args) {
new RoundGlyph(5); }
} /**
Glyph() before draw()
RoundGlyph.draw(). radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(). radius = 5
*/

java中构造代码块、方法调用顺序问题的更多相关文章

  1. Java中构造代码块的使用

    例子1 public class Client { { System.out.println("执行构造代码块1"); } { System.out.println("执 ...

  2. Java中四大代码块的运行顺序(附code)

    验证证的方法是写code.例如以下: public class test { static class A { public static String name = "hello" ...

  3. Java中四大代码块的执行顺序(附code)

    验证证的方法是写code,如下: public class test { static class A { public static String name = "hello"; ...

  4. 【Java基础】2、Java中普通代码块,构造代码块,静态代码块区别及代码示例

    Java中普通代码块,构造代码块,静态代码块区别及代码示例.Java中普通代码块,构造代码块,静态代码块区别及代码示例 执行顺序:静态代码块>静态方法(main方法)>构造代码块>构 ...

  5. Java 中静态代码块初始化问题测试

    Java 中静态代码块初始化问题测试 原创 情况一:变量是 static final 修饰的"编译期常量",如 public static final String a = &qu ...

  6. Java中普通代码块,构造代码块,静态代码块执行顺序

    //执行顺序:(优先级从高到低.)静态代码块>mian方法>构造代码块>构造方法. 其中静态代码块只执行一次.构造代码块在每次创建对象是都会执行. 1 普通代码块 1 //普通代码块 ...

  7. java中静态代码块,构造代码块,以及构造方法的执行顺序

    写了许久的代码,却把一些基础的东西都给忘了,今天无聊就顺手写了个,然后测试下,发现跟我记忆中的竟然有些出入,作为一个两年的开发,我感觉自己很失败啊. 父类pojo: public class Pojo ...

  8. Java中普通代码块,构造代码块,静态代码块区别及代码示例

    //执行顺序:(优先级从高到低.)静态代码块>mian方法>构造代码块>构造方法. 其中静态代码块只执行一次.构造代码块在每次创建对象是都会执行. 1 普通代码块 1 //普通代码块 ...

  9. 关于java中普通代码块、构造代码块与静态代码块

    1.普通代码块 public static void main(String[] args) { /*普通代码块: *直接定义在在方法或语句中出现”{普通代码的执行语句}“的就称为普通代码块. *普通 ...

随机推荐

  1. 一些常见的“功能性”JS事件

    ————————倒序上升———————— (2)给一些 保存.提交 按钮,添加 防止重复提交 事件(常见一例) $("#submitRank").attr("disabl ...

  2. 自己练习的一个小的demo的时候a标签关于href链接的问题

    一.Js的几种调用方法(参考总结的) 1.a href="javascript:js_method();" 这是常用的方法,但是这种方法在传递this等参数的时候很容易出问题,而且 ...

  3. 通过重写request.getParameter方法来解决中文乱码问题。

    在原生servlet的商城项目中,BeanUtils.populate方法封装不上注册的参数. 已知BeanUtils.populate方法是封装不上date对象的,于是自定义了一个转换器用来封装Da ...

  4. python网络编程(UDP+广播)

    UDP广播案例,一端发送,多端接受: 发送端: # UDP广播案例 from socket import * from time import sleep # 设定目标地址 dest=('176.21 ...

  5. Java探针

    使用java代理来实现java字节码注入 使用JavaSsist可以对字节码进行修改 使用ASM可以修改字节码 使用Java代理和ASM字节码技术开发java探针工具可以修改字节码 备注:javass ...

  6. redis学习步骤

    Redis简介 redis全称REmote DIctionary Server,是一个由Salvatore Sanfilippo写的高性能key-value存储系统,其完全开源免费,遵守BSD协议.R ...

  7. Openflow协议详解

    http://www.h3c.com/cn/d_201811/1131080_30005_0.htm# 1 OpenFlow背景 转发和控制分离是SDN网络的本质特点之一 .在SDN网络架构中,控制平 ...

  8. div嵌套,常见左右分类栏目

    最终效果图如下: html代码如下: <div class="smalItem"> <div class="leftnav"> < ...

  9. select默认显示

    select默认显示第一个option,但大部分需求都是显示一个请选择,点击后在显示option的内容. 就像上图一样 但如果正常写的话会是像下面这样显示 请选择也会显示在下拉款里面,这样就很不友好 ...

  10. classLoader和Class.forName的区别

    public class ClassLoaderOrClassForName{ public static void main(String[] args) throws ClassNotFoundE ...