【问题标题】:Define generic/variable type for data structure定义数据结构的泛型/变量类型
【发布时间】:2013-03-19 16:28:01
【问题描述】:

我有一个数据结构(LinkedHashMap),但问题是(第二个)值应该是变量类型,因为我可以在那里输入类型 String 或类型 int 或任何原始类型所以我的问题是:

有没有办法为它定义一个可以获取任何值类型的变量类型?

这就是我所拥有的:

private LinkedHashMap<String, String> keyVal;

我想要这样的东西:

private LinkedHashMap<String, anyValue> keyVal;

【问题讨论】:

  • 这正是泛型试图帮助避免的!如果你需要这个,你想要完成的事情很可能有问题。但如果你想走这条路,&lt;? extends Object&gt; 就是你所需要的……
  • 我假设您想使用 java.util.LinkedHashMap 但不想指定第二个类型参数?

标签: java generics type-conversion


【解决方案1】:
private LinkedHashMap<String, Object> keyVal;

您可以为此使用Object。但请记住,在尝试从该映射中取回数据时(稍后),您可能难以将 Object 转换为所需的数据类型,因为您可能不知道实际存在的数据类型。

因此,建议避免此类实现。

【讨论】:

  • 你能想出一些其他的解决方案吗,我试图做的是将 json 对象转换为键值列表,而不是使用相应的类型来处理它......
【解决方案2】:

您不能将泛型类型设为原始类型。如果您希望能够在地图中存储任何内容,则可以将地图的“值”泛型类型设为Object

private LinkedHashMap<String, Object> keyVal;

由于自动装箱,您仍然可以存储看起来像原始类型的内容,即

keyVal.put("one", 1);

将放置一个Integer,即使您指定了int

【讨论】:

    【解决方案3】:

    不,您可以使用的最接近的参数是 Object 作为第二个参数。

    现在,我建议重新考虑您需要完成什么,因为这实际上与创建泛型的目的反对

    如果你有一个绑定类型并且想要保持一些灵活性,那么你可以使用类似&lt;String, ? extends SomeType&gt;的东西。

    在 Java 中不建议在同一个数据结构中混合多种类型的对象(如果这是好的或坏的,那就不重要了),但类型安全在防止奇怪的错误方面大有帮助。

    试着想想当你真正需要 来检索对象时你会如何处理这个问题……你会假设它们是字符串吗?你打算怎么处理他们?

    【讨论】:

      【解决方案4】:

      你说你想要一个 Map原始类型>.

      the JLS指定的A,原语为NumericTypebooleanNumericTypeIntegralTypeFloatingPointType.

      如果你的需求不是primitive,而只是NumericType,你可以使用java.lang.Number:

      Map< String, Number >
      

      另一种方法是定义一个包含所有可能属性的类 Any:

      enum Type {
          NULL,
          INTEGER,
          SHORT,
          FLOAT,
          ...
      }
      
      class Any {
         private int   iValue;
         private short sValue;
         private float fValue;
         ...
         private Type  active = Type.NULL;
      
         public void setInt( int value ) {
            iValue = value;
            active = Type.INTEGER;
         }
         public void setFloat( float value ) {
            fValue = value;
            active = Type.FLOAT;
         }
         ...
         public int getInt() {
            if( type !=  Type.INTEGER ) {
               throw new ClassCastException( type.name() + " is not an integer" );
            }
            return iValue;
         }
         ...
      }
      

      如果在 float 持有者上调用 getInt(),则由您进行一些检查并抛出异常。一切皆有可能,例如像 C 语言那样的转换。

      编辑

      你也想要字符串,还有String isn't a primitive

      您必须将以下private short sValue; 添加到Any 类中:

      private String sValue;
      

      以及SHORT, 下面的followinf 进入Type 枚举:

      STRING,
      

      但是,正如其他人所说,最好的方法是避免使用这些弱类型 (法语为fourre-tout)。

      【讨论】:

      • 好的但是如果我有字符串我应该如何处理它?
      【解决方案5】:

      你可以使用

      private LinkedHashMap<String, Object> keyVal;
      

      让第二种类型的参数尽可能通用。 它允许您将任何对象存储为值,因为每个类都扩展 Object

      这会导致您不知道地图中的事物是什么类型的问题 - 您只知道它们是 Object 类型的,这意味着您什么都不知道

      因此,要再次使用这些对象,您必须将它们转换回原来的类型,这可能会导致运行时异常:ClassCastException

      Generics 是关于使用相同代码为不同类型定义数据结构,但是如果您想使用泛型类,则必须使用其类型参数对其进行参数化。这确保了类型在运行时是已知的,并且是泛型的一大优势(避免ClassCastException)。 但是,您仍然可以指定允许多种类型的更通用的类型。

      例如,如果您按以下方式定义它,您可以存储任何实现Serializable 的对象。

      private LinkedHashMap<String, ? extends Serializable> keyVal;
      

      如您所见,这允许您将允许的类型限制为公共属性(即,成为更通用类型的子类)。这样,您就可以将地图的值用作更通用类的对象,因为它是您所知道(并且想知道)的关于对象的一切。

      【讨论】:

        【解决方案6】:
        1. 最好看看: Generics lesson on Oracle.com
        2. 注意什么时候应该使用通配符 (?) 并且应该使用泛型。
        3. 不推荐使用LinkedHashMap&lt;String, Object&gt; keyVal; 类型的对象。

        【讨论】:

          【解决方案7】:

          就像有些人说的,你可以使用 Object 作为泛型变量类型,尤其是在使用泛型方法或不知道用户会来什么数据类型时,就像这个简单的:

          import java.util.Scanner;
          
          public class GenericMethod {
              public static void main(String[] args) {
                  System.out.println("Type something that's yours: ");
          
                  Scanner sc = new Scanner(System.in);
          
                  Object thing;
                  thing = sc.next();
                  isMine(thing);
              }
          
              // Generic Method
              public static <T> void isMine(T x) {
                  System.out.println(x + " is mine.");
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2019-12-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-04-28
            • 1970-01-01
            • 2020-04-21
            相关资源
            最近更新 更多