我首先要说的是我是一名Java(/编程)新手,这是我在网站上的第一个问题。
刚学会了如何使用递归节点在Java中创建有序列表。 一切都很简单,直到我遇到这个练习,要求我编写一个方法,将每个节点中包含的任何值加倍。 这是我试着编写的代码:
public class ListaInteri<E extends Integer>
{
private NodoLista inizio;
// Private inner class each instance of these has a raw type variable and a
// ref
// to next node in the list
private class NodoLista
{
E dato;
NodoLista pros;
}
// method that adds whatever is meant by x to the begging of the list
public void aggiungi(E x)
{
NodoLista nodo = new NodoLista();
nodo.dato = x;
if (inizio != null)
nodo.pros = inizio;
inizio = nodo;
}
// a method that switches last and first elements in the list
public void scambia()
{
E datoFine;
if (inizio != null && inizio.pros != null) {
E datoInizio = inizio.dato;
NodoLista nl = inizio;
while (nl.pros != null)
nl = nl.pros;
datoFine = nl.dato;
inizio.dato = datoFine;
nl.dato = datoInizio;
}
}
// and here is the problem
// this method is supposed to double the value of the raw type variable dato
// of each node
public void raddoppia()
{
if (inizio != null) {
NodoLista temp = inizio;
while (temp != null) {
temp.dato *= 2;
}
}
}
// Overriding toString from object (ignore this)
public String toString(String separatore)
{
String stringa = "";
if (inizio != null) {
stringa += inizio.dato.toString();
for (NodoLista nl = inizio.pros; nl != null; nl = nl.pros) {
stringa += separatore + nl.dato.toString();
}
}
return stringa;
}
public String toString()
{
return this.toString(" ");
}
}
这是编译器给我的错误。
ListaInteri.java:39: inconvertible types
found : int
required: E
temp.dato*=2;
^
1 error
现在请记住,任何形式的帮助都会受到极大的赞赏,无论如何,这里是我想要回答的问题。
EDIT;抱歉必须让它可读现在应该没问题。 EDIT2:几乎可以读取argh!
答案 0 :(得分:6)
Integer
是最终的,不能延期。因此,您对泛型的使用毫无意义(虽然语法上有效),您也可以使用int
- 然后问题就会消失。
答案 1 :(得分:3)
类型擦除不是问题(泛型类型被删除,因此它们在运行时不可用,但在编译时,类型必须是可转换的。)
我可能会解决这个问题,根本不使用类型参数。 Integer
是最后一个类,所以没有必要让它使用更通用的类型,例如E extends Integer
。
答案 2 :(得分:1)
一个澄清,只是为了确保你明白:你问,
不存在类型这样的东西 在编译期间擦除原始类型 所有必须做的信息的时间 参数或参数类型是 忽略?
人们在Java中谈论了很多关于“类型擦除”的内容,部分原因是类型擦除是Java和C ++之间许多有趣的差异之一,部分原因是类型擦除在混合较新时会给你带来奇怪和意外的错误(Java 5和以后用旧的Java代码。
但是,类型擦除并不意味着“所有与参数或参数类型有关的信息都会被忽略” - 这意味着比这更窄的东西。另外,正如您所说,类型擦除是在“编译期间”应用的,但在之后>>应用程序检查程序中的所有类型和声明以查看是否存在任何类型错误。
第一个问题:什么是类型擦除?类型擦除只发生在泛型类型中。 Integer
不是通用类型,但ArrayList<T>
是通用类型,因为您可以声明ArrayList<Integer>
或ArrayList<String>
。在编译器完成检查程序中的类型以使它们全部匹配之后,它会丢弃有关泛型类型的所有信息,以便ArrayList<Integer>
和ArrayList<String>
都变为{{1} }。这就是为什么你可以在Java中编写ArrayList
但你不能编写if (foo instanceof String)
的原因:当在运行时评估if (foo instanceof ArrayList<String>)
语句时,没有办法告诉{{ 1}}除了if
或任何其他类型的ArrayList<String>
。
第二个问题:何时应用类型擦除?在检查编译错误之后,编译器生成编译代码(“字节码”)时应用类型擦除。这意味着以下代码在Java中给出了编译错误,即使Java使用类型擦除:
ArrayList<Integer>
我知道我没有回答你的问题,但我想确保你先了解类型擦除。 : - )
回到原来的问题:为什么需要使用ArrayList
声明课程?这是家庭作业特别需要的吗?我只是将您的代码复制并粘贴到Eclipse中,删除了顶部的ArrayList<String> foo = new ArrayList<String>();
foo.add(new Integer(3)); // Error - Compiler knows that String is expected
,并用<E extends Integer>
替换了所有<E extends Integer>
声明,并且编译得很好。
(顺便说一句,E
仍然存在问题,因为你已经在这里写了它,即使你摆脱Integer
并让它编译 - 你找到了它吗?试试使用包含多个元素的列表测试raddoppia
,您应该看到问题...)
答案 3 :(得分:0)
尝试:
temp.dato= new Integer(((Integer)temp.dato).intValue*2);
答案 4 :(得分:0)
我认为应该是
<E extends Number>
然后你可以说
tmp.dato = tmp.dato.intValue() * 2;
我认为这会编译,但如果有人将您的数据结构用于非整数,则此方法将无法产生正确的答案。