- PR -

NoSuchMethodExceptionの原因

投稿者投稿内容
空条Q太郎
会議室デビュー日: 2003/11/06
投稿数: 19
投稿日時: 2003-11-28 22:34
いつもお世話になります。

任意のクラスのメソッドを呼び出すクラスAを作成しましたが、
クラスBの引数がConnection型のメソッドを呼び出すと、下記コードの"エラー"の箇所で
parClass[0].getConstructor(new Class[] {Class.forName( "java.sql.Connection" ) })が
"java.lang.NoSuchMethodException"となります。

クラスBの引数がStringなら問題なく呼び出すことができます。
java.sql.Connectionの場合なぜエラーになるのかお教えください。

////////////////////クラスA////////////////////
Public static void rootSelect( Connection con, String key ) throws ServerException{
//keyからクラス名、メソッド名を取得


省略

Class actionClass = Class.forName( クラス名 );

Constructor constructor;
Object actionInstance;

constructor = actionClass.getConstructor( new Class[] {} );
actionInstance = constructor.newInstance( new Object[] {} );

Class[] parClass = new Class[1];
Object[] parObject = new Object[1];

//型定義
parClass[0] = Class.forName( "java.sql.Connection" );

//値定義
parObject[0] = parClass[0].getConstructor(
new Class[] {Class.forName( "java.sql.Connection" ) } ).newInstance( new Object[] { con } );------エラー

Method actionMethod = actionClass.getDeclaredMethod( メソッド名, parClass );

actionMethod.invoke( actionInstance, parObject );
}

////////////////////クラスB////////////////////
public void execute(Connection con) {
//省略
}
M・F
会議室デビュー日: 2002/12/20
投稿数: 3
投稿日時: 2003-11-28 22:45
java.sql.Connectionがインタフェースだからでしょう。
空条Q太郎
会議室デビュー日: 2003/11/06
投稿数: 19
投稿日時: 2003-11-28 23:25
M・Fさんありがとうございます。

>java.sql.Connectionがインタフェースだからでしょう。

インターフェースだと駄目となると
どうすればConnectionを引数にもつクラスBを呼べるのでしょうか。

クラスBのConnectionはjava.sql.Connectionをインポートしていますが
こちらを変える必要があるのでしょうか?
おばけ
ぬし
会議室デビュー日: 2002/11/14
投稿数: 609
お住まい・勤務地: 東京都江東区
投稿日時: 2003-11-29 01:02
すみませんが、私には提示されたソースコードから「空条Q太郎さんはもともと何がしたいのか」を読み取ることができません。まず、なぜこのようなコードを書かれたのか、そちらから教えていただけませんか?それが無いと、M・Fさんの仰るように「java.sql.Connectionがインタフェースであるから、コンストラクタを探してもNoSuchMethodと言われるのは当然である」としか答えられないのです。
M・F
会議室デビュー日: 2002/12/20
投稿数: 3
投稿日時: 2003-11-29 10:22
クラスAのrootSelectメソッドで、任意のクラスBをインスタンス化してConnectionを引数に持つexecuteメソッドを呼び出したいと解釈すると、

Class actionClass = Class.forName("ClassB");
actionInstance = actionClass.newInstance();
Class[] parClass = new Class[]{java.sql.Connection}
Method actionMethod = actionClass.getMethod("execute", parClass);
Object[] parObject = new Object[]{con}
actionMethod.invoke( actionInstance, parObject );

のような感じでいいのではないでしょうか?
#すみませんが時間がない為コードの検証はしてません。例外処理も省いています。


[ メッセージ編集済み 編集者: M・F 編集日時 2003-11-29 10:23 ]
空条Q太郎
会議室デビュー日: 2003/11/06
投稿数: 19
投稿日時: 2003-12-01 13:09
おばけさん、M・Fさんご回答ありがとうございました。
遅くなりました、すみません。

おばけさんの

