Как получить класс параметризованного типа в Java без его создания? [Дубликат]

Относительно ошибки «no such file»:

source - это внутренняя команда оболочки (см., например, Bash Builtin Commands ), а не внешнюю программу, которую вы можете запустить. В вашей системе нет исполняемого файла с именем source, поэтому вы получаете ошибку No such file or directory.

Вместо модуля command используйте shell , который будет выполнять source внутри оболочки.


Что касается проблемы с источником:

В цикле with_items Ansible будет запускать оболочку дважды, и оба процесса будут независимы от каждого Другие. Переменные, установленные в одном, не будут отображаться другим.

Вы должны запустить две команды в одном процессе оболочки, например, с помощью:

- name: Install node {{ nvm.node_version }}
  shell: "source /home/centos/.nvm/nvm.sh && nvm install {{ nvm.node_version }}"
  tags: nvm

Другие замечания:

Используйте {{ ansible_env.HOME }} вместо ~ в задаче git. Любой из них будет работать здесь, но расширение тильды - это функциональность оболочки, и вы пишете код для Ansible.

49
задан Ben Lakey 16 June 2009 в 22:25
поделиться

8 ответов

Я использовал аналогичное решение для того, что он объясняет здесь для нескольких проектов, и нашел, что это очень полезно.

http://blog.xebia.com/2009/02/07 / acessing-generic-types-at-runtime-in-java /

Суть его заключается в следующем:

 public Class returnedClass() {
     ParameterizedType parameterizedType = (ParameterizedType)getClass()
                                                 .getGenericSuperclass();
     return (Class) parameterizedType.getActualTypeArguments()[0];
}
58
ответ дан sgriffinusa 21 August 2018 в 01:01
поделиться
  • 1
    +1! я собирался написать об этом – Andreas Petersson 17 June 2009 в 07:32
  • 2
    +1 И это в значительной степени решение, с которым я пошел после дальнейших исследований, поэтому я изменил его на мой принятый ответ. – Ben Lakey 19 June 2009 в 04:49
  • 3
    Дает мне Exception in thread "main" java.lang.ClassCastException: java.lang.Class cannot be cast to java.lang.reflect.ParameterizedType Вы уверены, что это работает? – Ram 12 May 2011 в 11:28
  • 4
    Вот что происходит в Android: getClass (). GetGenericSuperclass () возвращает объект класса, представляющий java.lang.Object, который не передается в ParameterizedType. Если ваш класс наследует от манекена Base & lt; T & gt ;, возвращаемое значение представляет собой «Base & lt; T & gt;» & quot; и getActualTypeArguments () [0] возвращает тип с именем «T», который даже не передается классу. Нет. – misiu_mp 13 August 2011 в 13:18
  • 5
    Здесь стоит отметить, что это будет работать только для классов, параметры типов которых явно объявлены в java-коде. Этот тип логики не будет работать для таких вещей, как макеты, реализованные с помощью динамического проксирования. – Paul Morie 9 May 2012 в 18:47

Я согласен с Visage. Генерики предназначены для проверки времени компиляции, а не для динамического набора времени выполнения. Похоже на то, что вам нужно, это просто фабричная модель. Но если ваше «делать это» не является инстанцированием, то, скорее всего, будет работать простой Enum. Как и то, что сказал Майкл, если у вас есть немного более конкретный пример, вы получите лучшие ответы.

0
ответ дан aberrant80 21 August 2018 в 01:01
поделиться
  • 1
    Я должен не согласиться здесь, и было несколько упоминаний о неполиморфном решении, которое необходимо в конкретном проблемном пространстве, и я был вполне доволен полученными ответами. – Ben Lakey 19 June 2009 в 04:47

В отличие от .NET Java generics реализуются методом, называемым стиранием типа.

. Это означает, что компилятор будет использовать информацию о типе при создании файлов классов, но не передавать это информацию в байтовый код. Если вы посмотрите на скомпилированные классы с помощью javap или аналогичных инструментов, вы обнаружите, что List<String> является простым List (Object) в файле класса, как это было в коде pre-Java-5.

. Кодирование, получающее общий список, будет «перезаписано» компилятором, чтобы включить в него броски, которые вам придется писать в более ранних версиях. По сути, следующие два фрагмента кода идентичны с точки зрения байтового кода после компилятора с ними:

