`
zjf201172653
  • 浏览: 46488 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

java中静态块,静态属性,方法的加载顺序

阅读更多

java中静态块,静态属性,方法的加载顺序  转自http://blog.csdn.net/yufaw/article/details/7753669

 

这两天遇到几个类似的问题,就是一个程序到底是怎么运行的,而且这些问题很具有迷惑性,这里两个例子做分析( 实际上一切都在黑马的免费视频中有体现 ) !

问题一:如下代码的执行顺序是什么样的!一定理解:是执行的顺序(后面会给大家说一个误区)!

class Test
{

        int a = 5; 
        static int num = 4;                     //这是一个很简单的代码,但是你了解他的运行顺序吗
        Test()         

        }
        static {                                   // 那么可能你会有疑问,我该如何来去测试一下他们的执行顺序呢?
               
        }
        public static void main(String[] args){
                        
        }        
}

实际上你现在根本看不出来执行顺序,也很容易搞混淆,我们必须找出一种方便的手段去测试一下:

测试的方法:比如

static int num = 4; 这句代码,我们怎么知道他是不是执行了,可以这样写 static int num = 4; { system.out.println("执行了静态变量语句"); } 这样的话这段代码加载的时候,在控制台就能看到,是不是很方便!

接下来我们出发!--------->>
// 注意看,这里仅仅是一个普遍情况,特殊情况下面有总结:在下面的A ,B两种情况的总结非常的重要,一定要好好的看看! public classExten { static int num = 4; // 静态变量第二个 { num += 3; System.out.println("b"); } int a = 5;{ // 成员变量第三个 System.out.println("c"); } Exten() { // 类的构造函数,第四个加载 System.out.println("d"); } static { // 静态块,第一个加载 System.out.println("a"); } static void run() // 静态方法,调用的时候才加载// 注意看,e没有加载 { System.out.println("e"); } public static void main(String[] args) { new Exten(); }

一般顺序:静态块——>静态变量——>成员变量——>构造方法——>静态方法
1、静态代码块(只加载一次) 2、构造方法(创建一个实例就加载一次)3、静态方法需要调用才会执行,所以最后结果没有e


想知道顺序看看控制台!是不是一目了然了,

问题二:那么到这是不是已经完善了呢!请看下面问题很具有迷惑性!

 

  1. public class StaticInitTest {
  2. static int count = 2;      //定义静态变量(类变量)count,这个不是比较对象,下面的name是
  3. static String name = "我的黑马之路";     //定义静态变量
  4. static {              //通过静态初始化块为name变量初始化
  5. System.out.println("StaticInitTest的静态初始化块!");
  6. name = "黑马编程";
  7. }
  8. public static void main(String[] args) {
  9. System.out.println("count的值:"+StaticInitTest.count);
  10. System.out.println("name的值:"+StaticInitTest.name);
  11. }
  12. }
这是测试截图,请认真看看黑马程序员:JAVA中代码顺序,静态块-静态变量-成员变量-构造方法-静态方法,是如何加载的! - Budier_GreatMan - 黑马空间
 
黑马程序员:JAVA中代码顺序,静态块-静态变量-成员变量-构造方法-静态方法,是如何加载的! - Budier_GreatMan - 黑马空间
  • 你一看会发现就是啊,name的值改变了啊,这说明代码的执行改变了啊!
  • 实际上:刚才说了执行,什么是执行,什么是编译看明白自己就明白了!
  • 说实话,笔者研究这个问题一下午时间,为什么这么长时间,因为也没注意到这个问题,所以一直在深究内核的运作.....!
  • 下面我们看看为什么会出现这种问题把,为什么name的值会改变,是执行的顺序改变了吗!
  •    main方法中是什么,是不是只有打印语句,有没有操作上面的代码,没有把,其实是在不断的打印name这个静态对象的值

下面按前后顺序,分析谁在前,谁在后的执行结果 static { System.out.println("a静态块"); s = "我被编译了"; // 这里为什么不报错我们要理解Eclipse的编译顺序,从上到下依次编译,编译的时候就把所有的静态属性全部加载!

System.out.println(s);} // 这里你能获取到s吗? 系统会提示你,s还没有创创建,因为这里是第6行,你的对象在第8行才创建,编译不通过;

static String s = "你只是在打印我"; //这里才创建的String对象,按编译顺序s是多少?是不是变成了 "你只是在打印我"最终main函数中只是打印了s ,打印就是"你只是在打印我"

现在换位置:  static String s = "你只是在打印我" ; //编译通过先创建了String类型的s; s是多少?是不是"你只 是在打印我"

static { s = "我被编译了" ; System.out.println(s); //Eclipse从上到下依次编译,,不是执行,是编译,编译到这,这里s是谁 ?是不是"我被编译了" } 然后到这又把这个s直接打印了出来,打印结果肯定会变成,"我被编译了" !!

问题:有值就是执行过了吗?   
总结:因为main方法中都是打印语句,只是在-----打印编译后加载的值-----而已;

打印不打印,name和s的值都在那里!注意不注意,name和s都是静态的!编译加载而已!

static String s = "静态String"; { System.out.println("静态String"+s); }
static int a = 5;
{
s  = "非静态int";
System.out.println("静态int变量");
}//还要注意的问题就是,在a中到底有没有给s赋值,很显然s的值此时未变,new的时候才执行到,为什么,请看下面的大总结!

 

实际上,以上的所有问题加起来就得到的完整的答案,你如果看到了这里恭喜你,笔者费劲总结的最终的正确的结果就在下面:


先把内在的执行规律简述:

  •           静态变量这个问题是最不容易搞明白的问题,静态变量只加载一次,以后不论你怎么new不会再加载
  •           而且注意:静态块也是仅加载一次,
  •            静态变量后大括号内有代码的话,new一次执行一次。
  •            静态块加载的时候大括号内的语句就执行完毕,以后不会执行。

是不是比较复杂,光看特性就已经复杂了,这里有些的同学可能就会想了,那这两个的执行顺序是怎么样的呢,这里非常的迷惑人,因为各种情况你得到的测试结果可能都不一样
不过他们还是有顺序的,只不过分情况对待!

 


大补充:   
A、类的初始化顺序如下:
->1、为静态属性分配内存并赋值(后面大括号语句不执行,这里是初始化,只是添加变量和值) 
         或  执行静态代码块(立刻执行大括号里面的语句)
          为什么这样说呢,因为谁在前先加载谁,包括静态属性之间,和静态块之间的顺序,
          但是注意,虽然顺序都可以当第一,但是静态块、静态属性执行的东西完全不一样,怎么不一样,已经写上去了自己看
      (笔者注:这个问题,在花了很多时间的推敲后,最终有了答案,前后花了不少的时间去运行代码,修改各种情况,也有同学参与了进来,所以大家对我们付出的努力应该尊重啊)
->2、非静态属性分配内存并赋值
->3、构造方法(实际上这个先于非静态属性调用到,只是构造方法里面的语句暂停执行,等到非静态属性加载完才执行)
->4、执行非静态代码块 或 静态方法(都是调用了才加载)。



B、类的代码(大括号内的语句)执行顺序:   当你创建了对象的时候才会用到各个属性和变量对不对,这里就是这个顺序
->1、执行静态代码块(大括号包含的语句立刻执行,绝对是第一位的执行,没有能和它平级的)
->2、静态属性 (第二位执行
->3、为非静态属性分配内存并赋值(大括号内语句第三位执行)
->4、构造函数
->执行非静态代码块 或 静态方法(都是调用了才加载)。
  


这样的话是不是非常的清晰呢了!这才是所有代码加载的顺序啊,以后对于程序的执行就会有更深的理解了 !
分享到:
评论
1 楼 xiaoyao3857 2014-04-20  
"从接下来我们出发"下的第一个程序,总结的加载顺序不太对,静态块确实是第一个,但其后不一定是静态成员变量->成员变量,静态变量、成员变量谁在前、谁在后跟在程序声明的顺序有关

"    静态变量这个问题是最不容易搞明白的问题,静态变量只加载一次,以后不论你怎么new不会再加载
          而且注意:静态块也是仅加载一次,
           静态变量后大括号内有代码的话,new一次执行一次
           静态块加载的时候大括号内的语句就执行完毕,以后不会执行。"
还有大补充那块说得比较好

相关推荐

    java面试题静态加载顺序构造方法

    java面试题静态加载顺序构造方法 继承与static 面试题目如下:请写出程序执行完成之后的结果。 package extend; public class X { Y y=new Y(); static{ System.out.println("tttt"); } X(){ System....

    java 静态块实例块构造器调用

    Java编程语言中,类的初始化过程涉及到静态块(static block)、实例块(instance block)以及构造器(constructor)。这些块的执行顺序对于理解和编写复杂的Java程序至关重要,特别是在涉及继承关系时。下面我们将...

    构造函数与静态块的执行顺序

    这是因为静态块是在类加载时执行的,而类的加载顺序是按照继承层次自上而下进行的,所以父类的静态块总是先于子类的静态块执行。 2. **构造函数的执行**:接下来,父类的构造函数会被调用,然后才是子类的构造函数...

    java类中静态域、块,非静态域、块,构造函数的初始化顺序

    2. **静态块执行**:所有静态块按它们在源代码中出现的顺序依次执行。 3. **非静态域初始化**:所有非静态域按它们在源代码中出现的顺序进行初始化。 4. **非静态块执行**:所有非静态块按它们在源代码中出现的顺序...

    Java常见笔试、面试题目深度剖析,方法重写详解、静态代码块与构造方法执行顺序问题

    本文将深度剖析几个常见的Java面试题目,包括方法重写、静态代码块和构造方法的执行顺序。 首先,我们来讨论**方法重写(Override)**。在面向对象编程中,子类可以继承父类的属性和方法,有时需要根据自己的需求对...

    Java虚拟机类加载顺序

    ### Java虚拟机类加载顺序详解 #### 一、引言 在Java开发中,了解类是如何被加载到Java虚拟机(JVM)中的至关重要。本文将详细介绍JVM中的类加载顺序及其背后的原理,帮助读者理解这一过程,并掌握如何利用类加载...

    Java基础练习题练习下静态块的用处

    通过上述知识点,我们可以理解Java中的静态块是类加载过程中的一个重要组成部分,它在初始化静态变量和管理类级别资源等方面发挥着关键作用。在学习Java基础时,掌握静态块的使用能够帮助我们编写更加高效和整洁的...

    java 继承关系的加载顺序

    在Java编程语言中,继承是面向对象特性的重要组成部分,它允许一个类(子类)从另一个类(父类)继承属性和方法。了解Java中继承关系的加载顺序对于理解和优化程序性能至关重要。以下是对这个主题的详细阐述: 1. ...

    Java静态初始化块和对象初始化块

    静态初始化块是以`static`关键字标识的代码块,它在类被加载到Java虚拟机(JVM)时执行,且只执行一次。静态初始化块常用于设置类级别的变量,或者执行只应执行一次的初始化操作。例如,如果一个类需要在程序运行前...

    Java 普通代码块静态代码块执行顺序(实例讲解)

    这里我们将深入探讨Java中的普通代码块(实例初始化块)和静态代码块的执行顺序,并通过实例来阐述这一概念。 首先,我们需要明白两种类型的代码块: 1. 静态代码块(Static Block):这些代码块在类加载时执行,...

    java中静态与非静态的区别

    例如,在进行单元测试时,可以将测试主方法放置在静态内部类中,以避免为每个Java源文件都添加主方法。 2. **使用限制**: - 定义为静态的内部类有一些限制,比如不能访问外部类的非静态成员。这是因为静态内部类...

    Java中的static关键字

    静态代码块的定义:不包含在任何方法体中,当类被加载时,自动执行静态代码块,而且只被执行一次,它的作用是:经常用于实现类属性的初始化。 在 Java 中,类装载器把一个类装入 Java 虚拟机中,要经过三个步骤来...

    Java初始化块Java初始化块.doc

    - 类初始化:在类初始化阶段,静态属性的内存被分配,然后执行静态初始化块来初始化静态属性。这个过程是自顶向下的,从`java.lang.Object`开始,逐级执行每个类的静态初始化块。 总结起来,Java初始化块是Java中...

    生成静态的方法

    静态关键字在多种编程语言中都有应用,比如Java、C#、C++等,它赋予了类和成员一些特殊的属性和行为。下面我们将深入探讨静态方法、静态变量以及静态类等相关的知识点。 1. 静态方法 静态方法是与类关联,而不是与...

    java中的静态代码块、构造代码块、构造方法详解

    在Java编程语言中,类的初始化过程涉及到几个关键的概念,...这种执行顺序确保了类的静态属性在实例化之前被正确设置,同时实例属性在对象创建时得到初始化。理解这些概念对于编写高效、易于维护的Java代码至关重要。

    举例说明Java中代码块的执行顺序

    下面我们将详细探讨Java中代码块的执行顺序,包括静态属性、非静态属性、静态代码块、非静态代码块以及构造函数。 首先,让我们回顾一下结论: 1. 当创建一个类的实例时,首先会执行类中的静态属性和静态代码块,...

    浅谈Java 类中各成分加载顺序和内存中的存放位置

    本文将深入探讨Java类中各成分的加载顺序以及它们在内存中的存放位置。 首先,类的加载通常发生在以下三种情况: 1. 创建对象:通过`new`关键字创建类的实例。 2. 使用类的静态成员:访问类的静态变量或调用静态...

    java笔记 java笔记

    - **局部变量**:定义在方法或代码块中的变量。 ##### 6.4 成员方法 成员方法是在类中定义的方法,用于实现类的行为。 ##### 6.5 This关键字 `this`关键字代表当前对象的引用,常用于区分成员变量和局部变量。 ...

    Java面向对象(高级)- 类的成员之四:代码块

    类中的结构包括属性(变量)、方法(实现功能)、构造器(创建对象),还有代码块(初始化块),它们各自有不同的作用。 代码块可以分为静态代码块和非静态代码块。静态代码块由`static`关键字修饰,它们在类加载时...

    java web基础

    类的初始化发生在类首次被使用时,包括加载到内存、静态属性的默认初始化、静态属性的显式初始化以及静态块的执行。 总之,Java Web基础涵盖了类、对象、构造方法、`this`关键字、静态与实例成员等多个关键概念。...

Global site tag (gtag.js) - Google Analytics