【问题标题】:List implementation not resolving casts列表实现不解决强制转换
【发布时间】:2014-02-09 10:57:35
【问题描述】:

我制作了自己的基于数组的列表实现,它不限制无效参数。如果我使用演员 MyList<String> myList = new MyList<String>() 创建,它仍然会接受所有其他参数(int、float、double 等)。我该如何解决这个问题,所以如果指定了数据类型,那就是所有将被接受的;如果未指定数据类型,那么我希望它现在可以正常工作。

这是我的代码:

public class MyList <T> implements MyListInterface
{

    private Object[] contents;
    private int size;

    public MyList()
    {
        this(10);
    }

    public MyList(int length)
    {
        contents = new Object[length];
        size = 0;
    }

    private void alterArraySize(int value)
    {
        int len = 0;

        //Value is 1 shrink array; value is 2 then double it
        switch (value)
        {
            case 1:
                len = contents.length / 2;
                break;
            case 2:
                len = contents.length * 2;
                break;
        }

        Object[] copyArr = new Object[len];

        //Copy array
        for (int i = 0; i < size; i++)
        {
            copyArr[i] = contents[i];
        }

        contents = copyArr;
    }

    public <T> boolean insertHead(T newEntry)
    {

        size++;

        if ((size + 1) == contents.length)
            alterArraySize(2);

        //Shift elements up one
        for (int i = size; i >= 0; i--)
            contents[i + 1] = contents[i];

        contents[0] = newEntry;

        return true;
    }


    public <T> boolean insertTail(T newEntry)
    {
        //If the number of items in the list
        if ((size + 1) == contents.length)
            alterArraySize(2);

        //Put the newEntry in the last slot in the array
        contents[size++] = newEntry;

        return true;
    }

    public <T> Object deleteHead()
    {
        //Set temp to first item in the array
        Object temp = contents[0];

        //Delete the first item
        contents[0] = null;

        //Shift all items in the list down one position
        for (int i = 1; i < size; i++)
        {
            contents[i - 1] = contents[i];
        }

        //Update size to accommodate for the item deletion
        size--;
        return temp;
    }


    public <T> Object deleteTail()
    {
        //Set temp to last item in array
        Object temp = contents[--size];

        //Delete the last item
        contents[size] = null;

        //Resize if the number of items in the list is half the length
        if (size <= contents.length / 2)
            alterArraySize(1);

        return temp;
    }


    public void display()
    {
        for (int i = 0; i < size; i++)
            System.out.println(contents[i]);
    }


    public <T> int contains(T anEntry)
    {
        for (int i = 0; i < size; i++)
        {
            if (contents[i].equals(anEntry))
                return ++i;
        }

        return 0;
    }


    public boolean isEmpty()
    {
        return size == 0;
    }


    public boolean isFull()
    {
        //List can't be full
        return size == contents.length;
    }

    public <T> Object get(int givenPosition)
    {
        if ((givenPosition >= 1) && (givenPosition <= size))
            return contents[givenPosition - 1];

        return null;
    }

    public <T> void set(T s, int givenPosition)
    {
        contents[givenPosition - 1] = s;
    }

    public <T> Object remove(int givenPosition)
    {
        Object temp = null;

        //Check if givenPosition is valid and shift elements after remove
        if ((givenPosition >= 1) && (givenPosition <= size))
        {
            temp = contents[givenPosition - 1];
            for (int i = givenPosition; i < size; i++)
            {
                contents[i - 1] = contents[i];
            }

            contents[size--] = null;
        }

        return temp;
    }

    public int size()
    {
        return size;
    }

}

【问题讨论】:

    标签: java arrays generics


    【解决方案1】:

    您的所有方法本身都是通用的。因此,它们有自己的类型参数,与您的类声明的类型参数无关。下面的方法声明是通用的:

    public <T> boolean insertHead(T newEntry)
    

    因此,无论您创建的类的参数化实例如何,该方法都将接受任何参数类型,并且该方法的类型 T 将被推断为该类型。要解决此问题,您应该从每个方法中删除 &lt;T&gt; 部分。例如,将上述方法更改为:

    public boolean insertHead(T newEntry)
    

    此外,您的方法的返回类型应为T 而不是Object,否则在调用者端会失败。改变方法:

    public <T> Object get(int givenPosition)
    {
        if ((givenPosition >= 1) && (givenPosition <= size))
            return contents[givenPosition - 1];
    
        return null;
    }
    

    到:

    public T get(int givenPosition)
    {
        if ((givenPosition >= 1) && (givenPosition <= size))
            return (T) contents[givenPosition - 1];  // Add cast
    
        return null;
    }
    

    【讨论】:

    • 谢谢!这解决了我的问题。那么这是否意味着该类接受泛型,因为它在类定义中?而且由于每个类都继承自类型对象,它只会解析为作为强制转换传递的任何类,否则由于类定义中的 而它是泛型的。
    • @Whoppa 你是什么意思 - “每个类都继承自类型对象?*。是的,该类是通用的,因为 &lt;T&gt; 在类名之后。
    • 我的印象是每个类都派生自类型对象。就像 String 继承自类型 object 一样,Node 继承自 object。我的想法错了吗?
    • @Whoppa 首先,你的方法的返回类型不应该是Object,而应该是T。从方法返回到T 时添加适当的演员表。是的,传递原语将被自动装箱到各自的包装器。
    • @Whoppa 如果你的方法的返回类型是Object。然后你为MyList&lt;String&gt; 调用get() 方法,你会期望它返回一个String,并将返回值存储在String 引用中。那就是它会给你编译器错误的地方。试试看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-13
    • 1970-01-01
    相关资源
    最近更新 更多