• 关于初始化和清理


    1. this者谁?

    // housekeeping/PassingThis.java
    
    class Person {
        public void eat(Apple apple) {
            Apple peeled = apple.getPeeled();
            System.out.println("Yummy");
        }
    }
    
    public class Peeler {
        static Apple peel(Apple apple) {
            // ... remove peel
            return apple; // Peeled
        }
    }
    
    public class Apple {
        Apple getPeeled() {
            return Peeler.peel(this);
        }
    }
    
    public class PassingThis {
        public static void main(String[] args) {
            new Person().eat(new Apple());
        }
    }

    this简单来讲即使谁调代表谁,上面的代码就是this的一种用法,将自身引用传递出去。

    this的另一个常用地方就是this.super()等这种构造器中调用构造器,可以大量减少重复代码。

    // housekeeping/Flower.java
    // Calling constructors with "this"
    
    public class Flower {
        int petalCount = 0;
        String s = "initial value";
    
        Flower(int petals) {
            petalCount = petals;
            System.out.println("Constructor w/ int arg only, petalCount = " + petalCount);
        }
    
        Flower(String ss) {
            System.out.println("Constructor w/ string arg only, s = " + ss);
            s = ss;
        }
    
        Flower(String s, int petals) {
            this(petals);
            //- this(s); // Can't call two!
            this.s = s; // Another use of "this"
            System.out.println("String & int args");
        }
    
        Flower() {
            this("hi", 47);
            System.out.println("no-arg constructor");
        }
    
        void printPetalCount() {
            //- this(11); // Not inside constructor!
            System.out.println("petalCount = " + petalCount + " s = " + s);
        }
    
        public static void main(String[] args) {
            Flower x = new Flower();
            x.printPetalCount();
        }
    }

    这里的构造调用构造有两点要求,1是必须在开头调用,2是只能调用一个构造器(否则它就违背了第一点)。

    2. static者谁?

    它是为类创建的不是为对象创建的,听起来很别扭,但事实如此,因为它是不需要对象的支撑来调用的,这点和必须要有对象支撑的this截然相反,所以static中不能有this。它有点全局的语义,但是java并没有全局,所以它也是饱受人质疑的一点,它是否破坏了面向对象这个概念,我个人觉着是有一些的。

    3. 垃圾回收

    Java是有自己GC的,finalize()方法一般是不建议主动用的,我们需要关注的点应该是对象的引用上,比如链表,我们用数组实现的话,remove掉一个node,我们需要将该node的指针置为null。下面有一个手动gc的例子。

    // housekeeping/TerminationCondition.java
    // Using finalize() to detect a object that
    // hasn't been properly cleaned up
    
    import onjava.*;
    
    class Book {
        boolean checkedOut = false;
    
        Book(boolean checkOut) {
            checkedOut = checkOut;
        }
    
        void checkIn() {
            checkedOut = false;
        }
    
        @Override
        protected void finalize() throws Throwable {
            if (checkedOut) {
                System.out.println("Error: checked out");
            }
            // Normally, you'll also do this:
            // super.finalize(); // Call the base-class version
        }
    }
    
    public class TerminationCondition {
    
        public static void main(String[] args) {
            Book novel = new Book(true);
            // Proper cleanup:
            novel.checkIn();
            // Drop the reference, forget to clean up:
            new Book(true);
            // Force garbage collection & finalization:
            System.gc();
            new Nap(1); // One second delay
        }
    
    }

    4. 初始化,这块很基础了,就直接post代码了

    // housekeeping/OrderOfInitialization.java
    // Demonstrates initialization order
    // When the constructor is called to create a
    // Window object, you'll see a message:
    
    class Window {
        Window(int marker) {
            System.out.println("Window(" + marker + ")");
        }
    }
    
    class House {
        Window w1 = new Window(1); // Before constructor
    
        House() {
            // Show that we're in the constructor:
            System.out.println("House()");
            w3 = new Window(33); // Reinitialize w3
        }
    
        Window w2 = new Window(2); // After constructor
    
        void f() {
            System.out.println("f()");
        }
    
        Window w3 = new Window(3); // At end
    }
    
    public class OrderOfInitialization {
        public static void main(String[] args) {
            House h = new House();
            h.f(); // Shows that construction is done
        }
    }

    输出

    Window(1)
    Window(2)
    Window(3)
    House()
    Window(33)
    f()

    静态数据初始化

    // housekeeping/StaticInitialization.java
    // Specifying initial values in a class definition
    
    class Bowl {
        Bowl(int marker) {
            System.out.println("Bowl(" + marker + ")");
        }
    
        void f1(int marker) {
            System.out.println("f1(" + marker + ")");
        }
    }
    
    class Table {
        static Bowl bowl1 = new Bowl(1);
    
        Table() {
            System.out.println("Table()");
            bowl2.f1(1);
        }
    
        void f2(int marker) {
            System.out.println("f2(" + marker + ")");
        }
    
        static Bowl bowl2 = new Bowl(2);
    }
    
    class Cupboard {
        Bowl bowl3 = new Bowl(3);
        static Bowl bowl4 = new Bowl(4);
    
        Cupboard() {
            System.out.println("Cupboard()");
            bowl4.f1(2);
        }
    
        void f3(int marker) {
            System.out.println("f3(" + marker + ")");
        }
    
        static Bowl bowl5 = new Bowl(5);
    }
    
    public class StaticInitialization {
        public static void main(String[] args) {
            System.out.println("main creating new Cupboard()");
            new Cupboard();
            System.out.println("main creating new Cupboard()");
            new Cupboard();
            table.f2(1);
            cupboard.f3(1);
        }
    
        static Table table = new Table();
        static Cupboard cupboard = new Cupboard();
    }

    输出

    Bowl(1)
    Bowl(2)
    Table()
    f1(1)
    Bowl(4)
    Bowl(5)
    Bowl(3)
    Cupboard()
    f1(2)
    main creating new Cupboard()
    Bowl(3)
    Cupboard()
    f1(2)
    main creating new Cupboard()
    Bowl(3)
    Cupboard()
    f1(2)
    f2(1)
    f3(1)

    显示的静态初始化

    // housekeeping/ExplicitStatic.java
    // Explicit static initialization with "static" clause
    
    class Cup {
        Cup(int marker) {
            System.out.println("Cup(" + marker + ")");
        }
    
        void f(int marker) {
            System.out.println("f(" + marker + ")");
        }
    }
    
    class Cups {
        static Cup cup1;
        static Cup cup2;
    
        static {
            cup1 = new Cup(1);
            cup2 = new Cup(2);
        }
    
        Cups() {
            System.out.println("Cups()");
        }
    }
    
    public class ExplicitStatic {
        public static void main(String[] args) {
            System.out.println("Inside main()");
            Cups.cup1.f(99); // [1]
            Cups.cup1.f(99); // [1]
        }
    
        // static Cups cups1 = new Cups(); // [2]
        // static Cups cups2 = new Cups(); // [2]
    }

    输出

    Inside main()
    Cup(1)
    Cup(2)
    f(99)
    f(80)

    非静态的初始化

    // housekeeping/Mugs.java
    // Instance initialization
    
    class Mug {
        Mug(int marker) {
            System.out.println("Mug(" + marker + ")");
        }
    }
    
    public class Mugs {
        Mug mug1;
        Mug mug2;
        { // [1]
            mug1 = new Mug(1);
            mug2 = new Mug(2);
            System.out.println("mug1 & mug2 initialized");
        }
    
        Mugs() {
            System.out.println("Mugs()");
        }
    
        Mugs(int i) {
            System.out.println("Mugs(int)");
        }
    
        public static void main(String[] args) {
            System.out.println("Inside main()");
            new Mugs();
            System.out.println("new Mugs() completed");
            new Mugs(1);
            System.out.println("new Mugs(1) completed");
        }
    }

    输出,这里因为不是静态,所以基本每次都要重新把类的初始化流程走一遍

    Inside main
    Mug(1)
    Mug(2)
    mug1 & mug2 initialized
    Mugs()
    new Mugs() completed
    Mug(1)
    Mug(2)
    mug1 & mug2 initialized
    Mugs(int)
    new Mugs(1) completed

    5. 对于可变参数的重载

    // housekeeping/OverloadingVarargs2.java
    // {WillNotCompile}
    
    public class OverloadingVarargs2 {
        static void f(float i, Character... args) {
            System.out.println("first");
        }
    
        static void f(Character... args) {
            System.out.println("second");
        }
    
        public static void main(String[] args) {
            f(1, 'a');
            f('a', 'b');
        }
    }

    这段代码是编译不过的,因为不知道该调用哪个,这也是重载的一个常犯的错误,不过好处是编译就会发现这个错误不会产生事故。

    // housekeeping/OverloadingVarargs3
    
    public class OverloadingVarargs3 {
        static void f(float i, Character... args) {
            System.out.println("first");
        }
    
        static void f(char c, Character... args) {
            System.out.println("second");
        }
    
        public static void main(String[] args) {
            f(1, 'a');
            f('a', 'b');
        }
    }

    这样处理就可以了。

    6. 枚举类型,其实枚举的用处和性能很强,应该多用,比如替代掉比较传统的常量接口,后者对代码太具有污染性了

    // housekeeping/Spiciness.java
    
    public enum Spiciness {
        NOT, MILD, MEDIUM, HOT, FLAMING
    }
    // housekeeping/SimpleEnumUse.java
    
    public class SimpleEnumUse {
        public static void main(String[] args) {
            Spiciness howHot = Spiciness.MEDIUM;
            System.out.println(howHot);
        }
    }

    MEDIUM
    // housekeeping/EnumOrder.java
    
    public class EnumOrder {
        public static void main(String[] args) {
            for (Spiciness s: Spiciness.values()) {
                System.out.println(s + ", ordinal " + s.ordinal());
            }
        }
    }
    
    
    NOT, ordinal 0
    MILD, ordinal 1
    MEDIUM, ordinal 2
    HOT, ordinal 3
    FLAMING, ordinal 4

    enum还与switch绝配

    // housekeeping/Burrito.java
    
    public class Burrito {
        Spiciness degree;
    
        public Burrito(Spiciness degree) {
            this.degree = degree;
        }
    
        public void describe() {
            System.out.print("This burrito is ");
            switch(degree) {
                case NOT:
                    System.out.println("not spicy at all.");
                    break;
                case MILD:
                case MEDIUM:
                    System.out.println("a little hot.");
                    break;
                case HOT:
                case FLAMING:
                default:
                    System.out.println("maybe too hot");
            }
        }
    
        public static void main(String[] args) {
            Burrito plain = new Burrito(Spiciness.NOT),
            greenChile = new Burrito(Spiciness.MEDIUM),
            jalapeno = new Burrito(Spiciness.HOT);
            plain.describe();
            greenChile.describe();
            jalapeno.describe();
        }
    }
    一个没有高级趣味的人。 email:hushui502@gmail.com
  • 相关阅读:
    统一Windows Azure和一般web应用之间的文件操作代码(转+译)
    Windows Azure真实案例Lokad 公司通过软件+服务高效提供先进的预测服务
    Windows Azure Marketplace入门教学利用TabLeau Public构建可视化DataMarket应用
    SQL Azure 一款强大的管理工具 Houston CTP 1(转+译)
    Windows Azure真实案例:Invensys Operations Management 公司使用Windows Azure AppFabric 实现动态节能的智能电网
    开始Azure之旅,参加深度培训 (转)
    Windows Azure Marketplace入门教学通过代码操作DataMarket数据源
    Windows Azure真实案例:Infosys Technologies 使用SQL Data Services(现为SQL Azure)为汽车经销商创建了基于云的方案
    Windows Azure Marketplace入门教学 DataMarket for Excel插件
    Windows Azure AppFabric Caching入门简介
  • 原文地址:https://www.cnblogs.com/CherryTab/p/11923319.html
Copyright © 2020-2023  润新知