Java技术_基础技术(0003)_类执行顺序详解+实例(阿里面试题)+详细讲解+流程图

Java技术_基础技术(0001)_后台模拟调用action

Java技术_基础技术(0002)_中间件启动class加载顺序(以tomcat为例)

Java技术_基础技术(0003)_类执行顺序详解+实例(阿里面试题)+详细讲解+流程图

Java技术_基础技术(0004)_eclipse远程调试tomcat

基础技术:

对于java类各个成员的执行顺序,现拿出阿里的面试题作为样例(例子非常好,是用心出的题),在这里重新说明一下java类执行顺序的原则。

源码下载(包含题、结果、分析过程)

一、总体原则

列出执行顺序的原则(这里本人出了简化,比较明了。可能有漏的,请帮忙补充,但应付该实例足以):

 ==父类先于子类;

 
 ==静态先于非静态;
 
 ==变量和块先于构造方法;
 
 ==变量声明先于执行(变量赋值、块执行);(这一点是根据数据在内存中是如何存储的得出的,基本类型、对象、String均不一样,但是总结起来应该是这样)
 
 ==变量赋值与块优先级相同;
 
 ==同优先级的从上至下执行;

二、实例

直接上题(小马哥的阿里,问:system.out打印结果。这里我加上了行号,方便解说):

[java] view plain copy

 

  1. public class StaticTest {  
  2.   
  3.     public static int k = 0;// 1  
  4.     public static StaticTest s1 = new StaticTest("s1");// 2  
  5.     public static StaticTest s2 = new StaticTest("s2");// 3  
  6.     public static int i = print("i");// 4  
  7.     public static int n = 99;// 5  
  8.     public int j = print("j");// 6  
  9.   
  10.     {  
  11.         print("构造块");  
  12.     }// 7  
  13.   
  14.     static {  
  15.         print("静态块");  
  16.     }// 8  
  17.   
  18.     public static int print(String s) {  
  19.         System.out.println(++k + ":" + s + "\ti=" + i + "\tn=" + n + "\tprint");  
  20.         ++n;  
  21.         return ++i;  
  22.     }  
  23.   
  24.     public StaticTest(String s) {  
  25.         System.out.println(++k + ":" + s + "\ti=" + i + "\tn=" + n  
  26.                 + "\tStaticTest");  
  27.         ++i;  
  28.         ++n;  
  29.     }// 9  
  30.   
  31.     public static void main(String[] args) {  
  32.         new StaticTest("init");  
  33.     }  
  34. }  

三、执行结果

这里不废话,直接上结果(大家都可以去试一下,这里我加上了sysoN====,一会分析时候用来对看),这一部分内容在下载的代码里也有。结果如下:

[java] view plain copy

 

  1. /** 
  2.      *  
  3.      * 输出结果: 
  4.      *  
  5.      * syso1 ===="1:j       i=0     n=0     print" 
  6.      *  
  7.      * syso2 ===="2:构造块     i=1     n=1     print" 
  8.      *  
  9.      * syso3 ===="3:s1      i=2     n=2     StaticTest" 
  10.      *  
  11.      * syso4 ===="4:j       i=3     n=3     print" 
  12.      *  
  13.      * syso5 ===="5:构造块     i=4     n=4     print" 
  14.      *  
  15.      * syso6 ===="6:s2      i=5     n=5     StaticTest" 
  16.      *  
  17.      * syso7 ===="7:i       i=6     n=6     print" 
  18.      *  
  19.      * syso8 ===="8:静态块     i=7     n=99    <span style="white-space:pre">    </span>print" 
  20.      *  
  21.      * syso9 ===="9:j       i=8     n=100   <span style="white-space:pre">    </span>print" 
  22.      *  
  23.      * syso10===="10:构造块    <span style="white-space:pre">    </span>i=9        n=101   <span style="white-space:pre">    </span>print" 
  24.      *  
  25.      * syso11===="11:init   <span style="white-space:pre">    </span>i=10   <span style="white-space:pre">    </span>n=102  <span style="white-space:pre">    </span>StaticTest" 
  26.      */  

四、分析

一步一步按照上面的原则来分析,应该比较详细了,这一部分内容在下载的代码里也有。分析如下:

/**
====step1====首先声明StaticTest类的static变量并给与默认值。
*
* 故,执行1、2、3、4、5变量的声明。运行后变量如下:
*
* k=0; s1=null; s2=null; i=0; n=0; j未声明;
*
====step1 end====
*/
/**
====step2====变量声明完成后,为这些static变量赋值以及执行static块(赋值和块优先级一致,在前面的先执行).
*
* 故,执行1、2、3、4、5的赋值代码,8的块代码
*
========step2_1====当step2执行到2时,new了一个新的StaticTest对象.
* (此时2、3、4、5的赋值、8的代码都没执行,变量k被赋值为0,其余仍与step1中一致 )
* 这时,static变量已经声明(static变量是类属性,与对象无关),所以这里直接声明非static变量并给与默认值。
*
* 故,执行6变量的声明,运行后变量如下:
*
* k=0; s1=null; s2=null; i=0; n=0; j=0(s1的);
*
========step2_2====变量声明完成后,为这些非static变量赋值以及执行非static块。
*
* 故,执行6变量的赋值代码(syso1====k、n、i、j均+1),7的块代码(syso2====k、n、i均+1),运行后变量如下:
*
* k=2; s1=null; s2=null; i=2; n=2; j=1(s1的);
*
========step2_3====变量赋值、块执行完毕后,执行构造方法。
*
* 故,执行9构造方法(syso3====k、n、i均+1),运行后变量如下:
*
* k=3; s1=StaticTest对象; s2=null; i=3; n=3; j=1(s1的);
*
========step2_4====s1构造完毕后,继续执行3。同样是new一个新的StaticTest对象.
* 过程与step2_1至step2_3一致。
*
* 故,执行3(syso4====k、n、i、j(j=0)均+1;syso5====k、n、i均+1;syso6====k、n、i均+1),
* 运行后变量如下:
*
* k=6; s1=StaticTest对象; s2=StaticTest对象; i=6; n=6; j=1(s2的);
*
========step2_5====s2构造完毕后,继续执行4、5的赋值,为i和n赋值.
*
* 故,执行4(syso7====k、n、i均+1,i被重新赋值)、5(n被重新赋值)的赋值代码,运行后变量如下:
*
* k=7; s1=StaticTest对象; s2=StaticTest对象; i=7; n=99; j未声明;
*
========step2_6====static变量赋值完毕后,执行8的static块。
*
* 故,执行8(syso8====k、n、i均+1),运行后变量如下:
*
* k=8; s1=StaticTest对象; s2=StaticTest对象; i=8; n=100; j未声明;
*
====step2 end====
*/
/**
====step3====static变量及块完成后,声明非static变量并给与默认值.
*
* 故,执行6变量的声明。运行后变量如下:
*
* k=8; s1=StaticTest对象; s2=StaticTest对象; i=8; n=100; j=0(main的);
*
====step3 end====
*/
/**
====step4====非static变量声明完成后,为这些变量赋值以及执行非static块(赋值和块优先级一致,在前面的先执行)。
*
* 故,执行6的赋值代码(syso9====k、n、i均+1,j=++i),7的块代码(syso10====k、n、i均+1)。运行后变量如下 :
*
* k=10; s1=StaticTest对象; s2=StaticTest对象; i=10; n=102; j=9(main的);
*
====step4 end====
*/
/**
====step5====变量赋值、块执行完毕后,执行构造方法。
*
* 故,执行9构造方法(syso11====k、n、i均+1),运行后变量如下:
*
* k=11; s1=StaticTest对象; s2=StaticTest对象; i=11; n=103; j=9(main的);
*
====step5 end====
*/

五、执行流程图

以实例为准,绘制的图(原创图,请勿转载)。

原文地址:http://blog.csdn.net/ooppookid/article/details/42967353

时间: 2024-08-30 16:01:33

Java技术_基础技术(0003)_类执行顺序详解+实例(阿里面试题)+详细讲解+流程图的相关文章

UML技术_基础技术(0001)_常用UML绘制工具

UML技术_基础技术(0001)_常用UML绘制工具 基础技术: 本文介绍三种不同场合下最为常用的工具: 1.rational rose 专业级的工具,支持各种可视化建模,以及代码.结构的生成,包括数据库等等,而且拥有版本控制等功能,可以多人设计. 由于功能太多太全,产品过重,用起来不是很方便,一般国内项目慎重使用.而且收费! 下载地址:点击打开链接(这么大的东西还是放到新浪网盘上吧,百度网盘好用,但是容量太小) 2.starUML 轻量级的工具,不用安装,放到移动存储就可以用,移植也很方便.功

