Java 从泛型类返回数组。如何在main方法中打印数组中的数据?
我似乎不明白如何在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
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;ireturnItems()
是一种返回数组而不是数组本身的方法,因此您不能像在这里尝试的那样尝试在其上引用索引:
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++)
{
}