0

オブジェクトを入力として取り、そのオブジェクトのメソッドとそのパラメーターの文字列表現 (つまり、"charAt(3)") を指定して解析し、検索してこするメソッドを実装するジェネリック クラスを作成しました。正しい方法。パラメータを持たないメソッドに対して実行することはできましたが、理解できない理由で、それらを取る他のいくつかのメソッド(文字列のcharAtなど)で失敗し続けます。これがコードです。

public class MiniInterpreter<T> 
{
private Class<?> objClass;
private T object;

public MiniInterprete(T object)
{
    objClass = object.getClass();
    this.object = object;
}

private static boolean isNumeric(String str)  
{  
  try  
  {  
    @SuppressWarnings("unused")
    int i = Integer.parseInt(str);  
  }  
  catch(NumberFormatException nfe)  
  {  
    return false;  
  }  
  return true;  
}

private static boolean isBoolean(String str)
{
    return (str.equalsIgnoreCase("true") || str.equalsIgnoreCase("false"));
}


private static boolean isDouble(String str)
{
    try
    {
        @SuppressWarnings("unused")
        double d = Double.parseDouble(str);
    }
    catch(NumberFormatException nfe)
    {
        return false;
    }
    return true;
}

public String getName(int index, String str)
{
    if(str.charAt(index) == '(' || str.charAt(index) == ')')
        return "";
    else
        return str.charAt(index) + getName(index + 1, str);
}

public String getParameters(int index, String str)
{
        switch(str.charAt(index))
        {
        case '(': return "" + getName(index + 1, str);
        default: return getParametri(index + 1, str);
        }
}

public Object parse(String method) throws GenericErrorException
{
    String name = getName(0,method);
    String parameters = getParameters(0,method);

    if(!parameters.equals(""))
    {
        return parseParameters(name, parameters.split(","));
    }

    Method m = null;

    try 
    {
        m = objClass.getMethod(name);
    } 
    catch (NoSuchMethodException e) {e.printStackTrace();} 
    catch (SecurityException e) {e.printStackTrace();}

    try 
    {
        return m.invoke(object);
    } 
    catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {throw new GenericErrorException();}

}

private Object parseParameters(String name, String[] parameters) throws GenericErrorException
{
    List<Class<?>> parametersList = new ArrayList<Class<?>>();
    List<Object> parametersArray = new ArrayList<Object>();

    for(String s : parameters)
    {
        Object obj = null;

        if(isNumeric(s))
        {
            obj = Integer.parseInt(s);
        }
        else if(isDouble(s))
        {
            obj = Double.parseDouble(s);
        }
        else if(isBoolean(s))
        {
            obj = Boolean.parseBoolean(s);
        }
        else
            obj = s;

        parametersList.add(obj.getClass());
        parametersArray.add(obj);
    }

    Method m = null;
    Class<?>[] parametersTypeArray = parametersList.toArray(new Class<?>[parametersList.size()]);

    try 
    {
            m = objClass.getMethod(name, parametersTypeArray );
    } 
    catch (NoSuchMethodException | SecurityException e) {e.printStackTrace();}

    try 
    {

        return m.invoke(object, parametersArray.toArray());
    } 
    catch (IllegalAccessException | IllegalArgumentException
            | InvocationTargetException e) {throw new GenericErrorException();}

}

}

認められている唯一の型は、String、Integer、Boolean、および Double です。これは、メソッドが検索する場合にも当てはまります。また、その名前とパラメーターを持つメソッドが複数存在しないふりをする必要があります。この制限のためにコードが正しく機能しない場合は、何かを見落としていました。それが機能しない場合、noSuchMethod 例外が発生します。もちろん、nullPointer の例外により、メソッドが初期化されません。

4

2 に答える 2

0

user1676075 が示唆するように、問題は、署名が間違っているために存在しないメソッドを探していることです。

String#charAt(int)あなたが与える例です。署名はintクラスと同じではないプリミティブ型Integerです。あなたが使用している

obj = Integer.parseInt(s)

これは型を返すintので、おそらくプリミティブを取得していると思います。しかし、プリミティブをオブジェクトに格納することはできず、Java はこれを認識しています。objは であるため、 Java はプリミティブを にObject自動ボックス化します。次に、名前と署名付きのメソッドを要求すると、JRE はそれを聞いたことがないと言います。intIntegercharAtInteger

(標準ライブラリのほとんどをカバーする)を受け取るメソッドのみを使用して無視するメソッドのみを使用することに満足している場合は、型を指定するだけです。intInteger

obj = Integer.parseInt(s);
parametersList.add(Integer.TYPE);  // the type of primitive ints

ただし、正しく実行したい場合は、コードをより複雑にする必要があります。を呼び出すのではなく、Class#getMethod()を呼び出しClass#getDeclaredMethods()て、探している名前を持つサブセットを見つけ、メソッドのパラメーター リストがパラメーターと型互換性があるかどうかを確認します。

于 2013-06-01T16:14:00.590 に答える
0

.class 修正プログラムを追加すると、すべてのパブリック メソッドでプログラムがスムーズに実行されます。エラーはプライベート メソッド parseParameters にありました。2 つの異なる状況 (パラメーターまたは空の () で文字列を解析する) に対して 2 番目のメソッドを作成する必要さえありません。 getMethod に空のリストを指定すると、とにかく正しい結果が得られます。サポートに感謝します。

for(String s : parameters)
    {

        if(isNumeric(s))
        {
            parametersList.add(int.class);
            parametersArray.add(Integer.parseInt(s));
        }
        else if(isDouble(s))
        {
            parametersList.add(double.class);
            parametersArray.add(Double.parseDouble(s));
        }
        else if(isBoolean(s))
        {
            parametersList.add(boolean.class);
            parametersArray.add(Boolean.parseBoolean(s));
        }
        else
        {
            parametersList.add(s.getClass());
            parametersArray.add(s);
        }
于 2013-06-02T13:31:23.617 に答える