Если 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
Я использую org.reflections :
Reflections reflections = new Reflections("com.mycompany");
Set<Class<? extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);
Java-способ сделать то, что вы хотите, использовать механизм ServiceLoader .
Также многие люди сворачивают свои собственные, имея файл в известном местоположении пути к методу (например, /META-INF/services/myplugin.properties), а затем используя ClassLoader.getResources () , чтобы перечислять все файлы с этим именем из всех банок. Это позволяет каждой банке экспортировать своих собственных поставщиков, и вы можете создавать их путем отражения с помощью Class.forName ()
используйте эту
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);
Редактировать:
Я решил эту проблему довольно элегантно, используя аннотации уровня пакета, а затем сделав эту аннотацию в качестве аргумента списком классов.
Найти Java-классы, реализующие интерфейс
Реализации просто должны создать package-info.java и включить магическую аннотацию в список классов, которые они хотят поддерживать.
Вы можете использовать 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 {}
Это также работает и на сервере приложений, так как именно там он был предназначен для работы;)
Код в основном выполняет следующие действия:
ClassLoader#loadClass(String fullyQualifiedName)
Animal.class.isAssignableFrom(loadedClass);
Спасибо всем, кто ответил на этот вопрос.
Кажется, это действительно крутая гайка. Я закончил тем, что отказался от создания статического массива и 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 где-то, среда выполнения не знает о классе, пока не будет упомянута ссылка. В это время загрузчик загружает его - то, что я пытаюсь сделать, это обнаружить его, прежде чем ссылаться на него, что невозможно, не выходя из файловой системы и не глядя.
Мне всегда нравится код, который может обнаружите себя вместо того, чтобы мне рассказывать о себе, но, увы, это тоже работает.
Еще раз спасибо!
Попробуйте ClassGraph . (Отказ от ответственности, я автор). Для данного примера код ClassGraph будет выглядеть следующим образом:
List<Animal> animals =
new ClassGraph()
.whitelistPackages("com.zoo.animals")
.enableAllInfo()
.scan()
.getSubclasses(Animal.class.getName())
.loadClasses(Animal.class);
ClassGraph может сделать намного больше, чем это - проверить API .
Используя 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));
}
Подумайте об этом с точки зрения аспекта; то, что вы хотите сделать, действительно, знает все классы во время выполнения, которые расширили класс 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, который никогда не будет вызван, вы не получите его в списке вашего класса животных.
Это сложная проблема, и вам нужно будет узнать эту информацию, используя статический анализ, который недоступен во время выполнения. В основном получите путь к классу вашего приложения и просмотрите доступные классы и прочитайте информацию об байт-коде класса, на котором он наследует. Обратите внимание, что класс Dog не может непосредственно наследовать от Animal, но может наследовать от Pet, который наследуется от Animal, поэтому вам нужно будет отслеживать эту иерархию.
К сожалению, это не совсем возможно, так как 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 и не будет работать под приложением сервер.
URL[]
, но не всегда, так что это может быть невозможно) из иерархии ClassLoader. Часто, хотя у вас должно быть разрешение, так как обычно у вас будет SecurityManager
, загруженный в JVM.
– Kevin Brock
31 March 2011 в 19:58
Java динамически загружает классы, поэтому ваш юниверс классов будет только теми, которые уже загружены (и еще не выгружены). Возможно, вы можете сделать что-то с помощью специального загрузчика классов, который мог бы проверять супертипы каждого загруженного класса. Я не думаю, что есть API для запроса набора загруженных классов.
Один из способов - заставить классы использовать статические инициализаторы ... Я не думаю, что они наследуются (они не будут работать, если они есть):
public class Dog extends Animal{
static
{
Animal a = new Dog();
//add a to the List
}
Он требует от вас добавьте этот код ко всем классам. Но он избегает наличия большой уродливой петли где-то, проверяя каждый класс, ищущий детей Animal.
animals.add( new c() );
вашего кода), поскольку в то время какClass.newInstance()
существует, у вас нет гарантии, что у конкретного класса есть конструктор без параметров (C # позволяет вам потребовать что в общем случае) – usr-local-ΕΨΗΕΛΩΝ 21 March 2018 в 11:53