возможно ли получить детские уроки от родителей? [Дубликат]

Если refs / heads / master может быть быстро перенаправлен на refs / remotes / foo / master, вывод

git merge-base refs/heads/master refs/remotes/foo/master

должен вернуть идентификатор SHA1, который ссылается на / heads / master points. С этим вы можете собрать скрипт, который автоматически обновляет все локальные ветви, у которых не было никаких отвлекающих коммитов.

Этот маленький скрипт оболочки (я назвал его git-can-ff) иллюстрирует, как он может

#!/bin/sh

set -x

usage() {
    echo "usage: $(basename $0) <from-ref> <to-ref>" >&2
    exit 2
}

[ $# -ne 2 ] && usage

FROM_REF=$1
TO_REF=$2

FROM_HASH=$(git show-ref --hash $FROM_REF)
TO_HASH=$(git show-ref --hash $TO_REF)
BASE_HASH=$(git merge-base $FROM_REF $TO_REF)

if [ "$BASE_HASH" = "$FROM_HASH" -o \
     "$BASE_HASH" = "$FROM_REF" ]; then
    exit 0
else
    exit 1
fi
125
задан sschuberth 23 October 2015 в 14:43
поделиться

13 ответов

Я использую org.reflections :

Reflections reflections = new Reflections("com.mycompany");    
Set<Class<? extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);
131
ответ дан sschuberth 19 August 2018 в 09:45
поделиться
  • 1
    Спасибо за ссылку о org.reflections. Я ошибочно полагал, что это будет так же просто, как в мире .Net, и этот ответ спас мне много времени. – akmad 1 October 2012 в 20:55
  • 2
    Благодарим вас за эту полезную ссылку на отличный пакет & quot; org.reflections & quot ;! С этим я наконец нашел практичное и аккуратное решение для моей проблемы. – Hartmut 7 July 2015 в 13:15
  • 3
    Есть ли способ получить все отражения, т. Е. Не отметив конкретный пакет, но загружая все доступные классы? – joey baruch 13 February 2017 в 14:39
  • 4
    Помните, что поиск классов не решит вашу проблему их создания (строка 5 animals.add( new c() ); вашего кода), поскольку в то время как Class.newInstance() существует, у вас нет гарантии, что у конкретного класса есть конструктор без параметров (C # позволяет вам потребовать что в общем случае) – usr-local-ΕΨΗΕΛΩΝ 21 March 2018 в 11:53
  • 5
    См. Также ClassGraph: github.com/classgraph/classgraph (Отказ от ответственности, я автор). Я приведу пример кода в отдельном ответе. – Luke Hutchison 1 August 2018 в 03:37

Java-способ сделать то, что вы хотите, использовать механизм ServiceLoader .

Также многие люди сворачивают свои собственные, имея файл в известном местоположении пути к методу (например, /META-INF/services/myplugin.properties), а затем используя ClassLoader.getResources () , чтобы перечислять все файлы с этим именем из всех банок. Это позволяет каждой банке экспортировать своих собственных поставщиков, и вы можете создавать их путем отражения с помощью Class.forName ()

32
ответ дан 2 revs, 2 users 94% 19 August 2018 в 09:45
поделиться
  • 1
    Для создания файла служб META-INF легко на основе аннотаций на классы, вы можете проверить: metainf-services.kohsuke.org или code.google.com/p/spi – elek 15 November 2012 в 15:48
  • 2
    Bleah. Просто добавляет уровень сложности, но не устраняет необходимость как создания класса, так и регистрации его в далекой далекой стране. – kevin cline 15 May 2013 в 21:41
  • 3
    Пожалуйста, см. Ответ ниже с 26 upvotes, намного лучше – SobiborTreblinka 23 January 2014 в 23:08
  • 4
    Действительно, если вам нужны какие-то рабочие решения, Reflections / Scannotations - хороший вариант, но оба они навязывают внешнюю зависимость, не детерминированы и не поддерживаются Java Community Process. Кроме того, я хотел подчеркнуть, что вы никогда не сможете надежно получить ВСЕ классы, реализующие интерфейс, так как тривиально выпускать новый из тонкого воздуха в любое время. Для всех своих бородавок сервисный загрузчик Java легко понять и использовать. Я бы держался подальше от него по разным причинам, но тогда сканирование классов еще хуже: stackoverflow.com/a/7237152/18187 – ddimitrov 27 January 2014 в 03:34

используйте эту

public static Set<Class> getExtendedClasses(Class superClass)
{
    try
    {
        ResolverUtil resolver = new ResolverUtil();
        resolver.findImplementations(superClass, superClass.getPackage().getName());
        return resolver.getClasses();  
    }
    catch(Exception e)
    {Log.d("Log:", " Err: getExtendedClasses() ");}

    return null;
}

getExtendedClasses(Animals.class);

Редактировать:

1
ответ дан Ali Bagheri 19 August 2018 в 09:45
поделиться
  • 1
    Вы должны сказать немного больше о ResolverUtil. Что это? Из какой библиотеки это происходит? – JohnnyLambada 8 April 2018 в 00:01

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

Найти Java-классы, реализующие интерфейс

Реализации просто должны создать package-info.java и включить магическую аннотацию в список классов, которые они хотят поддерживать.

0
ответ дан Community 19 August 2018 в 09:45
поделиться

Вы можете использовать ResolverUtil ( исходный источник ) из Stripes Framework , если вам нужно что-то простое и быстрое, не рефакторинг существующего кода.

Вот простой пример, не загружающий ни один из классов:

package test;

import java.util.Set;
import net.sourceforge.stripes.util.ResolverUtil;

public class BaseClassTest {
    public static void main(String[] args) throws Exception {
        ResolverUtil<Animal> resolver = new ResolverUtil<Animal>();
        resolver.findImplementations(Animal.class, "test");
        Set<Class<? extends Animal>> classes = resolver.getClasses();

        for (Class<? extends Animal> clazz : classes) {
            System.out.println(clazz);
        }
    }
}

class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
class Donkey extends Animal {}

Это также работает и на сервере приложений, так как именно там он был предназначен для работы;)

