是不是可以使用泛型的基于数组的队列?

时间:2015-09-12 08:02:49

标签: java arrays generics

这是一个基于数组的队列,用于int

/**
 * Array based
 * @author X220
 *
 */

public class MyQueue {

    private int[] _data;
    private int MAX_SIZE;
    private int front = -1;
    private int back = 0;
    private int elementsCount = 0;

    public void printQueue()
    {
        int j = this.front + 1;
        int i = 0;
        while (i < this._data.length && i < elementsCount)
        {
            System.out.println("At location " + j % MAX_SIZE + " element :" + this._data[j % MAX_SIZE]);
            j++;
            i++;
        }
    }

    public MyQueue(int _size)
    {
        MAX_SIZE = _size > 0 ? _size : 10;
        this._data = new int[MAX_SIZE];
    }

    public boolean IsEmpty()
    {
        return this.elementsCount == 0;     
    }

    public boolean IsFull()
    {
        return this.elementsCount == MAX_SIZE;
    }

    public void Push(int pushMe) throws QueueIsFullException
    {
        if (IsFull())
        {
            throw new QueueIsFullException("Queue is full");
        }
        this.elementsCount++;
        _data[back++ % MAX_SIZE] = pushMe;
    }

    public int Pop() throws QueueIsEmptyException 
    {
        if (IsEmpty())
        {
            throw new QueueIsEmptyException("Queue is full");
        }
        elementsCount--;
        return _data[++front % MAX_SIZE];
    }

    public static void main(String args[])
    {
        try
        {
            MyQueue q1 = new MyQueue(15);
            q1.Push(1);
            q1.Push(2);
            q1.Push(3);
            q1.Push(4);
            q1.Push(5);
            q1.Pop();
            q1.Pop();
            q1.Pop();
            q1.Pop();
            q1.Pop();
            q1.Push(6);
            q1.Pop();
            q1.Push(7);
            q1.Push(8);
            q1.Push(9);
            q1.Push(10);
            q1.Push(11);
            q1.Push(12);


//          q1.Push(1);
//          q1.Push(2);
//          q1.Push(3);
//          q1.Push(4);
//          q1.Push(5);
//          q1.Push(7);
//          q1.Push(8);
//          q1.Push(9);
//          q1.Push(10);
//          q1.Push(11);
//          q1.Push(12);
//          q1.Push(40);
//          q1.Push(50);
            q1.printQueue();

        }
        catch (Exception e)
        {
            System.out.println(e);
        }
    }


    @SuppressWarnings("serial")
    class QueueIsFullException extends Exception 
    {
          public QueueIsFullException(String message){
             super(message);
          }
    }

    @SuppressWarnings("serial")
    class QueueIsEmptyException extends Exception 
    {
          public QueueIsEmptyException(String message){
             super(message);
          }

    }

}

我想使用泛型,所以我将int更改为T但我得到了这个:

public class MyQueue <T>{

    private T[] _data;
    private int MAX_SIZE;
    private int front = -1;
    private int back = 0;
    private int elementsCount = 0;

    public void printQueue()
    {
        int j = this.front + 1;
        int i = 0;
        while (i < this._data.length && i < elementsCount)
        {
            System.out.println("At location " + j % MAX_SIZE + " element :" + this._data[j % MAX_SIZE]);
            j++;
            i++;
        }
    }

    public MyQueue(int _size)
    {
        MAX_SIZE = _size > 0 ? _size : 10;
        this._data = new T[MAX_SIZE];
    }

....


}

那:

  
      
  • 无法创建T
  • 的通用数组   

this post的答案中我发现我不能将泛型用于数组。

这是否意味着基于数组的泛型队列没有解决方法?我必须切换到其他一些数据结构吗?

3 个答案:

答案 0 :(得分:3)

问题的根本原因不在于你的MyQueue类,我认为你误解了Java处理泛型的方式。通用类型仅在编译时存在,之后它们只是从字节代码中删除,并且在运行时只有真正的Java类型存在于幕后。

这就是为什么你不能实例化泛型类型的原因,因为在运行时这个参数化类型根本就不存在。

你可以做的是在MyQueue类中提供一个真实的类(扩展T)作为参数来实例化这个类类型,因为这是一个一流的Java类型。

这是一个非常相似的StackOverflow问题和解决方案: Instantiating a generic class in Java

还建议阅读关于泛型的Java参考,就像你原来问题的答案在这里: https://docs.oracle.com/javase/tutorial/java/generics/restrictions.html#createObjects

答案 1 :(得分:2)

没有解决这个丑陋的演员,将你的数组通用创建改为:

        this._data = (T[])new Object[MAX_SIZE];

由于Java泛型的实现,您不能拥有这样的代码:

        this._data = new T[MAX_SIZE];

看看这个How to create a generic array in Java?

答案 2 :(得分:2)

我喜欢的方法是使用

@SuppressWarnings("unchecked")
T[] arr = (T[]) Array.newInstance(clazz,length);

其中clazz是与通用类型对应的Class<T>对象。请注意,转换操作未选中,但Array.newInstance可确保您无法在阵列中插入无效类型。

对我而言,这是最佳解决方案,因为:

  • 通过传递Array实例来处理Class<T>类的类型一致性,该实例将用于转换插入数组中的所有对象。因此,这是类型安全的,无需您执行任何操作。
  • 这是相对较小且自包含的,它不会强制您在每次使用数组时反复手动转换对象。如果您在引擎盖下使用Object[],就会出现这种情况。