Как получить весь подкласс из базового класса в JAVA [duplicate]

Да. Вы можете определенно посмотреть местоположение в фоновом режиме, если ваш мобильный браузер поддерживает Geolocation API.

Вы можете использовать функцию watchPosition().

blockquote>

watchPosition ( ) Code Snippet

var watchID = navigator.geolocation.watchPosition(function(position) {
  do_something(position.coords.latitude, position.coords.longitude);
});

Если данные позиции изменяются (либо путем перемещения устройства, либо при получении более точной геоинформации), вы можете настроить функцию обратного вызова, вызываемую с этой обновленной информацией о местоположении , Это делается с помощью функции watchPosition(), которая имеет те же входные параметры, что и getCurrentPosition(). Функция обратного вызова вызывается несколько раз, позволяя браузеру либо обновлять ваше местоположение при перемещении, либо предоставлять более точное местоположение.

blockquote>

getCurrentPosition () Фрагмент кода

navigator.geolocation.getCurrentPosition(function(position) {
  do_something(position.coords.latitude, position.coords.longitude);
});

Чтобы получить дополнительную информацию, обратитесь к Mozilla / Geolocation / WatchCurrentPosition

Надеюсь, что это поможет!

174
задан guerda 2 October 2009 в 14:15
поделиться

15 ответов

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

Eclipse может только рассказать вам о супер и подклассах в том, что кажется «эффективным» количеством времени, потому что он уже имеет все данные типа, загруженные в тот момент, когда вы нажимаете кнопку «Отображать в иерархии типов» (поскольку она постоянно компилирует ваши классы, знает обо всем на пути к классам и т. д.).

67
ответ дан matt b 17 August 2018 в 19:35
поделиться
  • 1
    Теперь есть простая библиотека, называемая org.reflections , которая помогает в этом и других общих задачах отражения. С помощью этой библиотеки вы можете просто вызвать ссылку reflections.getSubTypesOf(aClazz)) – Enwired 20 February 2015 в 02:29
  • 2
    @matt b - если он должен сканировать все классы, означает ли это, что есть ухудшение производительности, когда у вас много классов в вашем проекте, хотя только некоторые из них подклассифицируют ваш класс? – LeTex 24 September 2015 в 15:00
  • 3
    В точку. Он просто касается всех классов. Вы можете определить свой собственный сканер, который вы можете ускорить, например, исключая определенные пакеты, которые, как вы знаете, не будут расширены или просто откроете файл класса и проверьте наличие имени класса в разделе «константа» класса, не позволяя сканеру отражения читать много больше информации о классах, которые даже не содержат требуемую ссылку на ваш (прямой) суперкласс. Косвенно вам нужно сканировать дальше. Так что это лучшее, что есть на данный момент. – Martin Kersten 5 January 2016 в 14:52
  • 4
    Ответ от fforw работал на меня и должен быть помечен как правильный ответ. Ясно, что это возможно при сканировании классов. – Farrukh Najmi 23 March 2017 в 13:50

Следует также отметить, что это, конечно же, найдет только те подклассы, которые существуют в вашем текущем пути к классам. Предположительно, это нормально для того, что вы сейчас просматриваете, и, скорее всего, вы это рассмотрели, но если в какой-то момент вы выпустили класс не final в дикий (для разных уровней «дикий»), то это вполне возможно, что кто-то еще написал свой собственный подкласс, о котором вы не узнаете.

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

3
ответ дан Andrzej Doyle 17 August 2018 в 19:35
поделиться

