2011-01-27 10 views
2

私が取り組んでいるプロジェクトがあります。このプロジェクトでは、開発者がコード全体を変更することなく独自のプラグインを組み込むことができるようにしたいと考えています。Java:クラスを特定のインターフェイスにキャストできますか?

これは私がそれまでに開発したものです。 これはプラグインが使用しているインターフェイスです。


package com.pennion.pennpad; 

public interface action{ 
void doAction(); 
} 

これは、他のものの中でプラグインを読み込む主なコードです。

 


Map menuMap=new HashMap(); 
Map actionCommands=new HashMap(); 
public void load3rdPartyMenu() throws Exception{ 
    String userHome=System.getProperty("user.home"); 
    String sep=File.getSeparator(); 
    String fileString=userHome+sep+"pennion"+sep+"pennpad"+sep+"plugins"+sep+"plugins.conf"; 
    File cfgFile=new File(fileString); 
    BufferedReader in=new BufferedReader(new InputStreamReader(new FileStreamReader(cfgFile))); 
    String ln=""; 
    boolean menuFound=false; 
    while((ln=in.readLine())!=null){ 
    if(!menuFound){ 
    if(ln.equals("//!==Menu!==//")){ 
    menuFound=true; 
    } else{ 
    menuFound=false; 
    } 
    } else{ 
    String pluginName=""; 
    String pluginDescription=""; 
    String KeyMask=""; 
    String[] split=ln.split("||"); 
    pluginName=split[0]; 
    KeyMask=split[1]; 
    pluginDescription=split[2]; 
    ClassLoader pluginLoader=ClassLoader.getClassLoader(); 
    Class c=pluginLoader.loadClass("com.pennion.3rdparty."+pluginName); 
    Map keyMap=new HashMap(); 
    String[] kmSplit=KeyMask.split("+"); 
    if(kmSplit[0].equals("CTRL")){ 
    keyMap.put("ActionEvent",ActionEvent.CTRL_MASK); 
    } else if(kmSplit[0].equals("SHIFT")){ 
    keyMap.put("ActionEvent",ActionEvent.SHIFT_MASK); 
    } else if(kmSplit[0].equals("ALT")){ 
    keyMap.put("ActionEvent",ActionEvent.ALT_MASK); 
    } else if(kmSplit[0].equals("ALT_CTRL")||kmSplit[0].equals("CTRL_ALT")){ 
    keyMap.put("ActionEvent",ActionEvent.CTRL_MASK+ActionEvent.ALT_MASK); 
    } else if(kmSplit[0].equals("SHIFT_CTRL")||kmSplit[0].equals("CTRL_SHIFT")){ 
    keyMap.put("ActionEvent",ActionEvent.CTRL_MASK+ActionEvent.SHIFT_MASK); 
    } else if(kmSplit[0].equals("ALT_SHIFT")||kmSplit[0].equals("SHIFT_ALT")){ 
    keyMap.put("ActionEvent",ActionEvent.SHIFT_MASK+ActionEvent.ALT_MASK); 
    } 
    keyMap.put("KeyBind",getKeyBinding(kmSplit[1])); 
    this.addMenuItem("Plugin",pluginName,keyMap.get("KeyBind"),keyMap.get("ActionEvent"),keyMap.get("KeyBind"),pluginName,c); 
    } 
    } 
} 
public int getKeyBinding(String k){ 
    if(k.equals("A")){ 
    return KeyEvent.VK_A; 
    } else if(k.equals("B")){ 
    return KeyEvent.VK_B; 
    } else if(k.equals("C")){ 
    return KeyEvent.VK_C; 
    } else if(k.equals("D")){ 
    return KeyEvent.VK_D; 
    } else if(k.equals("E")){ 
    return KeyEvent.VK_E; 
    } else if(k.equals("F")){ 
    return KeyEvent.VK_F; 
    } else if(k.equals("G")){ 
    return KeyEvent.VK_G; 
    } else if(k.equals("H")){ 
    return KeyEvent.VK_H; 
    } else if(k.equals("I")){ 
    return KeyEvent.VK_I; 
    } else if(k.equals("J")){ 
    return KeyEvent.VK_J; 
    } else if(k.equals("K")){ 
    return KeyEvent.VK_K; 
    } else if(k.equals("L")){ 
    return KeyEvent.VK_L; 
    } else if(k.equals("M")){ 
    return KeyEvent.VK_M; 
    } else if(k.equals("N")){ 
    return KeyEvent.VK_N; 
    } else if(k.equals("O")){ 
    return KeyEvent.VK_O; 
    } else if(k.equals("P")){ 
    return KeyEvent.VK_P; 
    } else if(k.equals("Q")){ 
    return KeyEvent.VK_Q; 
    } else if(k.equals("R")){ 
    return KeyEvent.VK_R; 
    } else if(k.equals("S")){ 
    return KeyEvent.VK_S; 
    } else if(k.equals("T")){ 
    return KeyEvent.VK_T; 
    } else if(k.equals("U")){ 
    return KeyEvent.VK_U; 
    } else if(k.equals("V")){ 
    return KeyEvent.VK_V; 
    } else if(k.equals("W")){ 
    return KeyEvent.VK_W; 
    } else if(k.equals("X")){ 
    return KeyEvent.VK_X; 
    } else if(k.equals("Y")){ 
    return KeyEvent.VK_Y; 
    } else if(k.equals("Z")){ 
    return KeyEvent.VK_Z; 
    } else if(k.equals("1")){ 
    return KeyEvent.VK_1; 
    } else if(k.equals("2")){ 
    return KeyEvent.VK_2; 
    } else if(k.equals("3")){ 
    return KeyEvent.VK_3; 
    } else if(k.equals("4")){ 
    return KeyEvent.VK_4; 
    } else if(k.equals("5")){ 
    return KeyEvent.VK_5; 
    } else if(k.equals("6")){ 
    return KeyEvent.VK_6; 
    } else if(k.equals("7")){ 
    return KeyEvent.VK_7; 
    } else if(k.equals("8")){ 
    return KeyEvent.VK_8; 
    } else if(k.equals("9")){ 
    return KeyEvent.VK_9; 
    } else if(k.equals("0")){ 
    return KeyEvent.VK_0; 
    } else{ 
    return 0; 
    } 
} 
 

