Ява: как я могу сделать динамический кастинг переменной от одного типа до другого?

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

это - регулярный кастинг:

 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 получен, он рассматривает его как Целое число, и у меня есть проблема типа.

72
задан ufk 24 January 2010 в 14:19
поделиться

7 ответов

Единственный способ решить эту проблему в Java - это написать код, который охватывает все случаи с большим количеством выражений if и else и instanceof. То, что вы пытаетесь сделать, выглядит так, как будто вы привыкли программировать с динамическими языками. В статических языках то, что Вы пытаетесь сделать, практически невозможно, и, вероятно, Вы бы выбрали совершенно другой подход к тому, что Вы пытаетесь сделать. Статические языки просто не такие гибкие, как динамические :)

Хорошими примерами наилучшей практики Java являются ответ от BalusC (т.е. ObjectConverter) и ответ от Andreas_D (т.е. Adapter), которые приведены ниже.


Это не имеет смысла, в

String a = (theType) 5;

тип a статически привязан к String, поэтому нет никакого смысла в динамическом приведении к этому статическому типу.

PS: Первая строка вашего примера может быть записана как Class stringClass = String.class;, но все же вы не можете использовать stringClass для приведения переменных.

13
ответ дан 24 November 2019 в 12:35
поделиться

Да, это возможно использование Отражение

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

(не уверены, если мне нравится идея иметь неправильный тип на карте)

104
ответ дан 24 November 2019 в 12:35
поделиться

Вам нужно будет написать вроде objectConverter для этого. Это выполнимо, если у вас есть оба объекта, который вы хотите преобразовать, и вы знаете целевой класс, к которому вы хотите преобразовать. В этом конкретном случае вы можете получить целевой класс на поле # GetDeclaringClass () .

Вы можете найти здесь Пример такого ObjectConverter . Это должно дать вам базовую идею. Если вы хотите больше возможностей преобразования, просто добавьте больше методов к нему желаемым аргументом и типом возврата.

21
ответ дан 24 November 2019 в 12:35
поделиться

Вы можете сделать это, используя метод 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);
    }
}
12
ответ дан 24 November 2019 в 12:35
поделиться

Это работает, и есть даже общий шаблон для вашего подхода: шаблон адаптера . Но, конечно, (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
}

для вашей особой идеи - это невозможно. Вы не можете использовать строковое значение для отливки.

4
ответ дан 24 November 2019 в 12:35
поделиться

Ваша проблема не является отсутствием «динамического литья». Литье Integer - Двойной невозможно вообще невозможно. Кажется, вы хотите дать Java объектом одного типа, поля возможно, несовместимого типа, и имейте его как-то автоматически выяснить, как преобразовать между типами.

Такая вещь - это анафема к сильно набратому языку, как Java, и IMO по очень веским причинам.

Что вы на самом деле пытаетесь сделать? Все, что использование отражения выглядит довольно рыбным.

2
ответ дан 24 November 2019 в 12:35
поделиться

Не делай этого. Просто вместо этого есть правильно параметризованный конструктор. Набор и типы параметров соединения фиксируются в любом случае, поэтому нет смысла делать все это все динамически.

1
ответ дан 24 November 2019 в 12:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: