首页 文章

Java:当项目不相关时,绑定异构集合

提问于
浏览
1

如果我有异构集合,我确切知道我将要放置的类型是否有办法强制执行此操作 .

例如,假设我有一个具有String键和值的映射,该映射可以是三个不相关的类型 . 现在我知道我只会放ClassA和ClassB或java.lang.String

例如,这里是代码

public HetroCollection
{
    public Map<String,Object> values;
}

public ClassA
{
}

public ClassB
{
}

public static void Main(String args[])
{
   HetroCollection collection = new HetroCollection();
   collection.values.add("first", new ClassA());
   collections.values.add("second", new ClassB());
   collections.values.add("third" , "someString");
   //BAD want to stop random adds
   collections.values.("fourth" , new SomeRandomClass());
}

我想到的选项是:

  • 让类实现一个通用接口并在Map上使用Generics(问题是,如果这也涉及到JDK或第三方的库类,那么更改类不是一个选项

  • 隐藏Map并提供put方法,如paratemized

put(String key,ClassA value); put(String key,ClassB value); put(String key,String value); get(String key);

  • 重新思考设计并且不使用异构集合(不确定我将如何以任何其他方式表示)

寻找最佳实践答案 .

5 回答

  • 0

    我认为,“最佳实践”解决方案是您的第一和第三选择,只要情况允许 .

    你没有考虑的另一个选择是这样的:

    public class MyMap extends HashMap<String, Object> {
        ...
        // constructors
        ...
        @Override
        public void put(String key, Object value) {
            if (value instanceof ClassA || value instanceof ClassB) {
                super.put(key, value);
            } else {
                throw new IllegalArgumentException("Verbotten!");
            }
        }
        ...
    }
    

    您可以将此与第二个选项结合使用,以便存在静态类型选项,甚至可能将 put(String, Object) 方法标记为已弃用以阻止其使用 .

    最后,可以选择忽略问题,并依赖应用程序员不要将随机内容放入 Map 中 . 根据具体情况,这甚至可能是最佳解决方案 .

  • 2

    好吧,你已经证明你首先想到的不是一个选择 . 如果你真的需要这个功能,第二个想法是最好的选择 . 否则最好的选择是重新考虑你的方法 . 但是,如果我们知道一些上下文,它会更容易帮助 .

  • 1

    还有第四种选择:

    如果你想将这些类型的实例粘贴到一个集合中,很可能它们有一些共同之处 . 如果你不能引入一个通用的超类型来表达这种共性,你仍然可以引入一个具有这种公共超类的并行类层次结构,并声明你的 Map 可以保存那种类型的项目 .

    // You can find a better name ;-)
    abstract class Foo {
        public abstract void foo();
    
        public void bar() {
            // something generic
        }
    
        public abstract void visit(FooVisitor visitor);
    }
    
    class ClassAFoo {
        final ClassA delegate;
    
        // Constructor and implementations for foo()
    
    }
    
    class ClassBFoo {
        final ClassB delegate;
    
        // Constructor and implementations for foo()
    
    }
    
    class StringFoo {
        final String delegate;
    
        // Constructor and implementations for foo()
    }
    

    好处:

    • 静态类型安全

    • 您可以将方法添加到公共类型或实现访问者模式以打开包装值的类型

    • 编译器可以在处理 Map 时检查您是否已经处理了所有类型(与使用一系列if语句来打开类型相反)

    缺点:

    • 样板代码,复杂性
  • 0

    这个被称为类的Java有一个很好的工具 . 举个例子,你可以写一个这样的:

    public class Foo {
      private ClassA first;
      private ClassB second;
      private String someString;
    
      ...
    
      public void setFirst(ClassA first) {
        this.first = first;
      }
    
      public ClassA getFirst() {
        return first;
      }
    
      ...
    }
    

    说真的,给你've said this sounds like exactly what you want. If you only want to allow specific keys, with values that may only be of specific types (that depend on the key itself)... that'一个 class . 如果你有一些非常强烈的理由需要在这里使用 String Map 密钥(这对我来说似乎不太可能),请解释一下 .

    Edit:

    当我回答这个问题时,由于某种原因,我需要强制执行仅映射到特定类型值的特定键 . 再看一遍,似乎情况可能并非如此 . 如果情况并非如此,我认为您最好的选择是重新思考设计(举例说明您需要这样做的原因可能会有所帮助) . 如果你这样做并且没有想出任何东西,我认为#2是最好的选择 . 它以某种类型安全的方式强制限制 Map 可以具有的值类型 .

  • 0

    理论上,使用Functional Java中的HList可以实现List中混合对象的类型安全性 . 见blog postExamples . IBM developerworks也相关this article . 我在理论上写道,因为在实践中,类型声明只能处理有限数量的元素,并且它会迅速增长 .

相关问题