я хотел бы сделать динамический кастинг для явской переменной, тип кастинга сохранен в другой переменной.
это - регулярный кастинг:
String a = (String) 5;
это - то, что я хочу:
String theType = 'String';
String a = (theType) 5;
действительно ли это возможно? и раз так как?спасибо!
Я пытаюсь населить класс с hashMap, который я получил.
это - конструктор:
public ConnectParams(HashMap<String,Object> obj) {
for (Map.Entry<String, Object> entry : obj.entrySet()) {
try {
Field f = this.getClass().getField(entry.getKey());
f.set(this, entry.getValue()); /* <= CASTING PROBLEM */
} catch (NoSuchFieldException ex) {
log.error("did not find field '" + entry.getKey() + '"');
} catch (IllegalAccessException ex) {
log.error(ex.getMessage());
}
}
}
проблема здесь состоит в том, что некоторые переменные классов удваивают тип, и если номер 3 получен, он рассматривает его как Целое число, и у меня есть проблема типа.
Единственный способ решить эту проблему в Java - это написать код, который охватывает все случаи с большим количеством выражений
if
иelse
иinstanceof
. То, что вы пытаетесь сделать, выглядит так, как будто вы привыкли программировать с динамическими языками. В статических языках то, что Вы пытаетесь сделать, практически невозможно, и, вероятно, Вы бы выбрали совершенно другой подход к тому, что Вы пытаетесь сделать. Статические языки просто не такие гибкие, как динамические :)Хорошими примерами наилучшей практики Java являются ответ от BalusC (т.е.
ObjectConverter
) и ответ от Andreas_D (т.е.Adapter
), которые приведены ниже.
Это не имеет смысла, в
String a = (theType) 5;
тип a
статически привязан к String
, поэтому нет никакого смысла в динамическом приведении к этому статическому типу.
PS: Первая строка вашего примера может быть записана как Class
, но все же вы не можете использовать stringClass
для приведения переменных.
Да, это возможно использование Отражение
Object something = "something";
String theType = "java.lang.String";
Class<?> theClass = Class.forName(theType);
Object obj = theClass.cast(something);
, но это не имеет большого смысла, так как результирующий объект должен быть сохранен в переменной Тип объекта. Если вам нужна переменная, имеющая данный класс, вы можете просто отменить в этот класс.
Если вы хотите получить данный класс, номер, например:
Object something = new Integer(123);
String theType = "java.lang.Number";
Class<? extends Number> theClass = Class.forName(theType).asSubclass(Number.class);
Number obj = theClass.cast(something);
, но все еще нет смысла делать это так, вы могли бы просто отбрасывать на номер.
Литье объекта ничего не меняет; Это всего лишь путь Компилятор относится к нему.
Единственная причина, причина, делающая что-то подобное, - это проверить, является ли объект экземпляром данного класса или любого подкласса его, но это было бы лучше сделано с использованием instanceOf
или классов. )
.
Согласно вашему последнему Обновление Реальная проблема заключается в том, что у вас есть целое число в вашем hashmap, который должен быть назначен двойным. То, что вы можете сделать в этом случае, проверяет тип поля и использовать XXXValue ()
Методы номера
...
Field f = this.getClass().getField(entry.getKey());
Object value = entry.getValue();
if (Integer.class.isAssignableFrom(f.getType())) {
value = Integer.valueOf(((Number) entry.getValue()).intValue());
} else if (Double.class.isAssignableFrom(f.getType())) {
value = Double.valueOf(((Number) entry.getValue()).doubleValue());
} // other cases as needed (Long, Float, ...)
f.set(this, value);
...
(не уверены, если мне нравится идея иметь неправильный тип на карте)
Вам нужно будет написать вроде objectConverter
для этого. Это выполнимо, если у вас есть оба объекта, который вы хотите преобразовать, и вы знаете целевой класс, к которому вы хотите преобразовать. В этом конкретном случае вы можете получить целевой класс на поле # GetDeclaringClass ()
.
Вы можете найти здесь Пример такого ObjectConverter
. Это должно дать вам базовую идею. Если вы хотите больше возможностей преобразования, просто добавьте больше методов к нему желаемым аргументом и типом возврата.
Вы можете сделать это, используя метод CALS.CACH ()
, который динамически бросил прилагаемый параметр на тип экземпляра класса. Чтобы получить экземпляр класса определенного поля, вы используете метод GetType ()
на поле рассматриваемого. Я дал пример ниже, но обратите внимание, что оно пропускает всю обработку ошибок и не следует использовать немодифицированные.
public class Test {
public String var1;
public Integer var2;
}
public class Main {
public static void main(String[] args) throws Exception {
Map<String, Object> map = new HashMap<String, Object>();
map.put("var1", "test");
map.put("var2", 1);
Test t = new Test();
for (Map.Entry<String, Object> entry : map.entrySet()) {
Field f = Test.class.getField(entry.getKey());
f.set(t, f.getType().cast(entry.getValue()));
}
System.out.println(t.var1);
System.out.println(t.var2);
}
}
Это работает, и есть даже общий шаблон для вашего подхода: шаблон адаптера . Но, конечно, (1) он не работает для литья Java примитивов на объекты и (2) класс должен быть адаптируемым (обычно путем внедрения пользовательского интерфейса).
С помощью этого шаблона вы можете сделать что-то вроде:
Wolf bigBadWolf = new Wolf();
Sheep sheep = (Sheep) bigBadWolf.getAdapter(Sheep.class);
и метод GetAdapter в Wolf Class:
public Object getAdapter(Class clazz) {
if (clazz.equals(Sheep.class)) {
// return a Sheep implementation
return getWolfDressedAsSheep(this);
}
if (clazz.equals(String.class)) {
// return a String
return this.getName();
}
return null; // not adaptable
}
для вашей особой идеи - это невозможно. Вы не можете использовать строковое значение для отливки.
Ваша проблема не является отсутствием «динамического литья». Литье Integer
- Двойной
невозможно вообще невозможно. Кажется, вы хотите дать Java объектом одного типа, поля возможно, несовместимого типа, и имейте его как-то автоматически выяснить, как преобразовать между типами.
Такая вещь - это анафема к сильно набратому языку, как Java, и IMO по очень веским причинам.
Что вы на самом деле пытаетесь сделать? Все, что использование отражения выглядит довольно рыбным.
Не делай этого. Просто вместо этого есть правильно параметризованный конструктор. Набор и типы параметров соединения фиксируются в любом случае, поэтому нет смысла делать все это все динамически.