Код в основном выполняет следующие действия:

  • выполняет итерацию по всем ресурсам пакета (ов), который вы указываете
  • , сохраняет только ресурсы, заканчивающиеся на .class
  • Загрузите эти классы с помощью ClassLoader#loadClass(String fullyQualifiedName)
  • Проверяет, Animal.class.isAssignableFrom(loadedClass);
4
ответ дан DJDaveMark 19 August 2018 в 09:45
поделиться

Спасибо всем, кто ответил на этот вопрос.

Кажется, это действительно крутая гайка. Я закончил тем, что отказался от создания статического массива и getter в моем базовом классе.

public abstract class Animal{
    private static Animal[] animals= null;
    public static Animal[] getAnimals(){
        if (animals==null){
            animals = new Animal[]{
                new Dog(),
                new Cat(),
                new Lion()
            };
        }
        return animals;
    }
}

Кажется, что Java просто не настроен для самонастраиваемости, как это делает C #. Я полагаю, проблема заключается в том, что, поскольку приложение Java - это всего лишь коллекция файлов .class в файле directory / jar где-то, среда выполнения не знает о классе, пока не будет упомянута ссылка. В это время загрузчик загружает его - то, что я пытаюсь сделать, это обнаружить его, прежде чем ссылаться на него, что невозможно, не выходя из файловой системы и не глядя.

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

Еще раз спасибо!

1
ответ дан JohnnyLambada 19 August 2018 в 09:45
поделиться
  • 1
    Java создан для самообнаружения. Вам просто нужно немного поработать. См. Мой ответ для деталей. – Dave Jarvis 23 January 2010 в 23:12

Попробуйте ClassGraph . (Отказ от ответственности, я автор). Для данного примера код ClassGraph будет выглядеть следующим образом:

List<Animal> animals =
    new ClassGraph()
        .whitelistPackages("com.zoo.animals")
        .enableAllInfo()
        .scan()
        .getSubclasses(Animal.class.getName())
        .loadClasses(Animal.class);

ClassGraph может сделать намного больше, чем это - проверить API .

1
ответ дан Luke Hutchison 19 August 2018 в 09:45
поделиться

Используя OpenPojo , вы можете сделать следующее:

String package = "com.mycompany";
List<Animal> animals = new ArrayList<Animal>();