Java 5:

List<String> stringList = new ArrayList<String>();
stringList.add("Hello World");
String hw = stringList.get(0);

Java 1.4 и до:

List stringList = new ArrayList();
stringList.add("Hello World");
String hw = (String)stringList.get(0);

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

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

Оба подхода имеют свои плюсы и минусы, но так оно и есть находится в Java.

Чтобы вернуться к исходному вопросу: вы не сможете получить информацию о типе во время выполнения, потому что его просто больше нет, как только компилятор выполнил свою работу. Это, безусловно, ограничивает в некотором роде и есть некоторые капризные способы вокруг него, которые обычно основаны на хранении экземпляра класса где-то, но это не стандартная функция.

44
ответ дан Daniel Schneller 21 August 2018 в 01:01
поделиться

Проблема заключается в том, что большинство обобщающих материалов исчезнет во время компиляции.

Одним из распространенных решений является сохранение типа во время создания объекта.

Для краткого введения в поведение типа Erasure java прочтите эту страницу

3
ответ дан Janusz 21 August 2018 в 01:01
поделиться
  • 1
    Это очень полезно - я видел решения, которые связаны с этим, и может закончиться тем, что идет по этому маршруту. – Ben Lakey 16 June 2009 в 22:33
  • 2
    Вероятно, ваш дизайн плохой. – Tom Hawtin - tackline 16 June 2009 в 23:12

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

0
ответ дан Michael Borgwardt 21 August 2018 в 01:01
поделиться

Из-за стирания типа , нет никакого способа сделать это напрямую. Тем не менее, вы можете сделать Class<T> в конструкторе и удерживать его внутри вашего класса. Затем вы можете проверить его на три возможных типа Class, которые вы разрешаете.

Однако, если есть только три возможных типа, вы можете рассмотреть рефакторинг в enum вместо этого.

12
ответ дан Michael Myers 21 August 2018 в 01:01
поделиться
  • 1
    Это похоже на лучшее решение, хотя и менее красивое, чем настоящий синий родовой класс. Спасибо за ввод. – Ben Lakey 16 June 2009 в 22:35
  • 2
    Опять же, я настоятельно рекомендую вам решительно рассматривать полиморфизм, а не if-statement, основанный на типе. – Michael Myers♦ 16 June 2009 в 22:36
  • 3
    К сожалению, рассматриваемые вопросы никоим образом не связаны, поэтому полиморфное решение нецелесообразно. Возможные элементы, которые попадают в логику if-statement, являются краевыми случаями всей другой «нормальной» обработки, которые должны рассматриваться совершенно иначе, без реляционных способностей. – Ben Lakey 16 June 2009 в 22:39
  • 4
    @dxmio: Элементы соотносятся таким образом: что вы создаете Foo & lt; gt; из них. Я не говорю, что это флип: вы можете создать «Fooable». интерфейс и каждый из них реализует это - и интерфейс может иметь единственный метод, который возвращает их тип (или, лучше, перечисление). – Carl Manaster 16 June 2009 в 22:49
  • 5
    Это не удается с Java & lt; = 1.6.0.32 с ошибкой несравнимых типов. – HDave 8 August 2013 в 04:07

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

0
ответ дан PaulJWilliams 21 August 2018 в 01:01
поделиться
  • 1
    Правда, однако, если я создаю класс, который может быть создан в общем виде любым типом, я хочу обрабатывать конкретное подмножество всех возможных типов в качестве краевых случаев с определенной логикой. – Ben Lakey 16 June 2009 в 22:29
  • 2
    Затем создайте разные подтипы. Или делегировать стратегии (или аналогичные). – Tom Hawtin - tackline 16 June 2009 в 23:10

Если вы знаете несколько конкретных типов, которые имеют смысл, вы должны создать подклассы вашего общего типа с реализацией.

Итак,

public class Foo<T>

public ???? Bar()
{
    //else condition goes here
}

И затем

public class DateFoo extends Foo<Date>

public ???? Bar()
{
    //Whatever you would have put in if(T == Date) would go here.
}
1
ответ дан Ryan Shillington 21 August 2018 в 01:01
поделиться
Другие вопросы по тегам:

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