关于java对象初始化的一点有意思的东西

原创 2015年04月01日 08:46:52

这篇文章实际的内容并没有多少,或者说对实际编程影响并不大,主要是为了可能的笔试面试之类的,还有就是有点好玩而已。

有一天我在书上看到很有意思的代码:

class A{

    {
        System.out.println("----->A的初始化块");
    }

    static {
        System.out.println("----->A的静态初始化块");
    }

    public A(){
        System.out.println("----->A的构造器");
    }
}

class B extends A{
    {
        System.out.println("---->B的初始化块");
    }

    static {
        System.out.println("---->B的静态初始化块");
    }

    public B(){
        System.out.println("---->B的构造器");
    }
}

class C extends B{
    {
        System.out.println("--->C的初始化块");
    }

    static {
        System.out.println("--->C的静态初始化块");
    }

    public C(){
        System.out.println("--->C的构造器");
    }
}

public class ForBlogTest {
    public static void main(String[] args) {
        C c = new C();
        System.out.println("----------------------------------分割线----------------------------------");
        C c1 = new C();
    }
}

你假如已经知道他的输出了,那么可以不用看这篇文章了。以下是他的输出结果。

下面我就来解释以下,当然这是建立在我对jvm还没有深入了解的基础上讨论的,相信不就后,我会站在那个角度来对他进行解释。

首先输出的是A的静态初始块,为什么,我们可以把这个问题分解为两个。1,为什么输出静态初始块; 2,为什么先输出A 。

我们先来说说第一个问题:因为在我们new 一个变量时,编译器首先会各种方式找到你调用的类,然后对它进行加载。因为静态的变量,方法,初始块都属于类,所以在加载一个类时,也会加载属于他的初始块,方法,和变量。所以,我们第一个输出的是初始块,但为什么又只输出一次呢。因为在我们的内存中已经加载了该类,所以下一次new一个新对象时,根本不需要再重新加载,因此也就只掉用一次初始块了。

那第二个问题呢:因为在初始一个对对象的时候,编译器会先找到它的父类,并先调用他的初始化操作,所以可以得到,每次初始一个对象是,最先调用的是Object的初始化操作。

那么又为什么是先输出初始块呢。因为编译器会在生成class文件中将初始块里的代码加到所调用的构造器的器中,并在最前面。所以,我们总能看到初始块里的代码是先于构造器中的代码输出的。到这,这个例子也就理解差不多了。那我们再来看个东西

class D{
    private int num = 3;
    
    public D(){
        num = 4;
    }
    
    public int getNum(){
        return num;
    }
    
}
调用getNum(),将会得到什么呢。没错就是4。其实假如再加一段代码,我们就可以把它和上面所说的联系起来了。

class D{
    private int num = 3;

    {
        num = 4;
    }

    public D(){
    }

    public int getNum(){
        return num;
    }

}

你觉得这个会输出什么呢。的确,是4.那么当我们这样写呢。

class D{
    {
        num = 4;
    }
    
    private int num = 3;

    public D(){
    }

    public int getNum(){
        return num;
    }

}

num的值就变成了3。所以我们可以得出结论。其实在类中初始化的变量的优先级和初始块了初始化变量的优先级是一样的。因此,不难理解初始块里的代码为什么先于构造器中的输出了。好了,还不够,还有点有意思的东西。

class E{
    public E(){
        echo();
    }

    public void echo() {
        System.out.println("-------->这是父类中的echo");
    }
}

class F extends E{
    public void echo(){
        System.out.println("----->这是子类中的echo");
    }
}

public class ForBlogTest{
    public static void main(String[] args) {
        F f = new F();
    }
}
请问,这会输出什么。

答案是:----->这是子类中的echo

是不是感觉挺好玩的。在编译过程中什么事都是按照平常的进行。当时在运行时,子类的方法直接将父类的覆盖了,所以就输出了子类echo中的内容。这个原理就有点类似于

class E{
    public void echo() {
        System.out.println("-------->这是父类中的echo");
    }
}

