在Java中使用带有静态类的通配符

时间:2013-05-14 00:18:59

标签: java

我想要的想法是我的程序中有一堆动作/功能。它们都是预定义的并分为几类。因此,管理员操作可能会有一个类别,然后为管理操作类别中的操作定义一堆静态代码。

由于类别和操作是固定的,因此它们都是静态类。

这些静态类别类都实现了一个接口ICategory:

public static interface ICategory{
    int getCateogory();
    String getCategoryName();
    String getFunctionName(int function);
}

这些静态类中的每一个都被添加到静态Map:

private static Map<Integer, Class<? extends ICategory>> catMap = new HashMap<Integer, Class<? extends ICategory>>();

基本上,每个类别都有一个整数代码。我正在尝试做的只是制作一个人类可读的字符串,当我收到类别和动作代码时,我可以打印出来。我想做的是像

ICategory whatever = catMap.get(catNumber);
System.out.println(whatever.getCategoryName());
System.out.println(whatever.getFunctionName(actionCode));

因此catMap.get(catNumber)实际上将返回正确的静态类,但我不知道如何使用返回的类来访问这些静态方法。我可以用类的常规实例来做,很好,但是用静态类做这件事让我感到困惑。

澄清问题:

我正试图解决的问题的一些澄清,以防你们有更好/更直观的方法来做到这一点的建议:

基本上我正在解释我公司某些定制硬件的命令。这是一个小数据集合小发明,它有一堆我必须解释的预定义消息/函数。

这些功能分为不同的类别:显示,键盘,采集等

所以基本上我有这样的映射:

  Display Category: 128
      ShowGraph: 01
      ShowText: 02
  Keypad Category: 129
      F1: 01
      F2: 02
      MenuKey: 03

我正在进行一个小流显示,以人类可读的格式打印出命令流。所以我只打印一个像

这样的大清单
Got Category Display, Function ShowGraph
Got Category Keypad, Function MenuKey

通常我会为此使用一个映射,但我想要的是也将每个类别中的函数用作常量,因为我必须在if语句中引用它们,并且经常将这些相同的类别发送回小小发明。

For Instance:

sendMessage(Categories.DisplayCategory.getCategoryInt(), Categories.DisplayCategory.SHOW_GRAPH);

按要求提供更多代码:

public class Functions {

    public static interface ICategory{
        int getCateogory();
        String getCategoryName();
        String getFunctionName(int function);
    }

    private static Map<Integer, Class<? extends ICategory>> catMap = new HashMap<Integer, Class<? extends ICategory>>();

    public static String getCategoryString(int category) {
        Class<? extends ICategory> clazz = catMap.get(category);
        System.out.println(catMap.toString());

        if(clazz != null){
            try{
                Method m = clazz.getMethod("getCategoryName", Integer.class);
                return (String) m.invoke(0, category);
            }catch (Exception e){
                return null;
            }

        }else{
            System.out.println("clazz was null");
            return null;
        }
    }

    public static class SystemKey implements ICategory{
        public static int CATEGORY = 134;
        private static Map<Integer, String> fmap = new HashMap<Integer, String>();
        @Override
        public int getCateogory() {
            return CATEGORY;
        }

        @Override
        public String getCategoryName() {
            return "SystemKey";
        }

        @Override
        public String getFunctionName(int function) {
            return fmap.get(function);
        }
    }

    public static class SystemCat implements ICategory{
        public static int CATEGORY = 128;
        private static Map<Integer, String> fmap = new HashMap<Integer, String>();

        public static final int POWER_UP = 0x01;
        public static final int END_OF_TRANSMIT = 0x02;
        public static final int CLEAR_TO_SEND = 0x03;
        public static final int NET_TEST = 0x05; /*Fom station to ctrlr*/ 
        public static final int NET_OK = 0x06; /*Response to controller*/
        public static final int MAIN_MENU = 0x07;

        static{
            catMap.put(CATEGORY, SystemCat.class);

            fmap.put(POWER_UP, "POWER_UP"); 
            fmap.put(END_OF_TRANSMIT, "END_OF_TRANSMIT"); 
            fmap.put(CLEAR_TO_SEND, "CLEAR_TO_SEND");
            fmap.put(NET_TEST, "NET_TEST"); 
            fmap.put(NET_OK, "NET_OK"); 
            fmap.put(MAIN_MENU, "MAIN_MENU");
        }


        @Override
        public int getCateogory() {
            return CATEGORY;
        }

        @Override
        public String getCategoryName() {
            return "System";
        }

        @Override
        public String getFunctionName(int function) {
            return fmap.get(function);
        }
    }




    public static class SoftKey implements ICategory{
        public static int CATEGORY = 129;

        private static Map<Integer, String> fmap = new HashMap<Integer, String>();

        public static final int F1 = 0x20;
        public static final int F2 = 0x21;
        public static final int F3 = 0x22;
        public static final int F4 = 0x23;
        public static final int F5 = 0x24;

