`
avaj
  • 浏览: 237629 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

[原]关于Java基础的一道题目

阅读更多
下面代码的结果是什么:

java 代码
  1. public class Test {
  2. private static Test test = new Test();
  3. public static int num1;
  4. public static int num2=0;
  5. private Test(){
  6. num1++;
  7. num2++;
  8. }
  9. public static Test getInstance(){
  10. return test;
  11. }
  12. public static void main(String[] args) {
  13. Test test = Test.getInstance();
  14. System.out.println(test.num1);
  15. System.out.println(test.num2);
  16. }
  17. }


这道题目咋看很简单,就是考察java初始化的顺序,但是很容易做错(我就做错了),结果应该是1、0

按照java初始化的顺序:首先静态初始化,然后定义初始化,然后是构造函数初始化,很简单吗,于是乎没张脑子般就写出了结果:1、1

分解一下这段代码执行的过程:
java 代码
  1. Test test = Test.getInstance();

java虚拟机看到需要用到Test了,于是开始满世界的找寻Test,黄天不负有心人,它终于找到了Test.class,然后开始加载......

然后要对Test打扮一番,好让她出去见人啊,于是开始初始化:

初始化顺序的总规则:

首先静态初始化,然后定义初始化,然后是构造函数初始化;

静态分为两种:
1、静态的成员变量
2、静态代码块 static{}

一般来说首先初始化静态类变量,然后初始化静态代码块。

如果某个类有父类:
那么初始化顺序是:
1、对父类进行静态初始化(初始化父类的静态成员变量或者静态代码块)
2、对子类进行静态初始化(初始化父类的静态成员变量或者静态代码块)
3、对父类进行定义初始化(初始化父类的成员变量)
4、对父类进行构造函数初始化
5、对子类进行定义初始化(初始化子类的成员变量)
6、对子类进行构造函数初始化

注意:jvm只在首次使用某个类的时候对其类变量进行一次初始化!

回到正题,jvm初始化Test的时候也是按照上面的顺序进行的:
1、ClassLoader加载Test.class,我自己理解这个时候Test.class中的三个静态变量已经被装载进内存,并分别赋予了初始值
null,0,0 (不知道这样理解对不对)
2、按照顺序对Test.class进行静态初始化,注意这里只对所有显示初始化的变量进行初始化!没有显示初始化的变量不再进行 初始化!比如num1没有被显示的初始化,不再参与这个初始化过程(不知道这个理解对不对)
所以首先初始化的是:
private static Test test = new Test();
3、初始化test变量的时候调用了Test类的构造函数,在Test构造函数中对两外两个静态变量num1、num2进行了++操作,这个 时候num1和num2的初始值应该都是默认值0!
这个时候num1和num2的值都是1
4、完成了对静态变量test的初始化后开始初始化num2,这个时候num1=1,但是num2=0!!

如果把代码改为:
java 代码
  1. public class Test {
  2. public static int num1;
  3. public static int num2 = 0;
  4. private static Test test = new Test();
  5. private Test() {
  6. num1++;
  7. num2++;
  8. }
  9. public static Test getInstance() {
  10. return test;
  11. }
  12. public static void main(String[] args) {
  13. Test test = Test.getInstance();
  14. System.out.println(test.num1);
  15. System.out.println(test.num2);
  16. }
  17. }

结果就是1、1了!
因为按照顺序,先初始化了num2,后初始化test!

1、装载Test.class
2、给类变量分配空间,赋予初始值
test = null (指向null)
num1 = 0
num2 = 0
3、开始初始化显示赋值的变量(test、num2)
1)初始化num2,将num2赋值为0
2)初始化test
(1)对类Test进行初始化,因为类变量只初始化一次,所以这里不再需要对test进行初始化了
(2)Test没有实例变量,所以不需要初始化实例变量
(3)对Test进行构造函数初始化,对num1和num2进行++操作
(4)初始化完毕,在堆区开辟内存空间存储Test的实例。
3)这个时候num1 = 1,num2 = 1

把代码改为:

java 代码
  1. public class Test {
  2. private static Test test = new Test();
  3. public int num1;
  4. public int num2 = 0;
  5. private Test() {
  6. num1++;
  7. num2++;
  8. }
  9. public static Test getInstance() {
  10. return test;
  11. }
  12. public static void main(String[] args) {
  13. Test test = Test.getInstance();
  14. System.out.println(test.num1);
  15. System.out.println(test.num2);
  16. }
  17. }

结果也是1、1

1、装载Test.class
2、给类变量分配空间,赋予初始值
test = null (指向null)
num1 = 0
num2 = 0
3、开始初始化显示赋值的变量(这里是test,因为num1和num2都不是静态的)
1)初始化test
(1)按照初始化顺序,构造Test的时候首先初始化类变量,因为类变量只初始化一次,
所以这里不再需要对test进行初始化了
(2)进行定义初始化,初始化num1 和 num2
(3)对Test进行构造函数初始化,对num1和num2进行++操作
(4)初始化完毕,在堆区开辟内存空间存储Test的实例。
3)这个时候num1 = 1,num2 = 1

参考一篇不错的文章:
http://www.ibm.com/developerworks/cn/java/j-lo-clobj-init/
分享到:
评论

相关推荐

    《Java编程基础》课后习题答案(原创)

    在《Java编程基础》课程中,学习者会接触到一系列的核心...每一道题目都是对理论知识的实践检验,通过调试和解决问题,有助于形成良好的编程习惯和问题解决技巧。对于初学者来说,这份习题答案是一份宝贵的参考资料。

    java基础题-百马百担问题

    在Java编程领域,"百马百担问题"是一道经典的逻辑与算法题目,它源于中国古代的智力谜题,旨在考察程序员的逻辑思维能力和解决问题的能力。在这个问题中,我们需要使用Java来设计一个解决方案,以体现Java语言的基础...

    最新JAVA编程题全集(50题及答案)

    综上所述,这四道编程题目都是学习和练习Java基础知识、逻辑思维和算法设计的优秀材料。通过对这些问题的解决,开发者不仅能够加深对Java语言的掌握,还能够提升自己在软件开发过程中的问题分析和解决能力。在面对...

    关于c,java算法的练习题

    ### 关于C、Java算法的练习题解析 #### 练习题概述 这份文档提供了48道关于算法的练习...每一道题目的解答都需要综合运用条件语句、循环结构、数学运算等多种编程技术,对于提高编程能力和逻辑思维能力具有重要意义。

    java算法练习试题

    【程序 8】这是一道关于字符串处理和循环的问题。输入一个数字a,计算一系列数字的和,直到达到指定次数。关键在于计算每个项的值,可以使用字符串拼接或数学公式来实现。 【程序 9】完数是其因子之和等于自身的数...

    Java初学者基本习题50道

    【Java初学者基本习题50道】是一个适合Java初学者练习编程技能的集合,包含了基础的算法和逻辑思维题目。这些习题旨在帮助学习者巩固语法知识,提高解决问题的能力。 1. **兔子问题**(斐波那契数列): 这是一道...

    剑指Offer(java版)全部运行通过

    在《剑指Offer》(Java版)中,有一道题目要求在一个特殊的二维数组中查找一个整数是否存在。这个特殊的二维数组具有以下特点: - 每一行都按从左到右递增的顺序排序; - 每一列都按从上到下递增的顺序排序。 #### ...

    2020年春学期《Java程序设计语言》期末复习练习题.docx

    【Java程序设计语言】期末复习练习题涵盖了多个Java编程的核心知识点,...这些练习题覆盖了Java基础到进阶的诸多知识点,是全面复习Java编程的好材料。通过解决这些问题,可以巩固和提升对Java语言的理解和应用能力。

    2013第四届蓝桥杯-预赛真题-Java本科-B组考生须知.pdf

    对于每一道题目,都需要仔细阅读题目描述,理解题目要求,不限制解决问题的方法。在提交答案时,务必遵循规定,确保答案的准确性与完整性,以提高得分的可能性。 在准备此类比赛时,参赛者应熟练掌握Java语言基础,...

    ACM.rar_ACM_ACM Hwang .p_ACM java_pku 1689 rubbery_ppt

    "ACM java_pku 1689 rubbery_ppt" 提到的可能是关于 Java 语言在解决 ACM 比赛问题中的应用,特别是针对北京大学(PKU)的一道编号为1689的题目 "rubbery" 的解题策略或解析,PPT 格式意味着是以演示文稿的形式呈现。...

    java-leetcode题解之第147题对链表进行插入排序.zip

    在本压缩包中,我们关注的是一个Java编程相关的学习资源,特别是一道来自LeetCode的题目——第147题“对链表进行插入排序”。LeetCode是一个知名的在线编程挑战平台,它提供了一系列的算法问题,帮助开发者提升编程...

    java笔试题

    以下是针对每一道题目所涉及的核心知识点的详细解析: ### 1. 多态与方法重载 题目描述了两个类`A`和`B`,其中`B`继承自`A`。`B`类重载了`A`类中的`getNumber`方法,但参数类型不同。这涉及到Java中的方法重载概念...

    java-leetcode题解之第86题分隔链表.zip

    这是一道涉及链表操作的算法问题,主要考察开发者对链表的理解以及解决问题的能力。让我们深入探讨这个题目及其解题策略。 ### 题目概述 在LeetCode的第86题中,给定一个单链表,其中的元素按升序排序,将其分成k...

    2014年最新Java笔试题及答案.docx

    4. 这是一道关于匿名内部类的问题。代码创建了一个匿名内部类,重写了`equals`方法,使其始终返回`true`。当调用`o.equals("Fred")`时,实际上调用了这个重写后的`equals`方法,所以返回`true`。答案是B:`True`。 ...

    sun公司scjp考试题

    SCJP(Sun Certified Programmer for the Java 2 Platform, Standard Edition)是Oracle公司(原Sun公司)推出的Java程序员认证考试,旨在验证考生对于Java语言的基础知识和编程能力。这个认证对于那些希望进入Java...

    开发面试题

    下面将对每一道题目进行详细解析。 ### 题目一:Java水平定位 #### 题目描述: 1. Java水平定位。 2. 给定 `int a = 10`,计算经过以下操作后 `a` 的值: - `a = a / 2;` - `a = a / 3;` - `a = a * 2.89;` ##...

    华为秋招_多数组合并问题.doc

    总之,这道题目涉及了Java基础、数据结构(ArrayList)的运用、字符串处理以及简单的算法设计。解题思路清晰,代码可读性好,但需要注意的是,对于大规模数据,可能需要考虑更高效的数据结构和算法,例如使用链表...

    SCJP模拟器

    4. **答案解析**:对于每一道题目,模拟器会提供正确答案和详细的解释,帮助考生理解错误之处,巩固知识点。 5. **成绩统计**:模拟器会记录每次模拟考试的成绩,分析考生的强项和弱点,为复习提供参考。 6. **...

Global site tag (gtag.js) - Google Analytics