基于java涉及父子类的异常详解_java

java中的异常涉及到父子类的问题,可以归纳为一句话:子类的构造函数抛出的异常必须包含父类的异常,子类的方法可以选择抛出"范围小于等于"父类的异常或不抛出异常. 1. 为什么构造函数必须抛出包含父类的异常? 在<thingking in java>中有这么一段话: 异常限制:当覆盖方法时,只能抛出在基类方法的异常说明中列出的那些异常 异常限制对构造器不起作用,你会发现StormyInning的构造器可以抛出任何异常,而不必理会基类构造函数所抛出的异常.然而因为必须构造函数必

玩转JavaScript OOP - 类的实现详解_javascript技巧

概述 当我们在谈论面向对象编程时,我们在谈论什么? 我们首先谈论的是一些概念:对象.类.封装.继承.多态. 对象和类是面向对象的基础,封装.继承和多态是面向对象编程的三大特性. JavaScript提供了对象却缺乏类,它不能像C#一样能显式地定义一个类. 但是JavaScript的函数功能非常灵活,其中之一就是构造函数,结合构造函数和原型对象可以实现"类". 对象和类的概念 对象 "对象"是面向对象编程中非常重要的一个概念,一个对象是一个"东西"

使用Java构造和解析Json数据的两种方法(详解二)_java

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式.同时,JSON是 JavaScript 原生格式,这意味着在 JavaScript 中处理 JSON数据不须要任何特殊的 API 或工具包. 在www.json.org上公布了很多JAVA下的json构造和解析工具,其中org.json和json-lib比较简单,两者使用上差不多但还是有些区别.下面接着介绍用org.json构造和解析Json数据的方法

C++聚合关系类的构造函数的调用顺序详解_C 语言

如图,表示一个聚合关系 下面就用简单的代码来实现 #pragma once class Engine { public: Engine(); ~Engine(); }; Engine.h #include <iostream> #include "Engine.h" using namespace std; Engine::Engine() { cout << "调用构造函数:Engine()" << endl; } Engine

iOS开发:Cocoa—类与对象详解

我们可以在/usr/include/objc/objc.h 和 runtime.h 中找到对 class 与 object 的定义: typedef struct objc_class *Class; typedef struct objc_object { Class isa; } *id; Class 是一个 objc_class 结构类型的指针:而 id(任意对象) 是一个 objc_object 结构类型的指针,其第一个成员是一个 objc_class 结构类型的指针.注意这里有一关键的

iOS网络编程之四——请求类NSURLRequest使用详解

iOS网络编程之四--请求类NSURLRequest使用详解 一.引言         在前面几篇博客中,介绍了iOS开发中的网络编程相关内容并且介绍了常用了两个平行的网络框架NSURLSession和NSURLConnection.无论是NSURLSession类还是NSURLConnection类,其网络请求都是通过NSURLRequest类进行发起的,本篇博客将介绍NSURLRequest类的用法和其中请求属性的设置.         前几篇博客地址如下: 1.iOS网络框架介绍:http

JavaScript中定义类的方式详解_javascript技巧

本文实例讲述了JavaScript中定义类的方式.分享给大家供大家参考,具体如下: Javascript本身并不支持面向对象,它没有访问控制符,它没有定义类的关键字class,它没有支持继承的extend或冒号,它也没有用来支持虚函数的virtual,不过,Javascript是一门灵活的语言,下面我们就看看没有关键字class的Javascript如何实现类定义,并创建对象. 一.定义类并创建类的实例对象 在Javascript中,我们用function来定义类,如下: function Sh

python魔法方法-属性转换和类的表示详解_python

类型转换魔法 类型转换魔法其实就是实现了str.int等工厂函数的结果,通常这些函数还有类型转换的功能,下面是一些相关的魔法方法: •__int__(self) •转换成整型,对应int函数. •__long__(self) •转换成长整型,对应long函数. •__float__(self) •转换成浮点型,对应float函数. •__complex__(self) •转换成 复数型,对应complex函数. •__oct__(self) •转换成八进制,对应oct函数. •__hex__(s