动手·动脑


以下代码为何无法通过编译?哪儿出错了?


public class Test {
public static void main(String[] args)
{
Foo obj1=new Foo();
}
}
class Foo
{
int value;
public Foo(int intValue)
{
Value=intValue;
}
}

该程序运行时会出错,原因是 如果类提供了一个自定义的构造方法,将导致系统不再提供默认构造方法。

试验------

public class InitializeBlockClass {
{
field=200;
}
public int field=100;
public InitializeBlockClass(int value)
{
this.field=value;
}
public InitializeBlockClass() {

}
public static void main(String[] args)
{
InitializeBlockClass obj=new InitializeBlockClass();
System.out.println(obj.field);
obj=new InitializeBlockClass(300);
System.out.println(obj.field);
}
}

运行结果为100 300。

Java进行初始化的地方有两个:初始化块和构造函数,其中初始化块又分为静态初始化块和实例初始化块。
静态初始化块是类中由static修饰的初始化块,实例初始化块为类中没有任何关键字修饰的初始化语句。
如果在主函数中创建对象时没有形参时,如果在类中定义了公共的变量并给与了赋值,那么就会把值赋给主函数中的变量,
再调用类中的默认构造函数,如果在主函数中创建对象时有形参,则调用类中对应的构造函数。

java字段的初始化规律:

1.类的构造方法

(1)“构造方法”,也称为“构造函数”,当创建一个对象时,它的构造方法会被自动调用。构造方法与类名相同,没有返回值。

(2)如果类没有定义构造函数,Java编译器在编译时会自动给它提供一个没有参数的“默认构造方法”。如果类提供了一个自定义的构造方法,将导致系统不再提供默认构造方法

(3)同一个类可以有多个构造函数,多个构造函数之间通过参数来区分.这是方法重载的一个实例。

构造函数之间可以相互调用。

2.类的初始化块

(1)可以在类中使用“{”和“}”将语句包围起来,直接将其作为类的成员。

类的这种“没有名字”的“成员”,多用于初始化类的字段。

3.执行类成员定义时指定的默认值或类的初始化块,到底执行哪一个要看哪一个“排在前面”。

执行类的构造函数

类的初始化块不接收任何的参数,而且只要一创建类的对象,它们就会被执行。因此,适合于封装那些“对象创建时必须执行的代码”。


-------请运行TestStaticInitializeBlock.java示例,观察输出结果,总结出“静态初始化块的执行顺序”。--------

运行结果:
Root的静态初始化块
Mid的静态初始化块
Leaf的静态初始化块
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值:Java初始化顺序演示
Leaf的普通初始化块
执行Leaf的构造器


总结:
1,静态初始化块的优先级最高,也就是最先执行,并且仅在类第一次被加载时执行;
2,非静态初始化块和构造函数后执行,并且在每次生成对象时执行一次;
3,非静态初始化块的代码会在类构造函数之前执行。因此若要使用,应当养成把初始化块写在构造函数之前的习惯,便于调试;
4,静态初始化块既可以用于初始化静态成员变量,也可以执行初始化代码;
5,非静态初始化块可以针对多个重载构造函数进行代码复用。

---------------------------
一个有趣的问题:

静态方法中只允许访问静态数据,那么,如何在静态方法中访问类的实例成员(即没有附加static关键字的字段或方法)?

package Test;

public class test0

{

private static test0 _instance = null;

public static test0 getInstance()

{

if(null == _instance)

_instance = new test0();

return _instance;

}

}

-----------------------------------------------------------------
Integer的“诡异”特性”

public class StrangeIntegerBehavior

{

public static void main(String[] args)

{

Integer i1=100;

Integer j1=100;

System.out.println(i1==j1);

Integer i2=129;

Integer j2=129;

System.out.println(i2==j2);

}

}


运行结果:
true
false


使用javap来分析生成class文件,看它调用了Interger类的哪个方法,然后打开JDK源文件查看源码,就可以找到答案。

猜你喜欢

转载自www.cnblogs.com/shenaoyu/p/11700105.html