在Java中,创建一个对象,到底代码执行顺序是什么样子的。通过编写一个类,测试一下就知道了。
请看如下类:
package com.ant.order;
public class TestOrder {
private static int p1 = staticPrintInt("P....初始化父类静态属性", 100);
private int p2 = instancePrintInt("P....初始化父类实例属性", 200);
static{
System.out.println("P....执行父类静态代码段");
}
{
System.out.println("P....执行父类非静态代码段");
}
public static int staticPrintInt(String str, int value){
System.out.println(str);
return value;
}
public int instancePrintInt(String str, int value){
System.out.println(str);
return value;
}
public void publicPrintProperty(){
System.out.println("P....Parent public 方法");
System.out.println("P....p1 =" + p1);
System.out.println("P....p2 =" + p2);
}
private void privatePrintProperty(){
System.out.println("P....Parent private 方法");
System.out.println("P....p1 =" + p1);
System.out.println("P....p2 =" + p2);
}
public TestOrder(){
System.out.println("P....父类构造器");
publicPrintProperty();
privatePrintProperty();
}
public static void main(String[] args){
TestOrder p;
System.out.println("========================");
p = new TestOrder();
}
}
该类执行后会有如下结果:
P....初始化父类静态属性
P....执行父类静态代码段
========================
P....初始化父类实例属性
P....执行父类非静态代码段
P....父类构造器
P....Parent public 方法
P....p1 =100
P....p2 =200
P....Parent private 方法
P....p1 =100
P....p2 =200
从上面的输出可以看出,使用直接父类不是Object的类创建对象过程是:
a、加载类
1、为父类静态属性分配内存并赋值
2、执行父类静态代码段
3、为子类静态属性分配内存并赋值
4、执行子类静态代码段
b、创建对象
1、为父类实例属性分配内存并赋值
2、执行父类非静态代码段
3、执行父类构造器
5、为子类实例属性分配内存并赋值
6、执行子类非静态代码段
7、执行子类构造器
在这个过程里面,我们会注意到两段工作都是先处理父类,然后再处理子类的。也就是子类重复了一遍父类的工作。
这个过程里面可能会遇到一个特殊现象,那就是:
1、子类覆盖了父类中的某个方法。
2、父类构造器中调用到了该方法
3、在子类中,该方法访问到了只有子类才有的属性。
就像我们前面的代码中,
父类中的定义是:
public void publicPrintProperty(){
System.out.println("P....Parent public 方法");
System.out.println("P....p1 =" + p1);
System.out.println("P....p2 =" + p2);
}
子类中的定义是:
public void publicPrintProperty(){
System.out.println("C....Child public 方法");
System.out.println("C....c1 =" + c1);
System.out.println("C....c2 =" + c2);
}
其中,C2是只有子类才具有的属性,但是在父类构造器中却调用到了该方法。
也就是说,按照Java对象创建过程,当该方法被执行的时候C2还没有被初始化。
在这种情况下,Java会根据属性的类型不同,采用不同的缺省值进行处理。这也就是为什么父类构造器执行的时候C2=0,子类构造器执行的时候C2=2000的原因。
实际上,Java在处理创建子类对象的时候,在所有工作开始之前,先为继承层次中每个类的对象分配内存。然后在做其他工作。这样可以保证不管对象是否产生,起码属性已经先有了一个缺省值。
分享到:
相关推荐
本实验报告旨在探讨 Java 中的面向对象编程技术,涵盖类的定义、对象的创建、抽象类的定义、抽象方法的实现、接口的定义及其实现、类的继承、方法重写、多态性的应用等概念。实验要求学生掌握类的定义、对象的创建、...
标题中的“多出最优服务次序问题P116第七题java代码.zip”指的是一个关于计算机算法设计的项目,具体是王晓东所编著的《计算机算法设计与分析》第五版中的第116页第4-7题。这个问题通常涉及优化服务流程,可能与作业...
1. **Java 从代码到运行的全过程**:Java程序首先通过Java编译器(javac)编译成字节码(.class文件),然后由Java虚拟机(JVM)解释执行。JVM负责加载类、执行字节码并进行垃圾回收。 2. **虚拟机的工作机制**:...
为了使模拟的程序运行,可能还需要包含一个简单的解释器或虚拟机,能够执行Java字节码。 以上这些知识点构成了一个完整的Java模拟操作系统的基本框架。通过这样的模拟项目,开发者可以深入理解操作系统的工作原理...
关于java后根次序非递归遍历单栈方法,适用于任何类型。
Java程序的运行环境次序是从操作系统开始,通过Java运行时环境(JRE)或Java虚拟机(JVM)执行字节码,最后由硬件支持运行。开发者通过编写Java源代码,使用javac编译器将其编译成字节码,然后由JVM解释执行。 ...
(1)整体查询有两种显示方式:一是按加入序号次序显示,另一个是按姓名排序; (2)个别查询支持模糊查询,例如:输入“张”,则所有匹配的姓名中含“张”的均显示。 public class phonesystem extends Frame ...
本文将深入探讨Servlet的方法执行次序以及相关的API,帮助你更好地理解和运用这些关键功能。 首先,让我们了解Servlet生命周期中的主要方法: 1. **init()**:Servlet初始化时调用此方法。在Servlet实例化后,容器...
当使用String a1=“abc”的方式实例化数据时,栈空间会创建引用a1及在常量池中创建“abc”字符对象,当再次执行 String a2=“abc”语句时,则栈空间会创建引用a2,同时指常量池中的“abc”。当使用String a3=new ...
因为 Java 源程序经过编译生成字节码文件,它与平台无关,无论是 Windows、Mac OS 或 UNIX,只要计算机安装了能解释执行字节码文件的 Java 虚拟机就可以执行了。 三、字节码的概念 字节码是 Java 源程序经过编译...
Java 面试题是 Java 开发人员面试的必备知识,涵盖了 Java 基础知识、Java 框架、Java 集合框架、Java 多线程、Java 网络编程等方面的知识点。在本文中,我们将对 Java 面试题进行总结和分析,帮助读者快速掌握 Java...
java数据结构是计算机科学中研究非数值计算的程序设计问题中计算机的操作对象以及它们之间的关系和操作等等的学科。下面是java数据结构的知识点总结: 一、数据结构定义 数据结构是相互之间存在一种或多种特定关系...
在Java程序设计中,程序员首先创建源文件(`.java`),然后编译器将它们转化为字节码文件(`.class`)。字节码文件是平台无关的,可以在任何安装了Java虚拟机的平台上运行。 ### 14. 程序段执行后输出的结果 虽然...
1. 一个Java程序运行的环境次序是从操作系统开始,然后是Java运行时环境(JRE或JVM),接着是Java程序本身,最后是硬件。正确答案是A. 操作系统、Java程序、JRE/JVM、硬件。 2. Java程序中表达式优先级的问题。题目...
System.out.print("先根次序遍历二叉树:"); preorder(this.root); // 调用先序遍历方法 System.out.println(); } public void preorder(BinaryNode<T> p){ if (p != null) { System.out.print(p.data.toString...
但通常情况下,由于Java Bean是被容器所创建(如Tomcat)的,所以Java Bean应具有一个无参的构造器,另外,通常Java Bean还要实现Serializable接口用于实现Bean的持久性。Java Bean实际上相当于微软COM模型中的本地...