Я знаю, что на несколько лет опаздываю на эту вечеринку, но я столкнулся с этим вопросом, пытаясь решить ту же проблему. Вы можете использовать внутренний поиск Eclipse программно, если вы пишете плагин Eclipse (и, таким образом, используете их кеширование и т. Д.), Чтобы найти классы, которые реализуют интерфейс. Вот мой (очень грубый) первый снимок:

  protected void listImplementingClasses( String iface ) throws CoreException
  {
    final IJavaProject project = <get your project here>;
    try
    {
      final IType ifaceType = project.findType( iface );
      final SearchPattern ifacePattern = SearchPattern.createPattern( ifaceType, IJavaSearchConstants.IMPLEMENTORS );
      final IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
      final SearchEngine searchEngine = new SearchEngine();
      final LinkedList<SearchMatch> results = new LinkedList<SearchMatch>();
      searchEngine.search( ifacePattern, 
      new SearchParticipant[]{ SearchEngine.getDefaultSearchParticipant() }, scope, new SearchRequestor() {

        @Override
        public void acceptSearchMatch( SearchMatch match ) throws CoreException
        {
          results.add( match );
        }

      }, new IProgressMonitor() {

        @Override
        public void beginTask( String name, int totalWork )
        {
        }

        @Override
        public void done()
        {
          System.out.println( results );
        }

        @Override
        public void internalWorked( double work )
        {
        }

        @Override
        public boolean isCanceled()
        {
          return false;
        }

        @Override
        public void setCanceled( boolean value )
        {
        }

        @Override
        public void setTaskName( String name )
        {
        }

        @Override
        public void subTask( String name )
        {
        }

        @Override
        public void worked( int work )
        {
        }

      });

    } catch( JavaModelException e )
    {
      e.printStackTrace();
    }
  }

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

7
ответ дан Curtis 17 August 2018 в 19:35
поделиться

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

final static File rootFolder = new File(SuperClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());
private static ArrayList<String> files = new ArrayList<String>();
listFilesForFolder(rootFolder); 

@Test(timeout = 1000)
public void testNumberOfSubclasses(){
    ArrayList<String> listSubclasses = new ArrayList<>(files);
    listSubclasses.removeIf(s -> !s.contains("Superclass.class"));
    for(String subclass : listSubclasses){
        System.out.println(subclass);
    }
    assertTrue("You did not create a new subclass!", listSubclasses.size() >1);     
}

public static void listFilesForFolder(final File folder) {
    for (final File fileEntry : folder.listFiles()) {
        if (fileEntry.isDirectory()) {
            listFilesForFolder(fileEntry);
        } else {
            files.add(fileEntry.getName().toString());
        }
    }
}
0
ответ дан Cutetare 17 August 2018 в 19:35
поделиться

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

Вы можете запустить его из командной строки например:

javadoc -d build -doclet com.example.ObjectListDoclet -sourcepath java/src -subpackages com.example

или запустить его из муравья вроде этого:

<javadoc sourcepath="${src}" packagenames="*" >
  <doclet name="com.example.ObjectListDoclet" path="${build}"/>
</javadoc>

Вот базовый код:

public final class ObjectListDoclet {
    public static final String TOP_CLASS_NAME =  "com.example.MyClass";        

    /** Doclet entry point. */
    public static boolean start(RootDoc root) throws Exception {
        try {
            ClassDoc topClassDoc = root.classNamed(TOP_CLASS_NAME);
            for (ClassDoc classDoc : root.classes()) {
                if (classDoc.subclassOf(topClassDoc)) {
                    System.out.println(classDoc);
                }
            }
            return true;
        }
        catch (Exception ex) {
            ex.printStackTrace();
            return false;
        }
    }
}

Для простоты I 'удалил синтаксический анализ аргумента командной строки, и я пишу в System.out вместо файла.

8
ответ дан David Leppik 17 August 2018 в 19:35
поделиться

Сканирование для классов непросто с чистой Java.

Spring framework предлагает класс под названием ClassPathScanningCandidateComponentProvider , который может делать то, что вам нужно. В следующем примере будут найдены все подклассы MyClass в пакете org.example.package

ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AssignableTypeFilter(MyClass.class));

// scan in org.example.package
Set<BeanDefinition> components = provider.findCandidateComponents("org/example/package");
for (BeanDefinition component : components)
{
    Class cls = Class.forName(component.getBeanClassName());
    // use class cls found
}

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

