Java初始化小结

写的是一些看了《Java编程思想》4th和网上查的一些资料的总结,有错误的地方欢迎指正。

静态数据初始化

不管创建了多少对象都只占用单个存储区域。
static不能应用于局部变量,只能作用于域。
初始化完静态数据后再初始化非静态的。
静态数据会在加载类时初始化,成员变量则会在创建类的对象时才初始化。

class SimpleClass {

    {
        i = 3;
    }

    static int i;
}

    public void localVariable() {
//        static int  b = 3;              //局部变量里不允许使用static
    }

class Test {
    public static void main(String[] args) {
//        SimpleClass sc = new SimpleClass();   
        System.out.println(SimpleClass.i);
    }
}  /*output
    0
    */

当创建对象时,输出的结果是3,当注释掉时,输出的是0。

成员变量

变量在局部变量里未赋值时,会报错。
变量可以通过方法来赋值。

class Test1 {
    private int j;
    private int i = getI();           //通过方法给变量赋值

    public void localVarible() {
        int k;
        System.out.println(k);     //error:变量'k'可能没有初始化
        System.out.println(j);
    }

    public int getI() {
        i = 10;
        return i;
    }
}

当把 System.out.println(k) 注释掉时编译成功。

用构造器初始化

构造器名称和类名相同。
构造器是特殊的方法,它没有返回值。
java在操作对象前会分配空间,会调用相应的构造器,保证初始化。

默认构造器(不含参数)

导出类创建对象时会隐式的调用超类的默认构造器。如果不调用超类构造器,则当导出类调用超类的变量或方法时会出现还没有初始化的情况。 参考:
http://zhidao.baidu.com/link?url=Ex3zcGjxl5_XPHnyFBynsUKeBWPGB1j6d6zgLfEOZw4wT-geMILWiCaWPU6yPH4uf3kKwR4mxsUxb7G7ph6W8bDDjRU1UsL8GN74QVMiucq

class Super {
    Super() {
        System.out.println("Super()");
    }
}

class Derived extends Super {
    Derived() {
        System.out.println("Derive()");
    }
}

class Main {
    public static void main(String[] args) {
        Derived d = new Derived();       //会先调用超类的构造器
    }
}/*output
Super()
Derived() */
含参构造器

构造器也可以带参数, 当只有一种构造器时,将不会其他任何的形式来创建对象 。
当超类中只有含参的构造器时,导出类初始化时必须先用super调用超类构造器。

class Super {
    Super(String str) {
        System.out.println("Super(str)");
    }
}

class Derived extends Super {
    Derived() {
        super("str");
        System.out.println("Derived()");
    }
    Derived(String str) { 
        super("str");
        System.out.println("Derived(str)");
    }
}

为了保证导出类的成员和方法正确的初始化,当注释掉 super("str")时会报错。

数组初始化

数组之间赋值传递的是引用。

class ArrayInitialization { 

    public static void main(String[] args) { 
        int[] i = {1, 2, 3, 4, 5, 6}; 
        int[] j = i; 

        for (int n = 0; n < i.length; n++) 
            i[n] = i[n] + 1; 

        for (int n : j) 
            System.out.println(n);
    } 
}  /**output 
  2
  3 
  4 
  5 
  6 
  7  * / 

继承初始化

class Super { 
    static { 
        System.out.println("超类静态初始化块");
    } 
    static int i = 5; 

    int j = 6;  
    { 
        System.out.println("超类普通初始化块"); 
    } 

    Super() { 
        System.out.println("Super()"); 
    } 
} 

class Derived extends Super { 
    static int k = 10; 
    static { 
        System.out.println("导出类静态初始化块"); 
    }   

    { 
        System.out.println("导出类普通初始化块"); 
    } 
    int h = 11; 

    Derived() { 
        System.out.println("Derived()"); 
    } 

    public static void main(String[] args) {
        Derived d = new Derived();
    }
}     /** output:
 超类静态初始化块
 导出类静态初始化块
 超类普通初始化块
 Super()
 导出类普通初始化块
 Derived() */

当没有继承关系且只创建Super对象时:

class Super {
    static {
        System.out.println("超类静态初始化块");
    }
    static int i = 5;

    int j = 6;
    {
        System.out.println("超类普通初始化块");
    }

    Super() {
        System.out.println("Super()");
    }
}

class Derived  {
    static int k = 10;
    static {
        System.out.println("导出类静态初始化块");
    }

    {
        System.out.println("导出类普通初始化块");
    }
    int h = 11;

    Derived() {
        System.out.println("Derived()");
    }

    public static void main(String[] args) {
        Super s = new Super();
    }
}  /*
导出类静态初始化块
超类静态初始化块
超类普通初始化块
Super()
*/

这时候会先初始化Derived类的静态数据,再始初化Super的静态数据。因为JVM虚拟机会先加载类的main方法,判断其有无超类,如果没有就直接初始化静态数据;如果有就先初始化基类的构造器。

初始化顺序:

在初始化之前会把所有成员都赋初始值(0,null等)。
超类静态代码块 >> i >> k >> 导出类静态代码块 >> j >>超类静态代码块 >> 超类构造器 >> 导出类静态代码块 >> h >> 导出类构造器 。

向上转型时

当导出类构造器重写了超类构造器调用的方法后,在创建了对象进行初始化时超类构造器会调用导出类覆写的方法,但变量不会被重写,可以当它隐式的用private修饰了。

class Super {
    public int i = 3;
    public int j = 4;
    public Super() {
        System.out.println("i = " + i + ", j = " + j);
        rewriteMethod();
    }

    public void rewriteMethod() {
        System.out.println("Super's method");
    }
}
class Derived extends Super {
    public int i = 5;
    public int j = 6;
    public Derived() {
        System.out.println("i = " + i + ", j = " + j);
        rewriteMethod();
    }

    @Override
    public void rewriteMethod() {
        System.out.println("Derived's method");
    }
}

class Main {
    public static void main(String[] args) {
        Super s = new Derived();
    }
}
    /*output:
    i = 3, j = 4
    Derived's method
    i = 5, j = 6
    Derived's method*/
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • (一)Java部分 1、列举出JAVA中6个比较常用的包【天威诚信面试题】 【参考答案】 java.lang;ja...
    独云阅读 7,149评论 0 62
  • 第一章 对象导论 对象具有状态、行为和标识。这意味着每一个对象都可以拥有内部数据和方法,并且每一个对象都可以唯一地...
    niaoge2016阅读 870评论 0 0
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,823评论 18 399
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,395评论 11 349
  • 【R】能够清晰整理工作的“工作框架”(P93) 及时清晰的整理好工作的框架,梳理好重要的事情,即使我们时间不充裕,...
    深海碧影阅读 344评论 0 0