think in java-3:初始化与清理

1.构造器与初始化

    创建对象时,如果没有显性的创建构造器,则jvm会创建一个默认的无参构造器,如果创建了构造器,那么jvm将不在创建构造器。

    构造器:与类名相同,无返回值。

public class Construct {
    public static void main(String[] args) {
        Rock r = new Rock();
        Rock1 r1 = new Rock1();
        Rock2 r2 = new Rock2(11);
    }
}
//默认构造器
class Rock {}
//手动添加无参构造器
class Rock1 {
    public Rock1() {
        System.out.println("无参构造");
    }
}
//有参构造器
class Rock2{
    public Rock2(int i){
        System.out.println(i);
    }
}

2.方法重载

    方法重载:指方法名相同,参数列表不同。如有参构造与无参构造,即为方法重载。不能以返回值区分是否为重载方法。

    2.1基本类型的方法重载:

        所传参数类型与方法类型相同,则调用与之匹配的方法。

        所传参数类型小于方法中参数类型,则匹配与之容量最近的方法,char类型比较特殊,char类型作为参数传递,会默认提升为int类型

        所传参数类型大于方法中参数类型,则需将所传参数类型进行强制转换,否则编译不通过。

3.this关键字

    如果想在方法内部获得当前对象可使用this关键字,this关键字只能存在于方法内部,表示当前对对象的引用。

    3.1 方法内部调用this:可以直接return this返回当前对象

    3.2 构造函数调用

public class Flower {
    public static void main(String[] args) {
        Worker wk = new Worker("玫瑰",999);//输出结果,先输出"无花之人",在输出"采了999花",最后输出"采了999玫瑰花"

    }
}
class Worker{
    Worker(){
        System.out.println("无花之人");
    }
    Worker(int i){
        this();
        System.out.println("采了"+i+"花");
    }
    Worker(String name,int i){
        this(i);
        System.out.println("采了"+i+name+"花");
    }
}

    调用构造函数时,会根据this()传递的参数,自动匹配含有对应参数的构造函数。

4.static关键字

    static修饰静态变量或方法,在创建对象前就已经被创建,且只存在一份,不能调用非static修饰的变量或方法,不存在this关键字,不需要创建对象。

5.清理及垃圾回收。

    5.1finalize的用途,一旦垃圾回收准备好释放对象占用的存储空间,将首先调用finalize()方法,并且在下一次垃圾回收动作发生时,才会真正回收对象点用的内存。    

public class FinizeTest  {
    public static void main(String[] args) {
        new FinalizeCase();
        System.gc();
    }
}
class FinalizeCase{
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("执行了垃圾回收");
    }
}

        重写finalize方法,调用父类的finalize(),当只是通过new FinalizeCase()创建对象时,并没有引用指向对象,此时等着垃圾回收来回收此对象,但是垃圾回收发生是不定时的,无法控制,故我们通过调用System.gc()方法强制进行垃圾回收,通过输出可以看到,finalize()方法执行了。所以我们不能全指望垃圾回收处理,当某些必须关闭回收的对象,我们可以自己书写代码进行关闭。

    5.2 垃圾回收原理

        其它系统中的垃圾回收:每个对象者含有一个引用计数器,当对象有引用连接时,引用计数器加1,当对象无引用连接时,则计数器减1,直至减少为0,则该对象就将会被回收。

        java虚拟机采用一种更自适应的垃圾回收技术,对于查找活的对象,通过停止-复制、标记-清扫方法进行。

        标记-清扫:指从堆栈和静态存储区出发,遍历所有的引用,进行找出所有存活的对象,每当找到一个存活的对象,就会给对象进行一个标记,这个过程不会对回收任何对象,只有全部标记工作完成的时候,清理动作才会开始,在清理过程中,没有标记的对象不会被复制,直接释放空间,所以剩下的堆空间是不连续的,如果要得到连续的空间,则需要进行重新整理。

        停止-复制:指拉圾回收器进行工作时,程序将停止运行,然后将活的对象复制到另一片区域中去,且按顺序进行排列,将变量引用指向新地址,此种方法复制需要更大的内存区域,效率比较低下。

6.成员初始化

    对象中成员初始化:如果存在静态变量,则先初始化静态变量,然后初始化成员变量,在进行构造函数初始化。如果存在继承关系,首先初始化父类静态变量,在初始化子类静态变量,在初始化父类成员变量,在进行父类构造函数初始化,在初始化子类成员变量,子类构造函数初始化。

       1.成员初始化

