关闭

深入了解Java程序执行顺序

173人阅读 评论(0) 收藏 举报
分类:

Java中main方法,静态,非静态的执行顺序详解

  Java程序运行时,第一件事情就是试图访问main方法,因为main相等于程序的入口,如果没有main方法,程序将无法启动,main方法更是占一个独立的线程,找到main方法后,是不是就会执行mian方法块里的第一句话呢?答案是不一定

 看看下面两种最常见的情况:

  第一种情况:

    main方法在一个具有其他方法或属性的类中;

复制代码
public class Test1 {
public static String name;
    public Test1() {
    }
    public static void get() {
        System.out.println("Test start");
    }
    public static void main(String[] args) {
        System.out.println("main start");
        Test1 bb = new Test1();
    }
}
复制代码

 

  第二种情况:

              main方法在一个没有其他方法或属性的类中;

public class Test {
    public static void main(String[] args) {
        Student stu =new Student();
    }
}

 

分析:

  因为静态部分是依赖于类,而不是依赖于对象存在的,所以静态部分的加载优先于对象存在。

  当找到main方法后,因为main方法虽然是一个特殊的静态方法,但是还是静态方法,此时JVM会加载main方法所在的类,试图找到类中其他静态部分,即首先会找main方法所在的类。

 

执行顺序大致分类:

  1.静态属性,静态方法声明,静态块。

  2.动态属性,普通方法声明,构造块。

  3.构造方法。

    

1.1 静态:

  当加载一个类时,JVM会根据属性的数据类型第一时间赋默认值(一举生成的)。然后再进行静态属性初始化,并为静态属性分配内存空间,静态方法的声明,静态块的加载,没有优先级之分,按出现顺序执行,静态部分仅仅加载一次。至此为止,必要的类都已经加载完毕,对象就可以被创建了。

1.2 普通:

  当new一个对象时,此时会调用构造方法,但是在调用构造方法之前,(此刻1.1已经完成,除非被打断而暂停)执行动态属性定义并设置默认值(一举生成的)。然后动态属性初始化,分配内存,构造块,普通方法声明(只是加载,它不需要初始化,只有调用它时才分配内存,当方法执行完毕后内存立即释放),没有优先级之分,按出现顺序执行。最后进行构造方法中赋值。当再次创建一个对象,不再执行静态部分,仅仅重复执行普通部分。

  注意:如果存在继承关系,创建对象时,依然会首先进行动态属性进行定义并设默认值,然后父类的构造器才会被调用,其他一切都是先父类再子类(因为子类的static初始化可能会依赖于父类成员能否被正确初始化),如果父类还有父类,依次类推,不管你是否打算产生一个该父类的对象,这都是自然发生的。

下面是一道小程序:

  代码部分:

复制代码
class A {
    public A() {
        System.out.println("A的构造方法");
    }

    public static int j = print();

    public static int print() {
        System.out.println("A print");
        return 521;
    }
}

public class Test1 extends A {
    public Test1() {
        System.out.println("Test1的构造方法");
    }

    public static int k = print();

    public static int print() {
        System.out.println("Test print");
        return 522;
    }

    public static void main(String[] args) {
        System.out.println("main start");
        Test1 t1 = new Test1();
    }
}
复制代码

  运行结果:

A print
Test print
main start
A的构造方法
Test1的构造方法

 

下面是一道阿里巴巴的面试题:非常经典,可以不断的改变程序的顺序,来找到执行顺序机制。

  代码部分:

复制代码
public class Text {
    public static int k = 0;
    public static Text t1 = new Text("t1");
    public static Text t2 = new Text("t2");
    public static int i = print("i");
    public static int n = 99;
    public int j = print("j");

    {
        print("构造块");
    }
    static {
        print("静态块");
    }

    public Text(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "    n=" + n);
        ++i;
        ++n;
    }

    public static int print(String str) {
        System.out.println((++k) + ":" + str + "   i=" + i + "    n=" + n);
        ++n;
        return ++i;
    }

    public static void main(String args[]) {
        Text t = new Text("init");
    }
}
复制代码

   运行结果:

复制代码
1:j   i=0    n=0
2:构造块   i=1    n=1
3:t1   i=2    n=2
4:j   i=3    n=3
5:构造块   i=4    n=4
6:t2   i=5    n=5
7:i   i=6    n=6
8:静态块   i=7    n=99
9:j   i=8    n=100
10:构造块   i=9    n=101
11:init   i=10    n=102
复制代码

 

总结只要按照这个步骤,遇到这一类问题就可以解决了。     

 

          1-3:类加载过程,不涉及构造方法

          1-5: 实例化过程,涉及构造方法

  1.类中所有属性的默认值(一举而成)

  2. 父类静态属性初始化,静态块,静态方法的声明(按出现顺序执行)

  3. 子类静态属性初始化,静态块,静态方法的声明 (按出现顺序执行)

  4.  调用父类的构造方法,

      首先父类的非静态成员初始化,构造块,普通方法的声明(按出现顺序执行)

      然后父类构造方法

  5.  调用子类的构造方法,

      首先子类的非静态成员初始化,构造块,普通方法的声明(按出现顺序执行)

      然后子类构造方法

 

   注意:类加载过程中,可能调用了实例化过程(因为static可以修饰方法,属性,代码块,内部类),此时则会暂停类加载过程而先执行实例化过程(被打断),执行结束再进行类加载过程,上面阿里那道面试题就是典型的暂停类加载。

 

