3

私はJava(/プログラミング)初心者であると言うことから始めます。これはWebサイトでの私の最初の質問です。

再帰ノードを使用してJavaで順序付きリストを作成する方法を学びました。この演習に出くわして、各ノードに含まれる値を2倍にするメソッドを作成するように求められるまで、すべてが簡単でした。これが私が書き込もうとしたコードです:

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. なぜこれが起こるのですか?コンパイル時のraw型の型消去のように、パラメーターや引数の型に関係するすべての情報が無視されるようなことはありませんか?
  2. これを修正するにはどうすればよいですか?2番目の方法(最初と最後を切り替える方法)は、別のraw型が渡される限り、コンパイラがノードのフィールドを変更しても実際には問題ないことを示していますが、たとえば2を掛けようとすると、問題はなくなります。コンパイラは、int / Integerについて話していることを認識しているため、このエラーが返されます。回答をよろしくお願いします。

編集; 申し訳ありませんが、読みやすくする必要がありました。EDIT2:ほぼ読みやすい引数!

4

5 に答える 5

6

Integer最終的なものであり、延長することはできません。したがって、Generics の使用は無意味であり (構文的には有効ですが)、そのまま使用することもできますint。問題は解消されます。

于 2010-02-19T23:16:46.397 に答える
3

型の消去はここでは問題ではありません (ジェネリック型は消去されるため実行時に使用できませんが、コンパイル時には型を変換できる必要があります)。

おそらくこれを修正して、型パラメーターをまったく使用しないようにします。Integerは final クラスなので、 などのより一般的な型を使用しても意味がありませんE extends Integer

于 2010-02-19T23:16:15.933 に答える
1

あなたが何かを理解していることを確認するために、1つの明確化:あなたは尋ねました、

パラメーターまたは引数の型に関係するすべての情報が無視される、コンパイル時の生の型の型消去のようなものはありませんか?

人々は Java の「型消去」についてよく話します。これは、型消去が Java と C++ の多くの興味深い違いの 1 つであることと、新しい (Java 5 以降) を混合すると、型消去が奇妙で予期しないエラーを引き起こす可能性があるためです。古い Java コード。

ただし、型の消去は「パラメーターまたは引数の型に関係するすべての情報が無視される」という意味ではなく、それよりもはるかに狭いことを意味します。また、あなたが言ったように、型消去は「コンパイル時に」適用されますが、コンパイラがプログラム内のすべての型と宣言をチェックして型エラーがあるかどうかを確認した後に適用されます。

最初の質問: 型消去とは何ですか? 型の消去は、ジェネリック型にのみ発生するものです。 orを宣言できるため、ジェネリックInteger型ではありませんが、ジェネリック型です。コンパイラは、プログラム内の型をチェックしてすべて一致させると、ジェネリック型に関するすべての情報を破棄するため、 anと an の両方が になります。これが、 Java で記述できるのに を記述できない理由です。そのステートメントが実行時に評価されるとき、 をと、または他のタイプのと区別する方法はありません。ArrayList<T>ArrayList<Integer>ArrayList<String>ArrayList<Integer>ArrayList<String>ArrayListif (foo instanceof String)if (foo instanceof ArrayList<String>)ifArrayList<String>ArrayList<Integer>ArrayList

2 番目の質問: 型消去はいつ適用されますか? 型消去は、コンパイラがコンパイルされたコード (「バイトコード」) を生成するときに、コードのコンパイル エラーがチェックされた後に適用されます。これは、Java が型消去を使用している場合でも、次のコードは Java でコンパイル エラーになることを意味します。

ArrayList<String> foo = new ArrayList<String>();
foo.add(new Integer(3)); // Error - Compiler knows that String is expected

あなたの質問に答えていないことはわかっていますが、最初に型消去を理解していることを確認したかったのです。:-)

元の質問に戻ります: クラスを で宣言する必要があるのはなぜ<E extends Integer>ですか? それは宿題に特に必要ですか?コードをコピーして Eclipse に貼り付け、上部の を削除し、すべての宣言を<E extends Integer>に置き換えたところ、問題なくコンパイルされました。EInteger

(ちなみに、raddoppiaあなたがここに書いたように、たとえあなたが<E extends Integer>それを取り除いてコンパイルしても、まだ問題があります - あなたはまだそれを見つけましたか?raddoppia複数の要素を持つリストでテストしてみてください.問題を見るべきです...)

于 2010-02-22T00:11:12.167 に答える
0

試す :

  temp.dato= new Integer(((Integer)temp.dato).intValue*2);
于 2010-02-19T23:19:15.797 に答える
0

そうあるべきだと思う

<E extends Number>

それからあなたは言うことができます

tmp.dato = tmp.dato.intValue() * 2;

これはコンパイルされると思いますが、誰かが整数以外のデータ構造を使用している場合、このメソッドは正しい答えを生成しません。

于 2010-02-19T23:51:16.483 に答える