4.初始化与清理(下)

4.初始化与清理(下)-四曲博客
4.初始化与清理(下)
此内容为免费阅读,请登录后查看
0
免费阅读

成员的初始化

对于局部变量来讲,java采用错误提示的方式来提示程序员没有对变量进行初始化

对于成员变量来说,java则采用了提供默认值的方式来对成员变量进行初始化

指定初始化

有几种方式可以用于对于成员变量进行赋值,比如在定义成员变量的时候对它进行赋值,使用函数来对它进行赋值,采用构造函数的方式来进行初始化

使用构造器来进行初始化

可以使用构造器来对成员进行初始化,但是需要注意,在你使用构造器之前,成员就已经被初始化成默认值了。

初始化顺序

在类的内部,变量定义的先后顺序决定了初始化的顺序,既便变量散落在方法定义之外也是一样的,在调用构造器之前,会优先对成员变量进行默认初始化

package charpter05;

class window{
    window(int number){System.out.println("window("+number+")");}
}

class House{
    window w1=new window(1);
    House(){
        System.out.println("House");
        w3=new window(4);
    }
    window w2=new window(2);
    window w3=new window(3);

}
public class test_5_7_1 {

    public static void main(String[] args) {
        new House();
    }
}
//window(1)
//window(2)
//window(3)
//House
//window(4)

最终的运行效果与我们预期的一致,成员变量的初始化在构造函数调用之前

静态数据的初始化

初始化顺序是先静态对象,而后才是非静态对象,以下是对象的创建过程,假设有一个Dog的类

  1. 即是没有显示地使用static关键字,构造器实际上也是静态方法,因此,当首次创建类型为Dog的对象时,或者Dog类的静态方法/静态域首次被访问时,java解释器必须查找类路径,以定位到Dog.class文件
  2. 然后载入Dog.class,有关静态初始化的所有动作都会执行,静态初始化只在class对象首次加载的时候进行一次
  3. 当用new Dog()创建对象时,首先将在堆上为Dog对象分配足够的空间
  4. 存储空间被清零,然后将对象的基本类型数据进行初始化,而引用则设置成null
  5. 执行所有处于字段定义处的初始化动作
  6. 执行构造器
package charpter05;

class Bowl{
    static Bowl b2=new Bowl(2);
    Bowl(int number){
        System.out.println("Bowl("+number+")");
    }
}

class Table{
    static Bowl b1=new Bowl(1);
    Table(){
        System.out.println("Table create");
    }
}

public class test_5_7_2 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new Table();
    }

}
//Bowl(2)
//Bowl(1)
//Table create

显示的静态初始化

Java允许将多个静态初始化动作组织成一个特殊的“静态子句”(有时也叫做“静态块”),但它实际上只是一段跟在static关键字后面的代码,与其他静态初始化动作一样,这段代码只会执行一次

package charpter05;

class Cup {
    Cup(){
        System.out.println("Cup create");
    }
    static {
        int i = 47;
    }
}
public class test_5_7_3 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        new Cup();
    }
}
//Cup create

非静态实例初始化

{
    int i=45;
    String j="hello";
}

以上的写法在java当中也是允许的,可以使用块的形式来对非静态实例进行初始化

数组的初始化

如果没有没有使用花括号对数组进行初始化,那你获得的只是一个数组的引用,因此不允许指定数组的大小,如果使用花括号对数组进行初始化,那么必须在创建数组的地方出现

那为什么还可以直接创建数组的引用呢?因为在Java当中可以将一个数组赋值给另一个数组

package charpter05;

public class test_5_8 {
    public static void main(String[] args) {
        int[] a1= {1,2,3,4,5};
        int[] a2;
        a2=a1;
        for(int i=0;i<a2.length;i++) {
            a2[i]=a2[i]+1;
        }
        for(int i=0;i<a1.length;i++) {
            System.out.print(a1[i]+" ");
        }
    }
}
//2 3 4 5 6 

由这个例子可以看出,a2只是获得了对a1的引用,而不是复制这个数组

如果不确定数组里面到底有需要多少个元素,可以使用new关键字来创建固定大小的数组

package charpter05;

import java.util.Arrays;

public class test_5_8 {
    public static void main(String[] args) {
        int[] a1=new int[5];
        System.out.println(Arrays.toString(a1));
    }
}
//[0, 0, 0, 0, 0]

如果创建了一个非基本类型的数组,那就创建了一个引用数组,但它只是一个引用,通过创建新的对象,初始化进程才算结束,如果忘记创建对象,则会产生运行时异常,可以使用两种方式来进行初始化