今のようには、コンパイラによってクラス検討されているとactionCommandsのハッシュマップに追加することはできませんので、私はアクションとしてロードされたクラスをキャストする方法が必要です。

ロードされたStringによってどのKeyEventが要求されているかを簡単に処理する方法はありますか?

+0

残念ながら、私はまだコードにコメントしていません。そして、悪いコーディング習慣を練習しています。\ –

+0

2番目の質問については、文字列とKeyEvent定数の間のマッピングがあると考えるかもしれません。 「map actionCommands = new HashMap();」を変更すると役立ちますか? 「 actionCommands = new HashMap ();」にマップします。 (または類似のもので、マップの使い方を指定していない)。私は、使用している型をより明示的にするためにジェネリックスを使用してみてください。 –

+0

whats oddは、をコピーしなかったときに、私のマップにファイルがどのようにコード化されているかを示しています。 –

答えて

7

クラスを直接何かにキャストすることはできません。

オブジェクトを作成してインターフェイスにキャストすることができます。

Object obj = clazz.newInstance(); 
Action actionObj = (Action) obj; 

クラス名は大文字で始まります。

+1

それはちょうど 'newInstance()'です。 –

+0

'Action actionObj = clazz.createNewInstance(); 'のようにインターフェイスとして直接インスタンス化できません。 –

+0

' Class'には 'createNewInstance()'メソッドはありません。 – erickson

4

これまでのコードでは、そのクラスのインスタンスではなく、Classしかありません。

ある時点で、Classからインスタンスを構築する必要があります。そのインスタンスはActionにキャストされます。

あなたの第1の質問については
/* Load the plugin class. */ 
Class<?> clz = Class.forName("com.y.plugins.MyCustomAction"); 
/* Make sure the named class is the right type. */ 
Class<? extends Action> sub = clz.asSubclass(Action.class); 
/* Get the default constructor. */ 
Constructor<? extends Action> ctor = sub.getConstructor(); 
/* Create an instance of "MyCustomAction". */ 
Action custom = ctor.newInstance(); 
+0

実際には、コンストラクタを取得する必要はありません。デフォルト(パラメータなし)では、Classオブジェクトに対してnewInstanceを直接呼び出すことができます。 –

+2

@Marcos Vasconcelos - ダイナミックメソッド呼び出しとの一貫性のために、より新しいAPI(コンストラクタの取得)を使用することをお勧めします。 1つは、より良いエラー報告を得ることです。コンストラクタが存在しない場合、 'IllegalAccessException'ではなく' NoSuchMethodException'を取得します(コンストラクタは存在しますが、アクセスできないということもあります)。 – erickson

0

、あなたがロードされたクラスのインスタンスを作成し、それをキャストする必要があります。..

だから、あなたの第二の質問については

cInstance = c.newInstance(); 
((action)cInstance).doAction(); 

、私は」することができますストリングを静的変数にデコードするより速い方法を考える。

関連する問題