《Java编程入门官方教程》第十三章练习答案

【练习13-1(IGenQ.java、QueueFullException.java、QueueEmptyException.java、GenQueue.java、GenQDemo.java)】创建一个泛型队列

泛型带给程序设计的最大好处之一就是能够创建可靠、可重用的代码。如本章开头所述,许多算法不管使用的数据类型是什么、算法逻辑都是相同的。例如,队列的工作方式对于整数、字符串或File对象都是相同的。不必为每一种类型的对象分别创建独立的队列类,创建单个通用的解决方案就可以使用任何类型的对象。这样,设计、编码、测试和调试的开发过程可以一次完成,而不必在每次队列需要一种新数据类型时重复进行。

本练习将把从练习5-2开始开发的队列示例改进为泛型队列,以便最终完成这个队列程序。该程序包括一个定义了队列操作的泛型接口、两个异常类和一种队列实现方式:固定大小的队列。当然,读者也可以试验其他类型的泛型队列,如泛型动态队列或泛型循环队列,只要在本练习的基础上改进即可。

同前面的练习9-1中开发的队列一样,本练习也将队列组织到一组单独的文件中:一个代表接口,一个代表队列异常类,一个代表固定队列的实现方式,一个代表演示队列的程序。这种组织方式仿照了实际环境中的项目组织方式。

package javaone.a.beginners.guide.chapterthirteen;


// A generic queue interface.
interface IGenQ<T>{
    // Put an item into the queue.
    void put(T ch) throws QueueFullException;

    // Get an item from the queue.
    T get() throws QueueEmptyException;;
}

// An exception for queue-full errors.
class QueueFullException extends Exception{
    int size;
    QueueFullException(int s){
        size = s;
    }
    public String toString(){
        return "\nQueue is full. Maximum size is " + size;
    }
}

// An exception for queue-empty errors.
class QueueEmptyException extends Exception{
    public String toString(){
        return "\nQueue is empty.";
    }
}

// A generic, fixed-size queue class.
class GenQueue<T> implements IGenQ<T>{
    private T q[];  // this array holds the queue
    private int putloc, getloc; // the put and get indices
    // Construct an empty queue with the given array.
    public GenQueue(T[] aRef){
        q = aRef;
        putloc = getloc = 0;
    }
    // Put an item into the queue.
    public void put(T ch) throws QueueFullException{
        if(putloc == q.length){
            throw new QueueFullException(q.length);
        }
        q[putloc++] = ch;
    }
    // Get a character from the queue.
    public T get() throws QueueEmptyException{
        if(getloc == putloc){
            throw new QueueEmptyException();
        }
        return q[getloc++];
    }
}
/*
    Try This 13-1
    Demonstrate a generic queue class.
 */
public class ChapterThirteenProgramOne {

    public static void main(String[] args) {
        // Create an integer queue.
        Integer iStore[] = new Integer[10];
        GenQueue<Integer> q = new GenQueue<Integer>(iStore);

        Integer iVal;
        System.out.println("Demonstrate a queue of Integers.");
        try{
            for (int i = 0; i < 5; i++) {
                System.out.println("Adding " + i + " to q.");
                q.put(i);   // add integer value to q
            }
        }catch (QueueFullException exc){
            System.out.println(exc);
        }
        System.out.println();
        try{
            for (int i = 0; i < 5; i++) {
                System.out.print("Getting next Integer from q: ");
                iVal = q.get();
                System.out.println(iVal);
            }
        }catch (QueueEmptyException exc){
            System.out.println(exc);
        }
        System.out.println();

        // Create a Double queue.
        Double dStore[] = new Double[10];
        GenQueue<Double> qTwo = new GenQueue<Double>(dStore);
        Double dVal;
        System.out.println("Demonstrate a queue of Doubles.");
        try{
            for (int i = 0; i < 5; i++) {
                System.out.println("Adding " + (double)i/2 + " to qTwo.");
                qTwo.put((double)i/2);
            }
        }catch (QueueFullException exc){
            System.out.println(exc);
        }
        System.out.println();
        try{
            for (int i = 0; i < 5; i++) {
                System.out.print("Getting next Double from qTwo: ");
                dVal = qTwo.get();
                System.out.println(dVal);
            }
        }catch (QueueEmptyException exc){
            System.out.println(exc);
        }
    }

}

13.15 自测题

1. 泛型是Java添加的一项重要功能,因为它使得代码的创建:

A. 类型安全

B. 可重用

C. 可靠

D. 以上都对

答案:D

2. 基本类型能用作类型实参吗?

答案: 不能,类型实参必须是对象类型。

3. 说明如何声明一个名为FlightSched的类,它带有两个泛型形参。

