zoukankan      html  css  js  c++  java
  • JAVA中代码顺序,静态块 静态变量,加载顺序! (转)

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

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

    classTest
    {

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

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

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

    测试的方法:比如

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

    接下来我们出发!--------->>
    // 注意看,这里仅仅是一个普遍情况,特殊情况下面有总结:在下面的A ,B两种情况的总结非常的重要,一定要好好的看看!
    public classExten
    {
    staticint 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");
    }
    staticvoid run()// 静态方法,调用的时候才加载// 注意看,e没有加载
    {
    System.out.println("e");
    }
    publicstaticvoid main(String[] args)
    {
    newExten();
    }

    一般顺序:静态块——>静态变量——>成员变量——>构造方法——>静态方法
    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 ,打印就是"你只是在打印我"


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

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

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

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

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

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


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

     

    •           静态变量这个问题是最不容易搞明白的问题,静态变量只加载一次,以后不论你怎么new不会再加载
    •           而且注意:静态块也是仅加载一次,

     

    •            静态变量后大括号内有代码的话,new一次执行一次。
    •            静态块加载的时候大括号内的语句就执行完毕,以后不会执行。

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

     


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


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


    这样的话是不是非常的清晰呢了!这才是所有代码加载的顺序啊,以后对于程序的执行就会有更深的理解了 !
  • 相关阅读:
    Aurora 数据库支持多达五个跨区域只读副本
    Amazon RDS 的 Oracle 只读副本
    Amazon EC2 密钥对
    DynamoDB 读取请求单位和写入请求单位
    使用 EBS 优化的实例或 10 Gb 网络实例
    启动 LAMP 堆栈 Web 应用程序
    AWS 中的错误重试和指数退避 Error Retries and Exponential Backoff in AWS
    使用 Amazon S3 阻止公有访问
    路由表 Router Table
    使用MySQLAdmin工具查看QPS
  • 原文地址:https://www.cnblogs.com/andysd/p/2506500.html
Copyright © 2011-2022 走看看