下面附加一个小程序来显示新建对象时属性的四个过程:

 

复制代码
public class Test {
    public static void main(String[] args) {
        Student stu = new Student("zhangan", 21);
    }
}

class Student {
    public String name = "李寻欢";
    public int age = 20;

    public Student(String name, int age) {
        this.name = name;
        this.age = age;
    }

}
复制代码

 

1.

2.

3.

4.

2
0
查看评论

深入了解MySQL的索引(一)

(一)关于存储引擎               创建合适的索引是SQL性能调优中最重要的技术之一。在学习创建索引之前,要先了解MySql的架构细节,包括在硬盘上面如何组织的,索引和内存用法和操作方式,以及存储引擎的差异如...
  • qq_27291877
  • qq_27291877
  • 2015-05-06 21:42
  • 650

深入了解路由器

路由器是什么  是什么把网络相互连接起来?是路由器。路由器是互联网络的枢纽、"交通警察"。目前路由器已经广泛应用于各行各业,各种不同档次的产品已经成为实现各种骨干网内部连接、骨干网间互联和骨干网与互联网互联互通业务的主力军。    所谓路由就是指通过相互连接的网络把信息从源地点移...
  • feijj2002_
  • feijj2002_
  • 2007-04-02 22:46
  • 1284

深入理解Tomcat

简介tomcat是一个web服务器,运行jsp和servlet,使用HTTP与客户端(通常是浏览器)进行通信。构成下图是tomcat的架构,可以看出:核心内容是Connector和Container组件。一个Server服务器中可能有多个Service,Service可以暂时理解为“服务”。Serv...
  • u010066934
  • u010066934
  • 2016-06-14 14:59
  • 3110

JAVA程序执行顺序,你了解了吗?

本文主要介绍以下两块内容的执行顺序,熟悉的大虾可以直接飘过。      一。JAVA中执行顺序 静态块块构造器父类构造器     二。JAVA中赋值顺序       静态块直接...
  • fanyuna
  • fanyuna
  • 2014-04-17 16:18
  • 457

深入理解Hibernate

映射一对多关联关系一对多双向关联关系映射例子 用户与订单关系 customer表和order表 order表有个一个字段是customerid那么在用户的entity中就存在一个set来存放订单//表明一个用户有多个订单 private Set(Order)orders=new HashSet...
  • chenjianandiyi
  • chenjianandiyi
  • 2016-09-16 18:07
  • 747

深入理解Spring系列之一:开篇

Spring经过大神们的构思、编码,日积月累而来,所以,对其代码的理解也不是一朝一夕就能快速完成的。源码学习是枯燥的,需要坚持!坚持!坚持!当然也需要技巧,第一遍学习的时候,不用关注全部细节,不重要的代码可以先忽略掉,达到理解大体的架子及流程,避免第一次就陷入某个坑里出不来。第二遍针对某个流程更深入...
  • tianruirui
  • tianruirui
  • 2016-10-30 20:18
  • 2615

HTML深入理解—孙鑫视频小结

在之前的博客中简单介绍了HTML的一些知识http://blog.csdn.net/u010955843/article/details/41412025     这是自己参考一本书之后写的一些浅薄的知识,牛腩新闻发布系统的完成,里面大量提到了HTML代码,并且我们同样可以看到最...
  • u010955843
  • u010955843
  • 2014-12-07 20:34
  • 930

《深入了解.NET框架》

深入了解.net框架(一)理解受管理的执行(managed excution)    在受管理的执行过程的第一步是设计源程序。如果你想你的应用程序受益于common language runtime(公共语言运行时),你必须使用一个或多个支持运行时的语言编译器,比如vi...
  • benben1hao
  • benben1hao
  • 2001-06-19 11:46
  • 1201

深入了解FMDB<一>

今天公司项目需要,需要再FMDB基础上进行一次封装,好吧,我之前只是用用它,封装FMDB?吓我一跳,没办法,我就只能静下心来好好看看FMDB,以前都是就用那么几个方法,也没想着好好研究,好吧,研究吧。 As we know,FMDB is a SQLITE objective-c wrapper.F...
  • baidu_31683691
  • baidu_31683691
  • 2016-01-27 19:48
  • 352

深入理解 Hive

1. 分区表
  • lanchunhui
  • lanchunhui
  • 2016-03-17 09:16
  • 584
    个人资料
    • 访问:135227次
    • 积分:2053
    • 等级:
    • 排名:千里之外
    • 原创:34篇
    • 转载:213篇
    • 译文:0篇
    • 评论:20条
    爱编程-爱生活
    写给自己
    你花八块买个盒饭吃,觉得很节省,有人在路边买了一块钱馒头吞咽后步履匆匆;

    你八点起床看书,觉得很勤奋,上微博发现曾经的同学八点就已经在面对繁重的工作;

    你周六补个课,觉得很累,打个电话才知道许多朋友都连续加班了一个月。

    亲爱的,你真的还不够苦,不够勤奋和努力。