写的是一些看了《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*/
网友评论