动手动脑-3
package 动手动脑; public class 试验 { public static void main(String[] args) { Foo obj1=new Foo(); Foo obj2=new Foo(); System.out.println(obj1==obj2); } } class Foo{ int value=100; }
这个程序的运行结果是false,建立类Foo的对象obj1,然后立刻又建了类Foo的对象obj2,这两个对象是不同的,就像是克隆了一个新的对象,所以最终结果为false.
构造方法的特殊之处:1、没有返回值
2、与类名相同
3、对对象进行初始化
4、在建类时自动建立一个默认构造函数,但是如果自己建立了有参构造函数,将不再自动建立默认构造函数。
package 动手动脑; 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
第一次建立对象调用的是无参构造函数,然后就要调用上面的field的值,这是采用就近原则,所以第一次输出field的值为100,第二次建立对象,调用的是有参构造函数,这是构造函数自己赋值为300,所以第二次输出为300.
Java字段初始化的规律:
静态初始化生成实例变成你赋给他的值,先执行静态初始化,如果没有实例化,按照初始化和构造方法在程序中出现的顺序执行。
当多个类之间有继承关系时,创建子类对象会导致父类初始化块的执行。
class Root { static{ System.out.println("Root的静态初始化块"); } { System.out.println("Root的普通初始化块"); } public Root() { System.out.println("Root的无参数的构造器"); } } class Mid extends Root { static{ System.out.println("Mid的静态初始化块"); } { System.out.println("Mid的普通初始化块"); } public Mid() { System.out.println("Mid的无参数的构造器"); } public Mid(String msg) { //通过this调用同一类中重载的构造器 this(); System.out.println("Mid的带参数构造器,其参数值:" + msg); } } class Leaf extends Mid { static{ System.out.println("Leaf的静态初始化块"); } { System.out.println("Leaf的普通初始化块"); } public Leaf() { //通过super调用父类中有一个字符串参数的构造器 super("Java初始化顺序演示"); System.out.println("执行Leaf的构造器"); } } public class TestStaticInitializeBlock { public static void main(String[] args) { new Leaf(); } }
运行结果为:
Root的静态初始化块
Mid的静态初始化块
Leaf的静态初始化块
Root的普通初始化块
Root的无参数的构造器
Mid的普通初始化块
Mid的无参数的构造器
Mid的带参数构造器,其参数值:Java初始化顺序演示
Leaf的普通初始化块
执行Leaf的构造器
通过运行结果我发现:在调用这个方法时,有super,调用父类,然后先调用第一个父类中的静态初始化块,然后调用子类的静态初始化块,然后调用子类的子类中的静态初始化块,接着调用父类中的普通初始化块和无参的构造块,然后子类中的普通、无参构造、有参构造初始化块,最后调用方法中System.out.println()中要输出的内容
静态初始化块的执行顺序为:
- 静态初始化块的优先级最高,也就是最先执行,并且仅在类第一次被加载时执行;
- 非静态初始化块和构造函数后执行,并且在每次生成对象时执行一次;
- 非静态初始化块的代码会在类构造函数之前执行。因此若要使用,应当养成把初始化块写在构造函数之前的习惯,便于调试;
- 静态初始化块既可以用于初始化静态成员变量,也可以执行初始化代码;
- 非静态初始化块可以针对多个重载构造函数进行代码复用。
package 动手动脑; public class 静态方法 { public static int a=10; public void setvalue() { System.out.println(a); } public static void main(String[]args) { System.out.println(a); 静态方法 j=new 静态方法(); j.setvalue(); } }
程序的运行结果为:10 10 说明静态方法可以调用静态变量,非静态方法也可以调用静态变量。