106
ответ дан fforw 17 August 2018 в 19:35
поделиться
  • 1
    False должен передаваться как параметр при создании ClassPathScanningCandidateComponentProvider для отключения фильтров по умолчанию. Фильтры по умолчанию будут соответствовать другим типам классов, например. что-то аннотированное с @Component. Мы хотим, чтобы здесь был активен AssignableTypeFilter. – MCDS 31 January 2013 в 02:07
  • 2
  • 3
    Вы правы, ложь предпочтительнее. Отредактировал его. – fforw 12 November 2017 в 17:15

Я использую отражение lib, которое сканирует ваш путь к классам для всех подклассов: https://github.com/ronmamo/reflections

Вот как это было бы сделано:

Reflections reflections = new Reflections("my.project");
Set<Class<? extends SomeType>> subTypes = reflections.getSubTypesOf(SomeType.class);
2
ответ дан futchas 17 August 2018 в 19:35
поделиться

Попробуйте ClassGraph . (Отказ от ответственности, я автор). ClassGraph поддерживает сканирование для подклассов данного класса либо во время выполнения, либо во время сборки, но и многое другое. ClassGraph может создавать абстрактное представление всего графа классов (все классы, аннотации, методы, параметры метода и поля) в памяти, для всех классов в пути к классам или для классов в белых списках, и вы можете запросить этот графа классов, однако вы хотите. ClassGraph поддерживает больше механизмов спецификации классов и загрузчиков классов , чем любой другой сканер, а также легко работает с новой системой модулей JPMS, поэтому, если вы основываете свой код на ClassGraph, ваш код будет максимально переносимым. См. здесь API.

3
ответ дан Luke Hutchison 17 August 2018 в 19:35
поделиться

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

. Короче говоря, он позволяет разработчикам явно объявлять, что класс подклассы другого класса (или реализует некоторый интерфейс), перечислив его в файле в каталоге META-INF/services файла JAR / WAR. Затем он может быть обнаружен с использованием класса java.util.ServiceLoader , который при заданном объекте Class будет генерировать экземпляры всех объявленных подклассов этого класса (или, если Class представляет собой интерфейс , все классы, реализующие этот интерфейс).

Основное преимущество этого подхода состоит в том, что нет необходимости вручную сканировать весь путь к классам для подклассов - вся логика обнаружения содержится в классе ServiceLoader и он загружает классы, явно объявленные в каталоге META-INF/services (не каждый класс в пути к классам).

Однако есть некоторые недостатки:

  • Он выиграл 't найти все подклассы, только те, которые явно объявлены. Таким образом, если вам действительно нужно найти все подклассы, этот подход может быть недостаточным.
  • Он требует, чтобы разработчик явно объявлял класс в каталоге META-INF/services. Это дополнительное бремя для разработчика и может быть подвержено ошибкам.
  • ServiceLoader.iterator() генерирует экземпляры подкласса, а не их Class объектов. Это вызывает две проблемы: вы не можете сказать, как строятся подклассы - конструктор no-arg используется для создания экземпляров. Таким образом, подклассы должны иметь конструктор по умолчанию или должны быть объяснены конструктором no-arg.

Очевидно, что Java 9 будет решать некоторые из этих недостатков (в частности, те, которые касаются создания подклассов).

Пример

Предположим, вам интересно найти классы, реализующие интерфейс com.example.Example:

package com.example;

public interface Example {
    public String getStr();
}

Класс com.example.ExampleImpl реализует этот интерфейс:

package com.example;

public class ExampleImpl implements Example {
    public String getStr() {
        return "ExampleImpl's string.";
    }
}

Вы объявили бы класс ExampleImpl представляет собой реализацию Example путем создания файла META-INF/services/com.example.Example, содержащего текст com.example.ExampleImpl.

Затем вы можете получить экземпляр каждой реализации Example (включая экземпляр ExampleImpl) следующим образом:

ServiceLoader<Example> loader = ServiceLoader.load(Example.class)
for (Example example : loader) {
    System.out.println(example.getStr());
}

