《TIJ4》访问权限控制 练习 E08 拓展:创建一个更复杂的ConnectionManager

题目

创建一个名为ConnectionManager的类,该类管理一个元素为Connection对象的固定数组。客户端程序员不能直接创建Connection对象,而只能通过ConnectionManager的某个static方法获取它们。当ConnectinManager不再有对象时,它会返回null引用,要允许客户端程序员使用完Connection之后归还它。在main()中检测这些类。

我的解答

刚开始是没有思路的,在参考了答案之后,自己默写出来的代码如下。

package access;

import access.connection2.my.Connection;
import access.connection2.my.ConnectionManager;

public class E08_ConnectionManager2_My {

    public static void main(String[] args) {
        System.out.println("Get 5 connections.");
        Connection[] connections = new Connection[5];
        for (int i = 0; i < connections.length; i++) {
            connections[i] = ConnectionManager.getConnection();
            System.out.println(connections[i].toString());
        }
        System.out.println("Check in 2 connections");
        System.out.println("Check in " + connections[1].toString());
        connections[1].checkIn();
        System.out.println("Check in " + connections[4].toString());
        connections[4].checkIn();
        System.out.println("Get remaining connections.");
        Connection[] remainingConnections = new Connection[7];
        for (int i = 0; i < remainingConnections.length; i++) {
            remainingConnections[i] = ConnectionManager.getConnection();
            System.out.println(remainingConnections[i].toString());
        }
    }
}

/* Output:
Get 5 connections.
Connection 0
Connection 1
Connection 2
Connection 3
Connection 4
Check in 2 connections
Check in Connection 1
Check in Connection 4
Get remaining connections.
Connection 1
Connection 4
Connection 5
Connection 6
Connection 7
Connection 8
Connection 9
*/

package access.connection2.my;

public class Connection {

    private static int counter = 0;
    private int id = counter++;

    Connection(){}

    @Override
    public String toString() {
        return "Connection " + id;
    }

    public void doSomething(){
        //Todo
    }

    public void checkIn(){
        ConnectionManager.checkIn(this);
    }
}

package access.connection2.my;

public class ConnectionManager {

    private static Connection[] pool = new Connection[10];

    static {
        for (int i = 0; i < pool.length; i++) {
            pool[i] = new Connection();
        }
    }

    public static Connection getConnection() {
        for (int i = 0; i < pool.length; i++) {
            if (pool[i] != null) {
                Connection c = pool[i];
                pool[i] = null; //表示被取出
                return c;
            }
        }
        return null;    //都被取出
    }

    public static void checkIn(Connection c) {
        for (int i = 0; i < pool.length; i++) {
            if (pool[i] == null) {
                pool[i] = c;
                return;
            }
        }
    }
}

而参考答案代码如下:

package access;

import access.connection2.bruce.Connection;
import access.connection2.bruce.ConnectionManager;

public class E08_ConnectionManager2_Bruce {
    public static void main(String[] args) {
        Connection[] ca = new Connection[10];
        // Use up all the connections
        for (int i = 0; i < 10; i++) {
            ca[i] = ConnectionManager.getConnection();
            // Should produce "null" since there are no more connections:
        }
        System.out.println(ConnectionManager.getConnection());
        // Return connections, then get them out:
        for (int i = 0; i < 5; i ++){
            ca[i].checkIn();
            Connection c = ConnectionManager.getConnection();
            System.out.println(c);
            c.doSomething();
            c.checkIn();
        }
    }
}

/* Output:
null
Connection 0
Connection 0
Connection 0
Connection 0
Connection 0
*/


package access.connection2.bruce;

public class Connection {
    private static int counter = 0;
    private int id = counter++;
    Connection(){}
    public String toString() {
        return "Connection " + id;
    }
    public void doSomething(){}
    public void checkIn(){
        ConnectionManager.checkIn(this);
    }
}

package access.connection2.bruce;

public class ConnectionManager {
    private static Connection[] pool = new Connection[10];
    static {
        for (int i = 0; i < pool.length; i++) {
            pool[i] = new Connection();
        }
    }
    // Produce the first available connection
    public static Connection getConnection() {
        for (int i = 0; i < pool.length; i++) {
            if (pool[i] != null) {
                Connection c = pool[i];
                pool[i] = null; // Indicates "in use"
                return c;
            }
        }
        return null; // None left
    }
    public static void checkIn(Connection c) {
        for (int i = 0; i < pool.length; i++) {
            if (pool[i] == null) {
                pool[i] = c; // Check it back in
                return;
            }
        }
    }
}

容易犯错的地方:

  1. private int id = counter++; 由于counter是static变量,因此,所有类的对象共享1个counter,而每个对象生成时,成员变量id要初始化,这句代码依次做了两件事:一、id被初始化为0, 1, 2, 3, ... 。二、counter自增1。
  2. Connection(){} 这里显示声明了构造方法,而访问权限是默认的包访问权限,只有同一个包下的类能调用,对于客户端程序员是不可用的。
  3. private static Connection[] pool = new Connection[10]; 要注意new Connection[10]与new Connection()的区别,这里在初始化pool时只是初始化了空的引用,而每个引用并不指向实际的对象。
  4. 注意学习作者测试方法main()的思路,先取出所有connection, 然后依次归还5个的connection,分别是Connection 0, Connection 1, Connection 2, Connection 3, Connection 4,在每次归还后都要再取一个可用的Connection,第一次归还的是Connection 0,取出的也是Connection 0, 使用之后再次把Connection 0 归还,因此第二趟循环,归还的是Connection 1,在取时由于pool[0]的位置是可以取Connection的,所以取出的依旧是Connection 0;
posted @ 2018-03-14 15:17  庄浩  阅读(562)  评论(0编辑  收藏  举报