• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Java > Java类中各部分的执行顺序

Java类中各部分的执行顺序

作者:z3896823 字体:[增加 减小] 来源:互联网 时间:2017-09-23

z3896823通过本文主要向大家介绍了java,class,classloader等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com
public class ClassLoadTest {

    ClassLoadTest(){
        System.out.println("构造一个ClassLoaderTest");
    }

    {
        System.out.println("CLassLoader的非静态代码块");
    }

    static {
        System.out.println("CLassLoader的静态代码块");
    }

    public static void main(String[] args){

        A a = new A("a");

        System.out.println("构造一个子类对象,并赋值给子类引用");
        C c = new C();
        System.out.println("构造一个子类对象,并赋值给父类引用");
        B b = new C();
        System.out.println("构造一个父类对象,并赋值给父类引用");
        B b1 = new B();

    }
}

class A {

    A(String s){
        System.out.println("A 构造方法-----开始");
        B b1 = new B("构造方法中生成的B");
        System.out.println("A 的构造方法"+s);
        funA2();
        System.out.println("A 构造方法--------------完毕");
    }

    {
        System.out.println("A 的非静态代码块-----开始");
        funA2();
        funA1();
        System.out.println("A 的非静态代码块-------------完毕");
    }

    B b1 = new B("非静态全局变量生成的B");

    static B b2 = new B("静态全局变量生成的B");

    static {
        System.out.println("A的静态代码块-----开始");
        B b1 = new B("静态代码块");
        System.out.println("A 的静态代码块--------------完毕");
    }

    public static void funA1(){
        System.out.println("A 的静态方法");
    }

    public void funA2(){
        System.out.println("A 的成员方法");
    }
}

class B{

    String s = "b";

    static {
        System.out.println("B 的静态代码块");
    }

    {
        System.out.println("B 的非静态代码块");
    }

    B(){
        System.out.println("B 的无参构造方法");
    }

    B(String s){

        System.out.println("构造了一个 B--"+s);
    }

    public static void funA1(){

        System.out.println("B 的静态方法");
    }

    public void funA2(){
        System.out.println("B 的成员方法");
    }

    private void fun3(){
        System.out.println("B 的private成员方法");

    }
}

class C extends B{

    String s = "c";

    static {
        System.out.println("C 的静态代码块");
    }

    {
        System.out.println("C 的非静态代码块");
    }

    C(){
         System.out.println("C的无参构造方法");
    }

    private static void fun3(){
    }

    @Override
    public void funA2(){
        funA1();
        System.out.println("override");
    }
}

CLassLoader的静态代码块
B 的静态代码块
B 的非静态代码块
构造了一个 B–静态全局变量生成的B
A的静态代码块—–开始
B 的非静态代码块
构造了一个 B–静态代码块
A 的静态代码块————–完毕
A 的非静态代码块—–开始
A 的成员方法
A 的静态方法
A 的非静态代码块————-完毕
B 的非静态代码块
构造了一个 B–非静态全局变量生成的B
A 构造方法—–开始
B 的非静态代码块
构造了一个 B–构造方法中生成的B
A 的构造方法a
A 的成员方法
A 构造方法————–完毕
构造一个子类对象,并赋值给子类引用
C 的静态代码块
B 的非静态代码块
B 的无参构造方法
C 的非静态代码块
C的无参构造方法
构造一个子类对象,并赋值给父类引用
B 的非静态代码块
B 的无参构造方法
C 的非静态代码块
C的无参构造方法
构造一个父类对象,并赋值给父类引用
B 的非静态代码块
B 的无参构造方法

类的初始化原则:

  1. 静态的东西最先运行。静态全局变量和静态代码块谁先运行取决于谁写在前面。且静态的东西永远只运行一次。第二次new的时候既不会初始化static变量,也不会运行static代码块。
  2. 对于非静态的东西,先初始化变量,最后运行构造方法,与代码写的顺序无关。
  3. 构造子类时,首先会构造一个父类。等父类构造完成后才会构造子类。非静态代码块和对象绑定,所以父类的非静态代码块是在构造父类对象的时候运行的。
  4. 另外可以看到,运行Main方法并不需要生成对象,直接用类调用就行了,但是会调用static代码块。如果有static对象的话也会先生成,最后调用static的Main方法。