package charpter05;

import java.util.Arrays;

public class test_5_8 {
    public static void main(String[] args) {
        //第一种方法,比较受限,只能在创建数组的地方使用
        Integer[] a1={new Integer(1),new Integer(2),new Integer(3)};
        Integer[] a2=new Integer[] {
                new Integer(1),
                new Integer(2),
                new Integer(3)};
        System.out.println(Arrays.toString(a1));
        System.out.println(Arrays.toString(a2));
    }
}
//[1, 2, 3]
//[1, 2, 3]

可变参数列表

由于所有的对象都直接或者间接的继承Object类,因此,我们可以以Object为数组为参数的方法使用

package charpter05;
import java.util.Arrays;
class A{}
public class test_5_8 {
    public static void printString(Object[] args) {
        for(Object obj:args) {
            System.out.print(obj+" ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        printString(new Integer[] {1,2,3});
        printString(new String[] {"hello","world"});
        printString(new A[3]);
    }
}
//1 2 3 
//hello world 
//charpter05.A@15db9742 charpter05.A@6d06d69c charpter05.A@7852e922 

由于这个A对象没有toString方法,因此默认打印类名@十六进制的方式。

除了以上的方式以外,还可以使用这样的方式来使用可变参数列表

package charpter05;
import java.util.Arrays;
class A{}
public class test_5_8 {
    public static void printString(Object... args) {
        for(Object obj:args) {
            System.out.print(obj+" ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        printString(new Integer[] {1,2,3});
        printString(new String[] {"hello","world"});
        printString(new A[3]);
        printString(new A(),new A(),new A());
    }
}
//1 2 3 
//hello world 
//null null null 
//charpter05.A@15db9742 charpter05.A@6d06d69c charpter05.A@7852e922 

不用显示的声明数组,但是传递的仍然是一个数组,如果传入的不是数组,编译器会自动将它转换成一个数组,并且也可以传递0个参数。

在具有尾随参数的时候,这样的方式更加完美

package charpter05;
import java.util.Arrays;
class A{}
public class test_5_8 {
    public static void printString(int number,String... args) {
        System.out.print(number+" ");
        for(String string1:args) {
            System.out.print(string1+" ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        printString(1,"hello");
        printString(2,"hello","world");
    }
}
//1 hello 
//2 hello world 

除了使用对象数组作为可变参数之外,还可以使用基本数据类型作为可变参数进行传递。

package charpter05;
import java.util.Arrays;
class A{}
public class test_5_8 {
    public static void printString(int... args) {
        System.out.print(args.getClass()+" ");
        for(int string1:args) {
            System.out.print(string1+" ");
        }
        System.out.println();
    }

    public static void main(String[] args) {
        printString(1,2,3,4,5);
        printString(2,3,4,5,6);
    }
}
//class [I 1 2 3 4 5 
//class [I 2 3 4 5 6 

在上面这个程序当中,使用了getClass()方法,这个方法会打印出类名,[表示这个一个数组,I表示这是一个整数基本类型。

可变参数列表的使得重载更加复杂,看起来可能不会有问题,但是在使用过程当中会产生许多问题,因此,在重载方法上最好只使用一个可变参数列表,或者不使用可变参数列表。

枚举类型

可以使用enum关键字来创建枚举类型,由于枚举类型是常量,因此经常以大写的方法表示。

为了使用枚举类型,需要创建一个该类型的引用,并将其赋值给某个实例

package charpter05;

enum SimplEnumUse{
    NOT,NILD,MEDIUM,HOT,FLAMING
}

public class test5_9 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        SimplEnumUse e1=SimplEnumUse.FLAMING;
        System.out.println(e1);
    }

}
//FLAMING

在创建枚举类型时,编译器会自动添加一些有用的功能,比如toString()方法,用于显示枚举实例的名字,使用ordenal()方法,表示某个特定枚举常量的声明顺序,使用static values()方法,用来按照枚举常量的声明顺序,产生由这些常量值构成的数组,并且枚举类型还可以直接使用switch语句。

package charpter05;

enum SimplEnumUse{
    NOT,NILD,MEDIUM,HOT,FLAMING
}

public class test5_9 {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        for(SimplEnumUse s:SimplEnumUse.values()) {
            System.out.println(s+",ordinal:"+s.ordinal());
        }
    }

}
//NOT,ordinal:0
//NILD,ordinal:1
//MEDIUM,ordinal:2
//HOT,ordinal:3
//FLAMING,ordinal:4
© 版权声明
THE END
喜欢就支持以下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容