Если вы хотите использовать Strings в качестве ключей, вы потеряете безопасность типов, и нет никакого способа обойти это.Вы просто будете отказываться от всей информации, имеющейся у компилятора, и будете вынуждены предоставить ее самостоятельно.
Вместо этого вы можете использовать некоторый класс-оболочку для String, который также содержит информацию о типе.Таким образом, вы можете получить разумную степень безопасности типов.
Вот пример для класса Foo, который оборачивает HashMap и предоставляет методы safe put и get типа:
public class Foo {
static class TypedKey<T> {
final Class<T> clazz;
final String id;
public TypedKey(Class<T> clazz, String id) {
this.clazz = clazz;
this.id = id;
}
@Override
public int hashCode() {
return id.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof TypedKey)) {
return false;
}
return id.equals(((TypedKey<?>) obj).id);
}
@Override
public String toString() {
return id;
}
}
static final TypedKey<String> STRING_KEY = new TypedKey<>(String.class, "String");
static final TypedKey<Integer> INTEGER_KEY = new TypedKey<>(Integer.class, "Integer");
public static void main(String[] args) {
Foo foo = new Foo();
foo.put(STRING_KEY, "bar");
String bar = foo.get(STRING_KEY);
foo.put(INTEGER_KEY, 42);
int baz = foo.get(INTEGER_KEY);
foo.put(STRING_KEY, 42);
}
final Map<TypedKey<?>, Object> map = new HashMap<>();
public <T> void put(TypedKey<T> key, T value) {
map.put(key, value);
}
@SuppressWarnings("unchecked")
public <T> T get(TypedKey<T> key) {
return (T) map.get(key);
}
}