几个问题:

  • 构造方法中能不能调用成员函数?可以,但实际使用中要注意空指针,因为成员方法用到的变量不一定在构造对象的时候就已经初始化了。例如,在Android中就不能在Application的构造方法中调用getSharedPreferences()。
  • 非静态代码块,成员变量,构造方法的调用顺序?全局变量和非静态代码块的执行顺序看谁写在前面,构造方法总是最后调用。
  • 非静态代码块中能够调用成员函数?可以,静态函数也可以。

为什么构造方法总是最后执行的原因:

构造方法的作用是对类初始化。具体来讲是对类的变量进行初始化。那么首先得有变量才能对变量进行初始化。所以总是变量先构造出引用,最后构造函数才得到执行。

补充:

今天做美丽联合的笔试,遇到这么一个奇怪的题:

public class Meili {

    static Meili meili = new Meili();

    {
        System.out.println("非静态代码块");
    }

    static {
        System.out.println("静态代码块");
    }

    public static void main(String[] args){
        System.out.println("开始执行Main方法");
        Meili meili = new Meili();
    }
}

求输出是什么?

注意这块代码和上面的例子不同之处在于,它直接用执行类(包含Main方法的类)来生成对象。结果是:

非静态代码块
静态代码块
开始执行Main方法
非静态代码块

这段代码的执行顺序是这样的:先生成static的Meili对象,于是执行代码块,但是奇怪的是居然先执行了非静态代码块。当静态的Meili对象生成完了之后去执行Main方法。然后在Main方法中生成另一个Meili对象,此时由于静态代码块已经执行过了,所以只会执行非静态代码块,程序结束。

这段代码诡异的地方在于,每个Meili对象都持有一个Meili对象,即第三行的静态Meili引用所指的对象。如果去掉static会栈溢出,因为会无限调用构造方法。但是为什么非静态代码块会在静态代码之前调用呢?之前的测试证明了静态代码块是一定会在非静态代码块之前执行的呀?希望知道的大佬不吝赐教。

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • JavaThreadPoolExecutor线程池调度器
  • 全面掌握Java内部类
  • Java中的常用阻塞队列源码分析
  • Java虚拟机(四)垃圾收集算法
  • Java内存模型与线程
  • Java中如何优雅正确的终止线程
  • [译]深入字节码操作:使用ASM和Javassist创建审核日志
  • IntelliJIDEA平台下JNI编程(五)—本地C代码创建Java对象及引用
  • 【java总结】设计模式详解
  • Java代码中常见技术债务处理之Exception

相关文章

  • 2017-05-28spring使用RedisTemplate的操作类访问Redis
  • 2017-05-28详解Spring Boot 定时任务的实现方法
  • 2017-05-28详解spring boot配置单点登录
  • 2017-05-28jstl之map,list访问遍历以及el表达式map取值的实现
  • 2017-05-28java list 比较详解及实例
  • 2017-05-28Spring Boot的Controller控制层和页面
  • 2017-05-28详解 Java Maximum redirects (100) exceeded
  • 2017-05-28Mybatis开发环境搭建实现数据的增删改查功能
  • 2017-05-28浅谈spring中的default-lazy-init参数和lazy-init
  • 2017-05-28Java面试问题知识点总结

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • java 基础知识之IO总结
    • MyBatis 参数类型为String时常见问题及解决方法
    • 详解Spring简单容器中的Bean基本加载过程
    • Java中的对象流总结(必看篇)
    • 详解使用Spring Boot开发Web项目
    • 利用Java异常机制实现模拟借书系统
    • java中添加按钮并添加响应事件的方法(推荐)
    • Spring Boot + Jpa(Hibernate) 架构基本配置详解
    • Java身份证验证方法实例详解
    • Java中抽象类和接口的区别_动力节点Java学院整理

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有