>「空条Q太郎さんはもともと何がしたいのか」

については、M・Fさんからの

>クラスAのrootSelectメソッドで、任意のクラスBをインスタンス化してConnectionを引数に持つ
>executeメソッドを呼び出したいと解釈すると、

です。詳しくはConnectionを引数に持つ幾つかのクラスがあり、クラスAのrootSelectメソッドの
keyに該当するクラスのメソッドを呼び出したいのです。

また

>M・Fさんの仰るように「java.sql.Connectionがインタフェースであるから、コンストラクタを
>探してもNoSuchMethodと言われるのは当然である」としか答えられないのです。

コンストラクタのないjava.sql.ConnectionでgetConstructorメソッドは当然駄目ですね。すみません。

最終的なソースは以下の通りです。

////////////////////クラスA////////////////////
Public static void rootSelect( Connection con, String key ) throws ServerException{
//keyからクラス名、メソッド名を取得


省略

//クラスオブジェクト作成
Class actionClass = Class.forName( クラス名 );

//コンストラクタオブジェクト作成
Constructor constructor = actionClass.getConstructor( new Class[] {} );

//インスタンス作成
Object actionInstance = constructor.newInstance( new Object[] {} );

Class[] parClass = new Class[1];
Object[] parObject = new Object[1];

//型定義
parClass[0] = Class.forName( "java.sql.Connection" );

//値定義
parObject[0] = con;

Method actionMethod = actionClass.getDeclaredMethod( メソッド名, parClass );

actionMethod.invoke( actionInstance, parObject );
}

////////////////////クラスB////////////////////
public void execute(Connection con) {
//省略
}
おばけ
ぬし
会議室デビュー日: 2002/11/14
投稿数: 609
お住まい・勤務地: 東京都江東区
投稿日時: 2003-12-01 13:47
なるほど、なんとなく分かってきました。

引用:

詳しくはConnectionを引数に持つ幾つかのクラスがあり、クラスAのrootSelectメソッドのkeyに該当するクラスのメソッドを呼び出したいのです。


「Connectionを引数に持つ幾つかのクラス」というのは、「Connectionを引数に取るexecuteというメソッドを持つ幾つかのクラス」という意味ですか?

引用:

コンストラクタのないjava.sql.ConnectionでgetConstructorメソッドは当然駄目ですね。すみません。


そもそも、インタフェースにはコンストラクタは無いのです。

ところで、このコード、もっと簡略化できませんか?
例えば、

コード:
// executeメソッドを持つクラスの実装すべきインタフェースを定義
public interface InterfaceB
{
    public void execute(java.sql.Connection con);
}

// クラスA
public class ClassA
{
    static public void rootSelect( java.sql.Connection con, String key )
        throws ServerException
    {
        Class actionClass = Class.forName(key);
        Object actionObject = actionClass.newInstance();
        if ( actionObject instanceof InterfaceB ){
            InterfaceB interfaceB = (InterfaceB) actionObject;
            interfaceB.execute(con);
        }
    }
}

// クラスB
public class ClassB implements InterfaceB
{
}


というように。
あらかじめexecuteというメソッドを呼び出すことも決まっていますし、そのシグネチャも一つであるならば、メソッドのリフレクションを使う意義が良く分かりません。

それとも、このサンプルコードには無い部分でメソッドのリフレクションが必要なのでしょうか?
空条Q太郎
会議室デビュー日: 2003/11/06
投稿数: 19
投稿日時: 2003-12-01 16:11
おばけさんご回答ありがとうございます。

rootSelectメソッドの引数:keyからクラス名とメソッド名を取得しようとしたためメソッドのリフレクションを使いました。
メソッド名がexecuteだけでないということです。

ただし、"excecuteに統一したほうが良い"との声もありますので
おばけさんから頂きましたコードで試してみたいと思います。

勉強になりました。ありがとうございました。

スキルアップ/キャリアアップ(JOB@IT)