Java:您可以将 Class 转换为特定接口吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4820507/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 08:10:38  来源:igfitidea点击:

Java: can you cast Class into a specific interface?

javaclass

提问by erickson

I've got a project I am working on and in this project I would like to include the ability for developers to include their own plugins without having to change the whole code.

我有一个我正在处理的项目,在这个项目中,我希望让开发人员能够在无需更改整个代码的情况下包含他们自己的插件。

This is what I have developed for it so far. this is the interface that the plugins are using.

这是我迄今为止为它开发的。这是插件使用的界面。


package com.pennion.pennpad;

public interface action{
 void doAction();
}

This is the main code that loads the plugins among other things.

这是加载插件的主要代码。



 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;
  }
 }

I need a way to cast the loaded class as an action because as of now it is being considered a class by the compiler and can't be added to the actionCommands hashmap.

我需要一种将加载的类转换为动作的方法,因为到目前为止它被编译器认为是一个类,不能添加到 actionCommands 哈希图中。

and is there an easier way to process which KeyEvent is being asked for by the loaded String?

是否有更简单的方法来处理加载的字符串所要求的 KeyEvent?

回答by Marcos Vasconcelos

You can't cast a Class direct to something.

您不能将 Class 直接投射到某物上。

You can create a object of it and then cast it to your interface.

您可以创建它的对象,然后将其转换为您的界面。

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

Follow the conventions, class names starts with upper case.

遵循约定,类名以大写开头。

回答by erickson

So far, in the code you show, you only have a Class, not an instance of that class.

到目前为止,在您显示的代码中,您只有一个Class,而不是该类的实例。

At some point, you'll need to construct an instance from the Class; that instance is what you'll cast to an Action.

在某些时候,您需要从Class;构造一个实例。该实例是您将投射到Action.

/* 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();

回答by notthetup

For your 1st question, you will have to make an instance of the loaded class and then cast it..

对于您的第一个问题,您必须创建已加载类的实例,然后将其强制转换。

So,

所以,

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

For your 2nd question, I can't think of a quicker way to decode Strings into static variables.

对于您的第二个问题,我想不出更快的方法将字符串解码为静态变量。