2013-03-19 4 views
1

У меня есть структура данных (LinkedHashMap), но проблема в том, что (второе) значение должно иметь тип переменной, так как я могу поместить там тип String или тип int или любой примитивный тип, поэтому мой вопрос:Определить тип generic/variable для структуры данных

Есть ли способ определить для него тип переменной, который может получить любой тип значения?

Это то, что я имею:

private LinkedHashMap<String, String> keyVal; 

Я хочу что-то вроде этого:

private LinkedHashMap<String, anyValue> keyVal; 
+0

Точно это то, что дженерики пытаются избежать! Если вам это нужно, скорее всего, проблема в том, чего вы хотите выполнить. Но если вы хотите пойти так, ' 'то, что вам нужно ... – ppeterka

+0

Я предполагаю, что вы хотите * использовать *' java.util.LinkedHashMap', но не хотите указывать аргумент второго типа? – user905686

ответ

2
private LinkedHashMap<String, Object> keyVal; 

Для этого вы можете использовать Object. Но помните, что, пытаясь вернуть данные с этой карты (через некоторое время), вы можете столкнуться с трудностями при наборе Object на требуемый тип данных, поскольку, возможно, вы не знаете, какой тип данных действительно присутствует.

Следовательно, его рекомендуется, чтобы избежать таких реализаций.

+0

Можете ли вы подумать о каком-то другом решении, то, что я пытался сделать, - это сфокусировать json-объект на список ключевых значений и работать над ним с соответствующими типами ... –

1

Вы не можете иметь общий тип примитивный тип. Если вы хотите, чтобы иметь возможность хранить ничего в вашей карте, вы можете иметь «значение» общий тип для карты быть Object:

private LinkedHashMap<String, Object> keyVal; 

Вы все еще можете сохранить то, что выглядит как типы примитивов из-за Autoboxing, т.е.

keyVal.put("one", 1); 

поместит Integer, даже если вы указали int.

1

Нет, ближайший вы можете указать Object в качестве второго аргумента.

Теперь я бы посоветовал переосмыслить то, что вам нужно для достижения, поскольку на самом деле это происходит от против каких дженериков были созданы для.

Если у вас есть связанный тип и вы хотите сохранить некоторую гибкость, вы можете использовать что-то вроде <String, ? extends SomeType>.

Смешивание нескольких типов объектов в одной и той же структуре данных не рекомендуется в Java (если это хорошо или плохо, находится рядом с точкой), но безопасность типов имеет большое значение для предотвращения странных ошибок вдоль линии.

Попробуйте подумать о том, как вы справитесь с этим, когда вы на самом деле нужно для извлечения объектов ... предположите ли вы, что это строки? Что вы собираетесь с ними делать?

1

Вы говорите, что хотите иметь карту < String, Примитивный тип>.

Заданный по the JLS, примитивы NumericType или boolean, NumericType являются IntegralType или FloatingPointType.

Если ваша потребность не примитивным но только NumericType, вы можете использовать java.lang.Number:

Map< String, Number > 

Другой способ определить класс Любой который держит все возможные атрибуты:

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

Это до вас, чтобы поставить некоторые проверки и бросить исключение, если getInt() называется на float держателе. Все возможно, транслируя, например, язык C.

EDIT

Вы хотите строки тоже, и String isn't a primitive.

Вы должны добавить следующее ниже private short sValue; в Any класс:

private String sValue; 

и followinf ниже SHORT, в Type перечислении:

STRING, 

Но, как и другие, говорит, лучший путь должен избегать этих слабых типов(fourre-tout на французском языке).

+0

Хорошо. Но если у меня есть строка, как я должен ее обрабатывать? –

1

Вы можете использовать

private LinkedHashMap<String, Object> keyVal; 

оставить второй аргумент типа как можно более общим. Он позволяет хранить любой объект в качестве значения, потому что каждый класс расширяет Object.

Это приведет вас к проблеме, из-за которой вы не знаете, какие вещи находятся на вашей карте - вы знаете только, что они имеют тип Object, что означает, что вы не знаете ничего.

Чтобы снова использовать эти объекты, вам придется отбросить их обратно к исходному типу, что может вызвать исключение во время выполнения: ClassCastException.

Generics об определении структур данных для разных типов с одним и тем же кодом, но если вы хотите использовать общий класс, вы должны параметризовать его своими аргументами типа. Это гарантирует, что тип известен во время выполнения и является большим преимуществом генериков (избегайте ClassCastException). Однако вы можете указать более общий тип, который допускает несколько типов.

Например, если вы определяете его следующим способом, вы можете сохранить любой объект, который реализует Serializable.

private LinkedHashMap<String, ? extends Serializable> keyVal; 

Как вы можете видеть, это позволяет ограничить допустимые типы в общей собственности (то есть, чтобы быть подклассом более общего типа). Таким образом, вы используете значения карты как объекты более общего класса, потому что это все, что вы знаете (и хотите знать) об объектах.

0
  1. Лучше взглянуть на: Generics lesson on Oracle.com.
  2. Уход за использованием диких карт (?), И вы должны использовать Generics.
  3. Использование объекта в типе LinkedHashMap<String, Object> keyVal; не рекомендуется.
Смежные вопросы