public class OrderInitialization {
    public static void main(String[] args) {
        House house = new House();//输出首先执行属性初始化,即先创建窗户1,然后在窗户2,在窗户3,在执行构造函数

    }

}
class Window{
    Window(int i){
        System.out.println("window:("+i+")");
    }
}
class House{
    Window w1= new Window(1);
    House(){
        System.out.println("this is house");
        Window w3 = new Window(3);
    }
    Window w2 = new Window(2);
    Window w3 = new Window(3);
}

       2.静态数据实始化

              静态数据实始化:先执行静态成员变量实始化,且静态成员只会执行一次,在执行实例化成员,在执行构造函数。

        3.显示静态实初始化

              多个含有static关键字的子名:静态成员,静态块执行根据书写顺序执行,且一旦静态成员被访问,则其它静态成员同样会被初始化。

public class StaticInit {
    public static void main(String[] args) {
        Table table = new Table();
        System.out.println("***************");
        Table table1 = new Table();

        /** 输出如下,静态成员只执行一次
        cup(1)
        cup(2)
        cup(3)
        table
        cup(33)
        ***************
        cup(3)
        table
        cup(33)
        * */
    }
}
class Cup{
    Cup(int i){
        System.out.println("cup("+i+")");
    }
}
class Table{
    static  Cup cup1 = new Cup(1);
    Cup cup3 = new Cup(3);
    Table(){
        System.out.println("table");
        cup3 = new Cup(33);
    }
    static Cup cup2 = new Cup(2);
}

        4.初始化块,对象中通过{}包裹需要执行的方法,每创建一个对象 ,就会执行一次初始化块中代码

public class InitBlock {
    private String name;
    private String price;
    {
        System.out.println( "name = 华为");
        System.out.println( " price=4000");
    }

    public static void main(String[] args) {
        InitBlock ib = new InitBlock();
        InitBlock ib1 = new InitBlock();
        /**输出
         name = 华为
         price=4000
         name = 华为
         price=4000
         */
    }
}

    5.父子类初始化顺序 

public class FatherAndSonInit {
    public static void main(String[] args) {
        Son son = new Son();
    }
    //父子类初始化顺序,父类static,子类static,父类成员实始化,父类构造函数,子类成员初始化,子类构造函数
    /**输出结果
     * father static:Peple--父类静态
     * Son static:Peple -- 子类静态
     * father man :man -- 父类成员变量
     * father --父类构造函数输出
     * Son man:man -- 子类成中变量
     * Son -- 子类构造函数输出
     */
}
class Peple1{
    Peple1(String s){
        System.out.println(s+":Peple");
    }
}
class Man{
    Man(String s){
        System.out.println(s+":man");
    }
}
class Father{
    static Peple1 p1 = new Peple1("father static");
    Father(){
        System.out.println("father");
    }
    Man m = new Man("father man ");
}
class Son extends Father{
    static Peple1 p1 = new Peple1("Son static");
    Son(){
        System.out.println("Son");
    }
    Man m = new Man("Son man");
}

7.数组初始化

public static void main(String[] args) {
    int[]  i = new int[6];
    String[] s = new String[]{"one","tow","three"};
    double[] d = {1d,2d,3d,4d};
    for (int i1 : i) {
        System.out.println(i1);//第一种方式创建,未给初始值,默认为0,如果引用类型,则默认为null
    }
}

    数组中存入的是对象的引用,如果存入的是基本数据类型,则对应的会得到基本数据类型对应的初始值。

8.可变参数

public static void main(String[] args) {
    testVar(new String[]{"one","tow","three"},13,new Integer[]{1,2,3,4,5});

}
public  static void testVar(Object... args){
    for (Object arg : args) {
        System.out.println(arg);
    }
}

    可变参数的基本形式为(数据类型... args),表示传递不定多个形式参数,如果需要传递固定多个形式参数,则需要将固定的形式参数放至参数前边。

9.枚举    

public enum EnumTest {
    NOT,MILD,MEDIUM,HOT,FLAMING;
    public static void main(String[] args) {
        //可以直接调用
        System.out.println(EnumTest.FLAMING);
        //可以获得其下标和具体的内容
        for (EnumTest enumTest : EnumTest.values()) {
            System.out.println(enumTest.ordinal()+":"+enumTest);
            /** 输出
             0:NOT
             1:MILD
             2:MEDIUM
             3:HOT
             4:FLAMING
             */
        }
    }
}

基本用法如上,可以定义某些常量,然后直接调用其结果

用法二:    

public enum  EmunCalss {
    BEIJIN("001"),SHANGHAI("021"),GUANGDONG("020"),CQINGQING("023");
    private String value;
    EmunCalss(String value){
        this.value = value;
    }
    public static void main(String[] args) {
        for (EmunCalss emunCalss : EmunCalss.values()) {
            System.out.println("name:"+emunCalss.name()+", value:"+emunCalss.value);
        }
        /**输出,定义的前边部位为name,可以在枚举中定义一个变量,得其值
         name:BEIJIN, value:001
         name:SHANGHAI, value:021
         name:GUANGDONG, value:020
         name:CQINGQING, value:023
         */
    
    }

}


猜你喜欢

转载自blog.csdn.net/qq_37317845/article/details/80685097