java类的构造顺序

public class test {public static void main(String[] args) {B b = new B("b");   //实体化一个B的对象b 使用了B(String )构造函数 B bb = new B("bb");//实体化了一个B的对象b }
}class B {public B(String b1) {System.out.println(b1);}static {System.out.println("初始化静态语句块");}
}

执行结果:

初始化静态语句块
b
bb

可以看到初始化静态语句块输出只有一次并且在第一个执行
 在类内部,对于成员变量,如果在定义的时候没有进行显示的赋值初始化,则Java会保证类的每个成员变量都得到恰当的初始化:

  1)对于 char、short、byte、int、long、float、double等基本数据类型的变量来说会默认初始化为0(boolean变量默认会被初始化为false);

  2)对于引用类型的变量,会默认初始化为null。
    当程序执行时,需要生成某个类的对象,Java执行引擎会先检查是否加载了这个类,如果没有加载,则先执行类的加载再生成对象,如果已经加载,则直接生成对象。

  在类的加载过程中,类的static成员变量会被初始化,另外,如果类中有static语句块,则会执行static语句块。static成员变量和static语句块的执行顺序同代码中的顺序一致。记住,在Java中,类是按需加载,只有当需要用到这个类的时候,才会加载这个类,并且只会加载一次。在生成对象的过程中,会先初始化对象的成员变量,然后再执行构造器。也就是说类中的变量会在任何方法(包括构造器)调用之前得到初始化,即使变量散步于方法定义之间。
  
 

public class Main {public static void main(String[] args) {B b = new B("b");   //实体化一个B的对象b 使用了B(String )构造函数B bb = new B("bb");//实体化了一个B的对象b}
}class B {public B(String b1) {System.out.println(b1);}{System.out.println("初始化静态语句块");}
}

输出结果:

初始化静态语句块
b
初始化静态语句块
bb

结论:非静态语句快被执行了两次 注意这里去掉语句块的大括号会报错

public class test {public static void main(String[] args) {B b = new B();}
}class B {public B() {System.out.println("b loaded");}C c = new C();}class C {public C() {System.out.println("c loaded");}
}

以上运行结果为:

c loaded
b loaded

c 在b之前生成 说明成员变量优先被初始化

下面是继承相关的语法

class Person {public Person() {}
}class Man extends Person {public Man() {}
}

类Man继承于Person类,这样一来的话,Person类称为父类(基类),Man类称为子类(导出类)。如果两个类存在继承关系,则子类会自动继承父类的方法和变量,在子类中可以调用父类的方法和变量。在java中,只允许单继承,也就是说 一个类最多只能显示地继承于一个父类。但是一个类却可以被多个类继承,也就是说一个类可以拥有多个子类。

  1.子类继承父类的成员变量

  当子类继承了某个类之后,便可以使用父类中的成员变量,但是并不是完全继承父类的所有成员变量。具体的原则如下:

  1)能够继承父类的public和protected成员变量;不能够继承父类的private成员变量;

  2)对于父类的包访问权限成员变量,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承;

  3)对于子类可以继承的父类成员变量,如果在子类中出现了同名称的成员变量,则会发生隐藏现象,即子类的成员变量会屏蔽掉父类的同名成员变量。如果要在子类中访问父类中同名成员变量,需要使用super关键字来进行引用。

  2.子类继承父类的方法

  同样地,子类也并不是完全继承父类的所有方法。

  1)能够继承父类的public和protected成员方法;不能够继承父类的private成员方法;

  2)对于父类的包访问权限成员方法,如果子类和父类在同一个包下,则子类能够继承;否则,子类不能够继承;

  3)对于子类可以继承的父类成员方法,如果在子类中出现了同名称的成员方法,则称为覆盖,即子类的成员方法会覆盖掉父类的同名成员方法。如果要在子类中访问父类中同名成员方法,需要使用super关键字来进行引用。
注意:隐藏和覆盖是不同的。隐藏是针对成员变量和静态方法的,而覆盖是针对普通方法的

构造器的继承:

 
 