// Prints "ExampleImpl's string.", plus whatever is returned
// by other declared implementations of com.example.Example.
2
ответ дан Mac 17 August 2018 в 19:35
поделиться

Это невозможно сделать, используя только встроенный API Java Reflections.

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

Отражения

Анализ метаданных во время выполнения Java в духе Scannotations

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

Используя Reflections, вы можете запросить свои метаданные для:

  • получить все подтипы некоторого типа
  • получить все типы, аннотированные с некоторой аннотацией
  • get все типы, аннотированные некоторой аннотацией, включая параметры аннотации, соответствующие
  • , получают все методы, аннотированные некоторыми

(отказ от ответственности: я не использовал его, но описание проекта, по-видимому, точно соответствует вашим потребностям.)

42
ответ дан Mark Renouf 17 August 2018 в 19:35
поделиться
  • 1
    Интересно. У проекта, похоже, есть некоторые зависимости, которые, по-видимому, не упоминаются в их документации. А именно (те, которые я нашел до сих пор): javassist, log4J, XStream – Avrom 29 January 2009 в 17:51
  • 2
    – KarlsFriend 8 May 2012 в 13:16
  • 3
    Невозможно ли использовать только встроенный API Java Reflections или просто неудобно это делать? – Flow 10 March 2015 в 08:46
  • 4
    Будьте осторожны, когда вы собираетесь использовать Reflections, а затем разверните приложение WAR WARFish! В библиотеке Guava существует конфликт, и сбой при ошибке с ошибкой Ошибка развертывания CDI: WELD-001408 - более подробную информацию см. В GLASSFISH-20579 . FastClasspathScanner является решением в этом случае. – lu_ko 19 May 2016 в 14:04
  • 5
    Я просто пробую этот проект, и он работает. Я просто использую его для улучшения шаблона проектирования стратегии и получения всей стратегии конкретного класса (подкласса). Я расскажу о демо-последнем. – Xin Meng 2 February 2017 в 18:01

Имея в виду ограничения, упомянутые в других ответах, вы также можете использовать openpojo's PojoClassFactory (, доступный на Maven ) следующим образом:

for(PojoClass pojoClass : PojoClassFactory.enumerateClassesByExtendingType(packageRoot, Superclass.class, null)) {
    System.out.println(pojoClass.getClazz());
}

Где packageRoot - это корневая строка пакетов, которые вы хотите искать (например, "com.mycompany" или даже просто "com"), а Superclass - ваш супертип (это также работает и с интерфейсами) .

5
ответ дан mikołak 17 August 2018 в 19:35
поделиться
  • 1
    Безусловно, самое быстрое и изящное решение из предложенных. – KidCrippler 29 November 2016 в 17:51

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

3
ответ дан Peter Mortensen 17 August 2018 в 19:35
поделиться

Добавьте их в статическую карту внутри (this.getClass (). getName ()) конструктор родительских классов (или создайте по умолчанию), но это будет обновляться во время выполнения. Если ленивая инициализация - это вариант, вы можете попробовать этот подход.

1
ответ дан Ravindranath Akila 17 August 2018 в 19:35
поделиться

Не забывайте, что сгенерированный Javadoc для класса будет включать список известных подклассов (и для интерфейсов, известных классов реализации).

11
ответ дан Rob 17 August 2018 в 19:35
поделиться
  • 1
    это абсолютно неверно, суперкласс не должен зависеть от их подклассов, даже в javadoc или комментариях. – hunter 28 March 2017 в 06:15

Я просто написал простое демо, чтобы использовать org.reflections.Reflections для получения подклассов абстрактного класса:

https://github.com/xmeng1/ReflectionsDemo

3
ответ дан Xin Meng 17 August 2018 в 19:35
поделиться
  • 1
    было бы более продуктивно, если бы вы разместили здесь образец кода, а не ссылку с большим количеством классов, чтобы копать. – JesseBoyd 13 December 2017 в 01:19
  • 2
    Хорошо, я сделаю краткое резюме демо-кода позже. – Xin Meng 13 December 2017 в 12:46
Другие вопросы по тегам:

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