0

ユーザー入力を解析し、それをクラスの配列と比較して、それに応じて入力をキャストするための汎用コードを書きたいと思います。すなわち:

  1. Object[] paramTypes = {文字列.クラス、文字列.クラス、整数.クラス}
  2. Object[ ] userInput = { "playerName1", "targetPlayerName", "5" } //5 は文字列
  3. ユーザー入力の各文字列は、paramTypes の対応するクラスにキャストされます。
  4. 最後に、キャストされた単語は、後で使用するために別の Object[ ] castedUserInput に入れられます。

    for(int i = 0; i<userInput.length; i++)
      castedUserInput[i] = paramTypes[i].cast(userInput[i]);
    
問題:

paramTypes[i] が Integer.class でキャストが実行されるとすぐに、ClassCastException が発生します。その例外のドキュメントは次のとおりです。

ClassCastException: コードがオブジェクトをインスタンスではないサブクラスにキャストしようとしたことを示すためにスローされます

そのため、(Object)"5" (正確に機能しないのはなぜですか?) も "5" も Number のサブクラスにキャストできません。

Number と String はどちらもオブジェクトのサブクラスですが、それ以外は互いに関連していないことがわかりました。NumberClassCastExceptionのソースコードを確認するために JDK7 をインストールしていますが、プログラミングを始めてまだ1 年ほどで、Java コンパイラと仮想マシンが何であるかを十分に理解していないため、あまり役に立たないでしょう。マシンはまさにここでやっています。

誰か助けてくれませんか?

PS: もちろん、いくつかの if 句を使用してから、Integer.parseInt(userInput[i])、Long.parseLong(userInput[i]) などを使用できますが、それは最も効率的なソリューションではありませんよね?

4

2 に答える 2

1

String入力のタイプがであり、Stringにキャストできないため、説明したとおりにクラス キャスト例外が発生しますInteger。キャストする代わりに、入力を予想されるパラメーターの型に変換することを検討する必要があります。この目的のためのフレームワークがいくつかありますが、可能な型の数が限られている場合は、自分で何かを書くことができます。とInteger/Long.parseInt、ひとつの解決策になります。

于 2013-04-28T21:33:07.847 に答える
1

ここでの問題は、正しくお気づきのように、文字列である「5」が整数にキャストされていることです。Integer は String のサブクラスではないため、JVM は実行時に ClassCasrException をスローしています。Integer と String は両方とも Object の sub-cklsses であるため、String と Integer の値を Object に安全にキャストできます (Object 配列に文字列または整数を格納する場合と同様)。

修正する 1 つの方法は、次を使用することです。

for(int i = 0; i<userInput.length; i++)
  castedUserInput[i] = safeCast(paramTypes[i], userInput[i]);

int、longなどに解析するために言及したif句を使用して、どこでsafeCast()変換を行いますか。より一般的な別のアプローチは、リフレクションを使用して、文字列引数をとるコンストラクターを呼び出すことです。具体的な Number クラス (Byte、Double、Float、Integer、Long、Short) のほとんどは、このようなコンストラクタをサポートしているため、Number クラスを使いこなす必要があります。カスタム クラスの場合、単一の String 引数を取るコンストラクタが必要になります。リフレクションを使用し、渡された値を引数として受け取るコンストラクターを持つことに依存するソリューションを次に示します。

public static Object safeCast(Class paramType, Object value)
        throws NoSuchMethodException, IllegalAccessException,
        InvocationTargetException, InstantiationException {
    if (value == null) {
        return null;
    }
    final Class<?> valueClass = value.getClass();
    if (paramType.isAssignableFrom(valueClass)) {
        return value;
    }
    final Constructor theConstructor = paramType.getConstructor(valueClass);
    return theConstructor.newInstance(value);
}
于 2013-04-28T21:34:29.073 に答える