Java - 更改原始类型变量的值。可能?

时间:2010-02-19 23:06:35

标签: java list types nodes

我首先要说的是我是一名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

现在请记住,任何形式的帮助都会受到极大的赞赏,无论如何,这里是我想要回答的问题。

  1. 为什么会这样?在编译期间是否存在类型擦除原始类型的事情,其中​​忽略了与参数或参数类型有关的所有信息?
  2. 我该如何解决这个问题?第二种方法(首先和最后一种方法)显示,只要它被另一个原始类型传递,编译器就可以更改节点中的字段,而如果我们尝试将它乘以2,例如它就不再可以了因为编译器现在知道我们正在讨论一个int / Integer,所以给出了这个错误。 提前感谢您的任何答案。
  3. EDIT;抱歉必须让它可读现在应该没问题。 EDIT2:几乎可以读取argh!

5 个答案:

答案 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;

我认为这会编译,但如果有人将您的数据结构用于非整数,则此方法将无法产生正确的答案。