不可能有一个基于数组的带有泛型的队列吗? [复制]

Posted

技术标签:

【中文标题】不可能有一个基于数组的带有泛型的队列吗? [复制]【英文标题】:Is it not possible to have an array based Queue with generics ? [duplicate] 【发布时间】:2015-12-08 18:57:17 【问题描述】:

这是一个基于数组的队列,用于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 的答案中,我看到我不能将泛型与数组一起使用。

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

【问题讨论】:

见:***.com/a/21664946/1057429 为什么不直接使用java.util.ArrayDeque 有时我喜欢编写自己的数据结构。 【参考方案1】:

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

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

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

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

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

【讨论】:

我切换到 ArrayList 。谢谢。【参考方案2】:

对于这个丑陋的演员没有解决方法,将您的数组泛型创建更改为:

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

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

        this._data = new T[MAX_SIZE];

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

【讨论】:

【参考方案3】:

我更喜欢的方法是使用

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

其中clazz 是对应泛型类型的Class&lt;T&gt; 对象。请注意,强制转换未选中,但Array.newInstance 确保您无法将无效类型插入到数组中。

对我来说这是最好的解决方案,因为:

您通过传递Class&lt;T&gt; 实例来处理Array 类的类型一致性,该实例将用于强制转换插入数组中的所有对象。因此,这是类型安全的,无需您执行任何操作。 这是相对较小且独立的,它不会强迫您在每次使用数组时手动地一遍又一遍地投射对象。如果您在后台使用 Object[],就会出现这种情况。

【讨论】:

一些答案​​说这个解决方案可能会导致ClassCastException,从这里http://***.com/questions/2927391/whats-the-reason-i-cant-create-generic-array-types-in-java 我一直使用它,没有任何问题。如果我的记忆正确,演员表是未经检查的,所以它不会失败。此方法返回一个数组,该数组保证其组件类型为T,然后您可以对其进行强制转换以获取要编译的赋值。写T[]而不是Object[]只是为了方便,这个演员不会检查任何东西

以上是关于不可能有一个基于数组的带有泛型的队列吗? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Java中数组和泛型的类型规则

Java泛型:包含泛型的数组[重复]

「GoCN酷Go推荐」基于泛型的 Golang lodash 库 — samber/lo

PHP:类型检查返回值是弥补 PHP 缺乏泛型的好习惯吗?

带有泛型的 C# 不寻常的继承语法

基于泛型的类[关闭]