for(PojoClass pojoClass : PojoClassFactory.enumerateClassesByExtendingType(package, Animal.class, null) {
  animals.add((Animal) InstanceFactory.getInstance(pojoClass));
}
1
ответ дан Osman Shoukry 19 August 2018 в 09:45
поделиться

Подумайте об этом с точки зрения аспекта; то, что вы хотите сделать, действительно, знает все классы во время выполнения, которые расширили класс Animal. (Я думаю, это немного более точное описание вашей проблемы, чем ваше название, иначе я не думаю, что у вас есть вопрос о времени исполнения.)

Итак, я думаю, что вы хотите создать конструктор своего базовый класс (Animal), который добавляет к вашему статическому массиву (я предпочитаю ArrayLists, сам, но каждому свой) тип текущего класса, который создается.

Итак, грубо,

public abstract class Animal
    {
    private static ArrayList<Class> instantiatedDerivedTypes;
    public Animal() {
        Class derivedClass = this.getClass();
        if (!instantiatedDerivedClass.contains(derivedClass)) {
            instantiatedDerivedClass.Add(derivedClass);
        }
    }

Конечно, вам понадобится статический конструктор для Animal для инициализации экземпляра endivedDerivedClass ... Я думаю, что это сделает то, что вы, вероятно, захотите. Обратите внимание, что это зависит от выполнения; если у вас есть класс Dog, который происходит от Animal, который никогда не будет вызван, вы не получите его в списке вашего класса животных.

8
ответ дан Paul Sonier 19 August 2018 в 09:45
поделиться
  • 1
    Никакого улучшения существующего кода OP. – kevin cline 15 May 2013 в 21:35

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

0
ответ дан pdeva 19 August 2018 в 09:45
поделиться

К сожалению, это не совсем возможно, так как ClassLoader не скажет вам, какие классы доступны. Вы можете, однако, довольно близко сделать что-то вроде этого:

for (String classpathEntry : System.getProperty("java.class.path").split(System.getProperty("path.separator"))) {
    if (classpathEntry.endsWith(".jar")) {
        File jar = new File(classpathEntry);

        JarInputStream is = new JarInputStream(new FileInputStream(jar));

        JarEntry entry;
        while( (entry = is.getNextJarEntry()) != null) {
            if(entry.getName().endsWith(".class")) {
                // Class.forName(entry.getName()) and check
                //   for implementation of the interface
            }
        }
    }
}

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

6
ответ дан Renaud 19 August 2018 в 09:45
поделиться
  • 1
    Это плохо работает, когда классы загружаются другими способами, например, в веб-контейнере или контейнере J2EE. – johnstok 15 October 2008 в 20:33
  • 2
    Возможно, вы могли бы сделать лучшую работу даже под контейнером, если бы вы запросили пути (часто URL[], но не всегда, так что это может быть невозможно) из иерархии ClassLoader. Часто, хотя у вас должно быть разрешение, так как обычно у вас будет SecurityManager, загруженный в JVM. – Kevin Brock 31 March 2011 в 19:58
  • 3
    Работал как прелесть для меня! Я боялся, что это будет слишком тяжелый вес и медленный, пройдя все классы в пути к классам, но на самом деле я ограничил файлы, которые я проверил, на те, которые содержат «-ejb- & quot; или других распознаваемых имен файлов, и он по-прежнему в 100 раз быстрее, чем запуск встроенной Glassfish или EJBContainer. В моей конкретной ситуации я затем проанализировал классы, ищущие «Безстоящие», «Stateful» и «Singleton». аннотации, и если бы я их увидел, я добавил имя JNDI Mapped в свой MockInitialContextFactory. Еще раз спасибо! – cs94njw 25 March 2013 в 12:32

Java динамически загружает классы, поэтому ваш юниверс классов будет только теми, которые уже загружены (и еще не выгружены). Возможно, вы можете сделать что-то с помощью специального загрузчика классов, который мог бы проверять супертипы каждого загруженного класса. Я не думаю, что есть API для запроса набора загруженных классов.

2
ответ дан thoroughly 19 August 2018 в 09:45
поделиться

Один из способов - заставить классы использовать статические инициализаторы ... Я не думаю, что они наследуются (они не будут работать, если они есть):

public class Dog extends Animal{

static
{
   Animal a = new Dog();
   //add a to the List
}

Он требует от вас добавьте этот код ко всем классам. Но он избегает наличия большой уродливой петли где-то, проверяя каждый класс, ищущий детей Animal.

0
ответ дан user 19 August 2018 в 09:45
поделиться
  • 1
    Это не работает в моем случае. Поскольку класс не упоминается нигде, он никогда не загружается, поэтому статический инициализатор никогда не вызывается. Кажется, что статический инициализатор вызывается перед всем остальным при загрузке класса, но в моем случае класс никогда не загружается. – JohnnyLambada 15 October 2008 в 21:47
Другие вопросы по тегам:

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