        static{
            catMap.put(CATEGORY, SoftKey.class);

            fmap.put(F1, "F1");
            fmap.put(F2, "F2");
            fmap.put(F3, "F3");
            fmap.put(F4, "F4");
            fmap.put(F5, "F5");

        @Override
        public int getCateogory() {
            return CATEGORY;
        }

        @Override
        public String getCategoryName() {
            return "SoftKey";
        }

        @Override
        public String getFunctionName(int function) {
            return fmap.get(function);
        }

    }


    public static void main (String[] args) throws Exception{


         System.out.println(Functions.getCategoryString(128));
    }

}

2 个答案:

答案 0 :(得分:1)

更新

我怀疑,解决方案非常简单。有不同的方法可以做到这一点,这里有一个,我似乎记得称之为Registry,回到模式被称为习语的时代。你几乎就在那里,你需要的是跟随变化:

  1. catMap类型从Map<String,Class<? extends ICategory>更改为Map<Integer, ICategory>

  2. static initializers创建一个对象并将其放入地图中,例如

    public static class SoftKey实现ICategory { ....

    static{
        catMap.put(CATEGORY, new SoftKey());
    
  3. getCategoryString中使用注册表中的ICategory对象:

    ICategory categ = catMap.get(category); return categor.getCategoyString()


  4. 我可能误解了这个问题,但其中一部分令人困惑:

      

    因此catMap.get(catNumber)实际上将返回正确的静态类

    static class我假设你的意思是interfaces嵌套在某个类/接口中。 Java中没有顶级静态类。 get会返回Object static class ,而不是class

      

    但我不知道如何使用返回的类来访问这些静态方法。

    您声明的方法不是static,而是instance methods

      

    我可以用类的常规实例来做,很好,但是使用静态类做这件事让我感到困惑。

    我也很困惑。您可以调用静态类对象的实例方法。你能发一个完整的代码样本吗?

答案 1 :(得分:1)

假设您事先知道所有代码,并且没有1000个函数值,这将起作用。只要你不介意通过容器查找它们(而不是Map),函数值代码的非唯一性就不是问题。

如果您不介意始终循环遍历所有枚举值,则可以完全取消静态地图。如果您不经常进行查找,这可能是完全可以接受的。

import java.util.EnumMap;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;


public enum FunctionCategory {

    DISPLAY(128, "Display"),
    KEYPAD(129, "KeyPad");
    // more categories here...
    private final int code;
    private final String name;

    private static Map<Integer, FunctionCategory> categoryMap = new HashMap<>();

    static {
        for( FunctionCategory c : FunctionCategory.values() ) {
            categoryMap.put(c.getCode(), c);
        }
    }

    // For looking up a category from its code
    public static FunctionCategory fromCode( int code ) {
        return categoryMap.get(code);
    }

    private FunctionCategory(int code, String name) {
        this.code = code;
        this.name = name;
    }

    public int getCode() {
        return code;
    }

    public String getName() {
        return name;
    }


    public static enum FunctionValue {

        // DISPLAY
        DISPLAY_GRAPH(DISPLAY, 1, "Graph"),
        DISPLAY_TEXT(DISPLAY, 2, "ShowText"),
        //KEYPAD
        KEYPAD_MENU(KEYPAD, 1, "MenuKey"),
        KEYPAD_ENTER(KEYPAD, 2, "EnterKey");
            // TODO, others
        private static Map<FunctionCategory, Set<FunctionValue>> codeMapping = new EnumMap<>( FunctionCategory.class );

        static {
            for( FunctionValue fv : FunctionValue.values() ) {
                Set<FunctionValue> values = codeMapping.get(fv.getCategory());
                if( values == null ) {
                    values = EnumSet.of(fv);
                }
                else {
                    values.add(fv);
                }
                codeMapping.put(fv.getCategory(), values);
            }
        }

            // First we look up the category, then we just loop over all the values
            // within that category. Unless you have lots of values, or really need
            // to optimize the lookups, there is no need to do something more complex
        public static FunctionValue getFromCodes( int categoryCode, int valueCode ) {
            FunctionCategory c = FunctionCategory.fromCode(categoryCode);
            if( c != null ) {
                Set<FunctionValue> valueSet = codeMapping.get(c);
                if( valueSet != null ) {
                    // Just spin through them, there aren't that many
                    for( FunctionValue v : valueSet ) {
                        if( v.getCode() == valueCode ) {
                            return v;
                        }
                    }
                }
            }
            return null;
        }

        private final FunctionCategory category;
        private final int code;
        private final String name;
        private FunctionValue(FunctionCategory category, int code, String name) {
            this.category = category;
            this.code = code;
            this.name = name;
        }
        public FunctionCategory getCategory() {
            return category;
        }
        public int getCode() {
            return code;
        }
        public String getName() {
            return name;
        }       
    }
}