class F extends E{
    public void echo(){
        System.out.println("----->这是子类中的echo");
    }
    public void test(){
        
    }
}

public class ForBlogTest{
    public static void main(String[] args) {
        E f = new F();
        f.echo();
    }
}

这个echo是输出子类中echo里的代码,但是,我们调用f.test();时,连编译器都不能通过。但是强制类型转化后又能调用,说明在运行时,内存中加载的的确是F中的方法和变量。


关于爬虫的一些东西

这几天在写一个爬虫,实际上整个过程和思路很简单,难点在于繁杂的格式处理和一些未知的小问题,还有对python不太熟悉.基本上是边学边写.记录一些过程中值得记住的东西. 关于python的: 1...
  • github_32716139
  • github_32716139
  • 2015年11月10日 20:57
  • 293

Java基础总结之类与对象的初始化顺序

Java
  • crazyf2015
  • crazyf2015
  • 2015年06月27日 21:51
  • 2176

深入浅出Java类和对象的初始化

最近项目调试中出现了类初始化的问题,虽然事后证明是Eclipse的问题,但也暴露了对Java初始化机制的欠缺,在此翻译一篇javaworld上的文章。这篇文章很好,深入浅出地介绍了Java的初始化细节...
  • MOLIILOM
  • MOLIILOM
  • 2016年01月03日 21:23
  • 1115

java对象数组的声明和初始化

关键点: 在创建后,基本数据类型数组可以直接对数组元素赋值、引用等操作;而自定义对象数组,需要对数组中的每个对象元素独立进行创建,然后才可以对其赋值、引用等操作,如果没有单独对每个对象元素创建,...
  • fengzijia
  • fengzijia
  • 2015年06月21日 22:12
  • 11370

关于树状数组一些有意思的东西

嘛~最近刚刚学会树状数组,写个blog记录一下心得。树状数组呢,核心是一个叫lowbit的东西,lowbit(x)=x&-x=x的最后一位1的大小。 一、一个经典问题 一个初始值为0的k位计数器...
  • TA201314
  • TA201314
  • 2016年04月28日 09:23
  • 1428

JAVA web中的一点东西

参考文献: http://m.blog.csdn.net/article/details?id=45151569 http://www.cnblogs.com/goody9807/archive/...
  • youyou1543724847
  • youyou1543724847
  • 2016年10月05日 19:07
  • 988

Java基础-对象的内存分配与初始化

首先,什么是类的加载?类的加载由类加载器执行.该步骤将查找字节码(classpath指定目录),并从这些字节码中创建一个Class对象。java虚拟机为每种类型管理一个独一无二的Class对象。也就是...
  • Wang_1997
  • Wang_1997
  • 2016年08月21日 13:49
  • 1054

深入理解Java对象的创建过程:类的初始化与实例化

在Java中,一个对象在可以被使用之前必须要被正确地初始化,这一点是Java规范规定的。在实例化一个对象时,JVM首先会检查相关类型是否已经加载并初始化,如果没有,则JVM立即进行加载并调用类构造器完...
  • justloveyou_
  • justloveyou_
  • 2017年05月18日 14:17
  • 9401

JAVA笔记-类的初始化及对象的初始化

类的初始化及对象初始化 初学Java,觉得类的初始化与对象的初始化这一块真的特别重要,翻了很多大神前辈的整理资料,还是有些懵懂,决定将资料整理下,也希望对后来的初学者有些许帮助。 上图为类的生命周...
  • Java_Chuck
  • Java_Chuck
  • 2016年06月26日 13:19
  • 3168

浅析Java内存和创建对象时成员的初始化过程

Java虚拟机在运行需要在内存中开辟空间,在空间中进一步分区,每个分区都有其对数据的处理特点, 内存的划分: 1、寄存器: CPU在处理,存储速度非常快,程序不可控制 2、本地方法区:和所在系统...
  • xiaoshengfdyh
  • xiaoshengfdyh
  • 2015年10月08日 20:28
  • 1268
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于java对象初始化的一点有意思的东西
举报原因:
原因补充:

(最多只允许输入30个字)