Java 从泛型类返回数组。如何在main方法中打印数组中的数据?

Java 从泛型类返回数组。如何在main方法中打印数组中的数据?,java,arrays,generics,Java,Arrays,Generics,我似乎不明白如何在main方法中使用returnItems()返回的数组。我对泛型类型有点害怕。如果我继续梦想成为一名java开发人员,我将失去信心。当我阅读一些专业人士编写的代码时,他们似乎喜欢使用泛型,但我觉得这很吓人。如果我能得到一个我能很容易理解的泛型的好参考,我将不胜感激 public class Generic<T> { private int pos; private final int size; private T[] arrayOfItem

我似乎不明白如何在main方法中使用
returnItems()
返回的数组。我对泛型类型有点害怕。如果我继续梦想成为一名java开发人员,我将失去信心。当我阅读一些专业人士编写的代码时,他们似乎喜欢使用泛型,但我觉得这很吓人。如果我能得到一个我能很容易理解的泛型的好参考,我将不胜感激

public class Generic<T> {
    private int pos;
    private final int size;
    private T[] arrayOfItems;
    public Generic(int size)
    {
        this.size = size;
        pos = 0;
        arrayOfItems = (T[]) new Object[size];
    }
    public void addItem(T item)
    {
        arrayOfItems[pos] = item;
        pos++;
    }
    public void displayItems()
    {
        for(int i = 0;i<pos;i++){
        System.out.println(arrayOfItems[i]);
        }
    }
    public T[] returnItems()
    { 
        return arrayOfItems;
    }
}


public class GenericTesting {
    public static void main(String[] args) {
        Generic<String> animals = new Generic<String>(5);
        Generic<Integer> numbers = new Generic<Integer>(5);
        animals.addItem("Dog");
        animals.addItem("Cat");
        animals.addItem("Bird");
        animals.addItem("Mouse");
        animals.addItem("Elephant");
        animals.displayItems();

        numbers.addItem(1);
        numbers.addItem(2);
        numbers.addItem(3);
        numbers.displayItems();

        for(int i=0; i < animals.returnItems().length;i++)
        {
            System.out.println(animals.returnItems[i]);
        }
    }

}
公共类泛型{
私人国际邮政局;
私人最终整数大小;
私人T[]阵列设备;
公共通用(整数大小)
{
这个。大小=大小;
pos=0;
arrayOfItems=(T[])新对象[大小];
}
公共无效附加项(T项)
{
arrayOfItems[pos]=项目;
pos++;
}
公共项目()
{
for(int i=0;i
returnItems()
是一种返回数组而不是数组本身的方法,因此您不能像在这里尝试的那样尝试在其上引用索引:

        System.out.println(animals.returnItems[i]);
您需要做的是引用从方法返回的数组上的索引,如下所示:

        System.out.println(animals.returnItems()[i]);
编辑 存储和返回数据的方式也有问题。在构造函数中,您将
数组fitems
创建为
对象的数组

        arrayOfItems = (T[]) new Object[size];
…但您尝试将其作为
returnItems()
中的
T
数组返回:

当您尝试运行代码时,将出现异常:

java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
这是由于一个名为的东西造成的。基本上,Java编译器将用普通类(本例中为
Object
)替换所有泛型类型,并插入强制转换以保持类型安全

因此,您的
main()
方法中的这一行:

    for(int i=0; i < animals.returnItems().length;i++)
但是您返回的数组被创建为一个
新对象[]
不是
新字符串[]
,除非对象实际上是子类型,否则不能向下转换,因此出现异常

要消除
ClassCastException
,可以更改
returnItems()
以如下方式声明其实际返回类型:

    public Object[] returnItems()
    { 
        return arrayOfItems;
    }
这将防止编译器尝试插入数组的非法强制转换,但随后需要手动将每个元素强制转换为适当的类型,这首先会破坏使用泛型的目的


正如JBNizet在上面的评论中指出的那样,数组和泛型“不协调”,因此最好使用
ArrayList
而不是
t[]
来存储数据。

您编写的代码不起作用,因为
t[]
被初始化为
对象[]
。当您返回
t[]
returnItems()
函数中,您实际上返回了一个
对象[]
,因此不能将其视为
字符串[]

使用
ArrayList
而不是
T[]
(它实际上是一个
对象[]
)。通过其
菱形界面(
new ArrayList()
),它会自动推断
项的类型
变量:

import java.util.ArrayList;


public class Generic<T>
{
    private final int size;
    private ArrayList<T> items;
    private int pos;

    public Generic(int size)
    {
        this.size = size;
        items = new ArrayList<>(size);
        pos = 0;
    }

    public void addItem(T item)
    {
        items.add(item);
        pos++;
    }

    public void displayItems() {
        for(int i = 0; i < pos; i++)
            System.out.println(items.get(i));
    }

    public ArrayList<T> returnItems() {
        return items;
    }
}

如果您定义要打印的类的toString()方法(如果它不是基元类型),则该方法有效。

您不能将对象[]发送回字符串[]。相反,请将数组返回给对象[],然后依赖对象继承来使用正确的toString()

Object[]s=animals.returnItems();
对于(int i=0;i<代码> > p>您的代码不工作的原因与泛型没有什么关系。请考虑下面的例子:

public static void main(String[] args) {
        Object[] objArr = new Object[]{"1", "2", "3"};
        String[] strArr = new String[]{"1", "2", "3"};

        //the line below doesn't work, it has nothing to do with Generics
        String[] castedStr = (String[])objArr;

        //These lines do work
        Object[] castedObj = (Object[]) strArr;
        String[] newCastStr = (String[]) castedObj;
    }
《核心Java 2-基础知识》一书指出:

java数组会记住其条目的类型,即元素 在创建它的新[]表达式中使用的类型。强制转换是合法的 员工[]临时访问对象[]并将其回滚,但 作为对象[]开始其生命的数组永远不能强制转换为 雇员[]。”

现在,考虑java编译器对代码的作用。它将你的“<代码>通用/<代码>”类转换成:

    for(int i=0; i < ((String[])animals.returnItems()).length;i++)
public class Generic {
    private int pos;
    private final int size;
    private Object[] arrayOfItems;
    public Generic(int size)
    {
        this.size = size;
        pos = 0;
        arrayOfItems = (Object[]) new Object[size];
    }
    public void addItem(Object item)
    {
        arrayOfItems[pos] = item;
        pos++;
    }
    public void displayItems()
    {
        for(int i = 0;i<pos;i++){
        System.out.println(arrayOfItems[i]);
        }
    }
    public Object[] returnItems()
    { 
        return arrayOfItems;
    }
}
您的代码实际上接受了最初的对象[],并尝试将其转换为字符串[](我相信这是Java编译器作为类型检查的一部分插入的转换)。因此Java编译器将上面的循环转换为:

for(int i=0; i < ((String[])animals.returnItems()).length;i++)
            {

            }
for(int i=0;i<((String[])animals.returnItems()).length;i++)
{
}

如果你把这些概念放在一起,你会发现你所遇到的是一个糟糕的情况。你实际上可以解决它,而不需要做其他响应所建议的任何事情。你可以在上面的循环中插入一个显式转换到
Object[]
(我在这里编写了
String[]
)你的问题就会消失。

泛型和数组不能很好地结合在一起。使用列表而不是t[]。@jbnize你说它们“不能很好地结合在一起”是什么意思?例如,你不能创建t[]。你所能做的就是创建一个对象[]。从上面的方法返回的数组是note a t[],它是一个对象[]。实际上mbomb007,JB Nizet是正确的,T[]被类型擦除为对象[]。@mbomb007不,这是无效的。请看ArrayList的源代码:它不使用T[],它使用对象[]。它仍然不起作用。实际上我已经尝试过了,它返回一个ClassCastException。我尝试过这样做,但仍然不起作用:String[]animal=(String[])animals.returnItems();for(int i=0;i对象[]
,并且使用元素作为
String[]
。改用
ArrayList
。另一个选项可以是只声明
public Object[]returnItems()
您的解释(在“编辑”部分下)为false。ClassCastException不是beca
    Object[] s = animals.returnItems();
    for(int i=0; i < s.length;i++)
    {
        System.out.println(s[i]);
    }
public static void main(String[] args) {
        Object[] objArr = new Object[]{"1", "2", "3"};
        String[] strArr = new String[]{"1", "2", "3"};

        //the line below doesn't work, it has nothing to do with Generics
        String[] castedStr = (String[])objArr;

        //These lines do work
        Object[] castedObj = (Object[]) strArr;
        String[] newCastStr = (String[]) castedObj;
    }
public class Generic {
    private int pos;
    private final int size;
    private Object[] arrayOfItems;
    public Generic(int size)
    {
        this.size = size;
        pos = 0;
        arrayOfItems = (Object[]) new Object[size];
    }
    public void addItem(Object item)
    {
        arrayOfItems[pos] = item;
        pos++;
    }
    public void displayItems()
    {
        for(int i = 0;i<pos;i++){
        System.out.println(arrayOfItems[i]);
        }
    }
    public Object[] returnItems()
    { 
        return arrayOfItems;
    }
}
Generic<String> animals = new Generic<String>(5);
        Generic<Integer> numbers = new Generic<Integer>(5);
        animals.addItem("Dog");

        for(int i=0; i < animals.returnItems().length;i++)
        {

        }
for(int i=0; i < ((String[])animals.returnItems()).length;i++)
            {

            }