答案:class FlightSched<T, V> {

4. 对于自测题3,修改FlightSched的第二个类型形参,使得它必须扩展Thread。

答案:class FlightSched<T, V extends Thread>

5. 现在,修改FlightSched的第二个类型形参,使它成为第一个类型形参的子类。

答案:class FlightSched<T, V extends T>

6. 就泛型而言,"?"代表什么?它的作用是什么?

答案:“?"是通配符实参,能匹配任何有效的类型。

7. 可以约束通配符实参吗?

答案:可以,通配符实参既可以有上层约束,也可以有下层约束。

8. 泛型方法MyGen()带有一个类型形参。而且,MyGen()带有一个其类型与该类型形参相同的形参。它还返回该类型形参的对象。写出如何声明MyGen()。

答案: <T> T MyGen(T o) { 

9. 对于下面的泛型接口:

interface IGenIF<T, V extends T> { // ...

提供实现IGenIF的MyClass类的声明。

答案: class MyClass<T, V extends T> implements IGenIF<T, V> { // ...

10. 对于泛型类Counter<T>,说明如何创建一个其原类型的对象。

答案:要获得Counter<T>的原类型,在不带任何类型规范的情况下只需要使用其名称即可,如下所示:

Counter x = new Counter();

11. 类型形参在运行时存在吗?

答案:不存在,所有的类型形参在编译时都被擦除,由合适的强制转换替代。这一过程称为擦除。

12. 把第9章自测题10中的解决方案 转换为泛型解决方案。在转换过程中,创建一个以泛型方式定义操作push()和pop()的堆栈接口IGenStack。

package javaone.a.beginners.guide.chapterthirteen;

// A generic stack.
interface IGenStack<T> {
    void push(T t) throws StackFullException;
    T pop() throws StackEmptyException;
}

// An exception for stack-full errors.
class StackFullException extends Exception {
    int size;
    StackFullException(int s) {
        size = s;
    }
    public String toString() {
        return "\nStack is full. Maximum size is " +size;
    }
}

// An exception for stack-empty errors.
class StackEmptyException extends Exception {
    public String toString() {
        return "\nStack is empty.";
    }
}

// A stack class for characters.
class GenStack<T> implements IGenStack<T> {
    private T stck[];   // this array holds the stack
    private int tos;    // top of stack
    // Construct an empty stack given its size.
    GenStack(T[] stckArray){
        stck = stckArray;
        tos = 0;
    }
    // Construct a stack from a stack
    GenStack(T[] stackArray, GenStack<T> ob){
        tos = ob.tos;
        stck = stackArray;
        try {
            if(stck.length < ob.stck.length){
                throw new StackFullException(stck.length);
            }
        }catch (StackFullException exc){
            System.out.println(exc);
        }
        // copy elements.
        for (int i = 0; i < tos; i++) {
            stck[i] = ob.stck[i];
        }
    }
    // Construct a stack with initial values.
    GenStack(T[] stackArray, T[] a){
        stck = stackArray;
        for (int i = 0; i < a.length; i++) {
            try {
                push(a[i]);
            }catch (StackFullException exc){
                System.out.println(exc);
            }
        }
    }
    // Pusg objects onto the stack.
    public void push(T obj) throws StackFullException {
        if(tos == stck.length){
            throw new StackFullException(stck.length);
        }
        stck[tos] = obj;
        tos++;
    }
    // Pop an object from the stack.
    public T pop() throws StackEmptyException {
        if(tos == 0){
            throw new StackEmptyException();
        }
        tos--;
        return stck[tos];
    }
}
// Demonstrate the GenStack class.
public class ChapterThirteenExerciseTwelve {

    public static void main(String[] args) {
        // Construct 10-element empty Integer stack.
        Integer iStore[] = new Integer[10];
        GenStack<Integer> stkOne = new GenStack<Integer>(iStore);
        // Construct stack from array.
        String name[] = {"One","Two","Three"};
        String strStore[] = new String[3];
        GenStack<String> stkTwo = new GenStack<String>(strStore,name);

        String str;
        int n;
        try{
            // Put some values into stkOne
            for (int i = 0; i < 10; i++) {
                stkOne.push(i);
            }
        }catch (StackFullException exc){
            System.out.println(exc);
        }
        // Construct stack from another stack.
        String strStoreTwo[] = new String[3];
        GenStack<String> stkThree = new GenStack<String>(strStoreTwo,stkTwo);
        try{
            // Show the stacks.
            System.out.print("Contents of stkOne: ");
            for (int i = 0; i < 10; i++) {
                n = stkOne.pop();
                System.out.print(n + " ");
            }
            System.out.println("\n");
            System.out.print("Contents of stkTwo: ");
            for (int i = 0; i < 3; i++) {
                str = stkTwo.pop();
                System.out.print(str + " ");
            }
            System.out.println("\n");
            System.out.print("Contents of stkThree: ");
            for (int i = 0; i < 3; i++) {
                str = stkThree.pop();
                System.out.print(str + " ");
            }
        }catch (StackEmptyException exc){
            System.out.println(exc);
        }
        System.out.println();
    }

}

13. <>是什么?

答案:是菱形运算符用于类型推断。

14. 如何简化下面的语句?

MyClass<Double, String> obj = new MyClass<Double, String>(1.1, "Hi");

答案:

MyClass<Double, String> obj = new MyClass<>(1.1, "Hi");

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值