public class test {public static void main(String[] args) {B b = new B();}
}class B {public B() {System.out.println("b loaded");}public B(String b1) {System.out.println("B " + b1 + " loaded");}public B(String b1, String b2) {System.out.println("B " + b1 + " " + b2 + " loaded");}
}class C extends B {public C(String a) {System.out.println(a);;}
}

如果将B的无参构造其注释去掉会报错
当子类重新定义父类继承的有参构造方法时 父类必须要有无参构造方法
如果父类的没有无参构造方法则必须使用super

public class test {public static void main(String[] args) {C c = new C("c");}
}class B {/* public B(){System.out.println("b loaded");} */public B(String b1) {System.out.println("B " + b1 + " loaded");}public B(String b1, String b2) {System.out.println("B " + b1 + " " + b2 + " loaded");}
}class C extends B {public C(String a) {super("m");  //super语句必须在构造器的第一句  这里也可以是super("c","d")System.out.println(a);;}
}

运行结果

B m loaded
c

super()调用了父类的有参参构造方法:B(String b1);
如果使用super("c","d")则调用父类的方法B(String b1,String b2);

super.成员 的用法

要注意的是早使用super.之前要使用超类型的构造器

public class test {public static void main(String[] args) {C c = new C("c", "c");}
}class B {String b = "10";/* public B(){System.out.println("b loaded");} */public B(String b1) {System.out.println("B " + b1 + " loaded");}public B(String b1, String b2) {System.out.println("B " + b1 + " " + b2 + " loaded");}
}class C extends B {public C(String a) {super("m", "3");System.out.println(a);;}public C(String a1, String a2) {super("superb:" + "  ");//当调用超类型构造器后可以在这里调用父类的成员变量System.out.println(super.b);}
}

一道题


public class test {public static void main(String[] args) {E e = new E();}
}class C {public C(String cString) {System.out.println(cString + " constructor");}
}class D {private C c = new C("c");public D() {System.out.println("D constructor");}
}class E extends D {private D d = new D();public E() {System.out.println("E constructor");}
}

输出结果

c constructor
D constructor
c constructor
D constructor
E constructor

如果将class E extends D{...}更改为class E{..}

public class test {public static void main(String[] args) {E e=new E();}
}class C {public C(String cString) {System.out.println(cString + " constructor");}
}class D {private C c = new C("c");public D() {System.out.println("D constructor");}
}class E extends D {private D d = new D();public E() {System.out.println("E constructor");}
}

输出结果为
c constructor
D constructor
E constructor

可以发现少了两次输出 因此该小题第一段代码的实际的传递过程如下:

new E();//需要构造E 先构造E的父类D

构造父类D要先构造父类的成员c
所以调用C();输出了一次c constructor
继续构造D 调用D的构造方法D(); 输出D constructor
D构造结束后构造E
先构造E的成员d
d是D的对象 要实例化D 先构造D的成员c
new C("c");//调用了C的构造方法 输出c constructor
//回到
D d=new D();//输出constructor D 这时d也构造完毕
最后 调用E();方法构造e 结束

下面是验证

public class test {public static void main(String[] args) {E e = new E();F f = new F();}
}class C {public C(String cString) {System.out.println(cString + " constructor");}
}class D {private C c = new C("c");public D() {System.out.println("D constructor");}
}class E extends D {private D d = new D();public E() {System.out.println("E constructor");}
}class F extends D {public F() {System.out.println("F constructor");}
}

输出结果:
c constructor
D constructor
c constructor
D constructor
E constructor
c constructor
D constructor
F constructor
总结:先有父类后有子类 现有成员后有构造
每一次继承前都会把父类的方法和成员构造一次

感谢作者海子 原文地址http://www.cnblogs.com/dolphin0520/p/3803432.html

转载于:https://www.cnblogs.com/Salaku/p/5203937.html

java基础1--继承相关推荐

  1. 第二十八节:Java基础-进阶继承,抽象类,接口

    前言 Java基础 - 进阶继承,抽象类,接口 进阶继承 class Stu {int age = 1; } class Stuo extends Stu {int agee = 2; } class ...

  2. Java基础篇--继承(inherit),多态(Polymorphism)

    Java基础篇--继承(inherit),多态(Polymorphism) 1. 继承概述 1.1 什么是继承 1.2 为什么要使用继承 1.3 继承的特点 1.4 继承的优点 2. 组合设计模式 2 ...

  3. Java基础:继承、多态、抽象、接口

    第一讲    继承 一.继承概述 1.多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那么多个类无需再定义这些属性和行为,只要继承那个类即可. 2.通过extends关键字可以实现类与类的 ...

  4. Java 基础(继承)

    继承 基础 1. 继承的特点 2. super关键字 3. 继承中变量访问特点(就近原则) 4. 继承中成员方法访问特点 5. 继承中构造访问特点 为什么子类中所有构造方法默认都会访问父类无参构造方法 ...

  5. java基础:继承的使用

    一.继承的使用 1.什么是继承 2.继承的设计规范 3.继承的内存原理 test.java package Test;public class test {public static void mai ...

  6. Java基础08 继承

    继承(inheritance)是面向对象的重要概念.继承是除组合(composition)之外,提高代码重复可用性(reusibility)的另一种重要方式.我们在组合(composition)中看到 ...

  7. 11. Java基础之继承

    在<Think in java>中有这样一句话:复用代码是Java众多引人注目的功能之一.但要想成为极具革命性的语言,仅仅能够复制代码并对加以改变是不够的,它还必须能够做更多的事情.在这句 ...

  8. java基础 通过继承Thread类和实现Runnable接口创建线程

    java 创建线程 Java中,线程也是一种对象,但不是任何对象都可以成为线程. 只有实现了Runnable接口或继承了Thread类的对象才能成为线程. 继承Thread类 //格式: class ...

  9. Java基础复习——继承机制

    一.写在前面 1.基本作用 代码复用,更重要的就是有了继承机制后才会有后面的"方法重写"和"多态机制". 2.语法格式 //Student类继承了Person类 ...

  10. java基础之继承补充和抽象类

    继承的补充和抽象类 1.子类和父类中出现了同名的变量该如何访问?(super) 使用super关键字可以直接指定父类空间 格式: super.成员变量 访问成员变量的时候特点: 如果所指定的空间找不到 ...

最新文章

  1. 2022最新!基于深度transformer的时间序列异常检测模型
  2. Linux C编程--临时文件
  3. Java多线程:线程安全和非线程安全的集合对象
  4. 已知矩阵 matlab,在MATLAB中,已知矩阵A,那么A(:,2:end)表示
  5. 7个免费强大的Ajax文件管理器
  6. JS----贪吃蛇游戏
  7. NHibernate源码分析开篇
  8. 【算法大赛直播周】如何赋予机器更多“想象力”?《计算广告》作者刘鹏带你解密深度学习
  9. 计算机各单位间转换(位,字节,进制间转换)
  10. 云计算作业001-电脑配置
  11. 面向对象三大特性——多态
  12. node js npm grunt安装,elasticsearch-head 5.X安装
  13. java连接数据库增删改查公共方法
  14. React-native设置全局函数globle【适用于有组件嵌套时】
  15. 使用Python找丑数
  16. 图像标记img的alt属性
  17. win10系统崩溃怎么修复_系统崩溃!win10系统修复和数据恢复方法总结
  18. java中not equal_Java ObjectUtils.notEqual方法代码示例
  19. 自己的邮箱还有在用吗,还安全吗?
  20. mysql的primary key_MySQL Primary Key约束

热门文章

  1. Linux-0.00 代码解析(四)
  2. Spring学习总结一
  3. 【跨平台网络抓包神器のtcpdump】ubuntu下编译tcpdump开源抓包工具
  4. 白话详细解读(四)-----FCN
  5. hdu1754(树状数组求最值问题)
  6. MDM9x35MDM9x35启动流程简介
  7. Android7.0 PowerManagerService(1) 启动过程
  8. 理解Android Java垃圾回收机制
  9. mysql批量加逗号_批量插入数据到数据库的方式
  10. [CODEVS 1050] 棋盘染色 2