2016-12-14 10 views
2

У меня есть класс, как это:Дополнительный тип поля и кода, безопасен ли он?

class Environment { 

    somelib.SomeType someOptionalDep = null; 

    public void doSomething() { 
     boolean found = false; 
     try { 
      Class.forName("somelib.SomeType"); 
      found = true; 
     } catch (ClassNotFoundException e) { 
     } 
     if (found) { 
      someOptionalDep = new somelib.SomeType(); 
      // ... 
     } 
    } 

} 

somelib является дополнительным пакетом: во время компиляции существует, но исключен из базовой баночки. Фактически, этот код работает без зависимости (Oracle Java HotSpot 1.8.0_111 на Debian 8), но действительно ли это безопасно?

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

EDIT:

Из документации Oracle о NoClassDefFoundError:

Брошенный, если виртуальная машина Java или ClassLoader экземпляр пытается загрузить в определении класса (как часть нормального метода вызов или как часть создания нового экземпляра с использованием выражения new), и определение класса не может быть найдено.

Определение класса поиска было выполнено, когда выполняемый в данный момент класс был скомпилирован, но определение больше не может быть найдено.

К сожалению, в нем явно не сказано ничего о декларации или загруженном, но не выполненном коде.

+2

В чем смысл? Почему бы просто не поймать 'NoClassDefFoundError'? – shmosel

+0

Является ли объявление поля безопасным с потенциально несуществующим типом? –

ответ

1

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

class Environment { 
    SomeInterface someOptionalDep = null; 
    public void doSomething() { 
     try { 
     Class c = Class.forName("somelib.SomeType");   
     someOptionalDep = c.newInstance(); 
     } catch (ClassNotFoundException, InstantiationException, IllegalAccessException e) { 
     } 
    } 
} 
+0

OP сказал, что это действительно сработало для него. – shmosel

+0

Я сомневаюсь, что он может работать, если класс среды не был загружен в первую очередь. –

+0

@Roberto Attias: Как говорит @shmosel, я пробовал это с Oracle Java HotSpot 1.8.0_111 на Debian 8 и работал. «someOptionalDep» хранит экземпляр класса сторонних библиотек, который вообще не имеет портативного интерфейса (возможно, «Object someOptionalDep»). –

1

Я считаю, что ваш основной вопрос говорится в комментарии

Является ли объявление поля безопасным с потенциально несуществующим типом?

и безопасно, кажется, означает «не вызывает NoClassDefFoundError».

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


Технически, ответ да.

JVM имеет тенденцию делать вещи как можно более лениво - особенно при загрузке класса. Когда класс загружен, JVM будет загружать только суперкласс и суперинтерфейсы, но не другие типы, используемые в коде.

Кроме того, даже чтение и запись поля, которое имеет несуществующий тип, не сам провоцирует загрузку класса (и NoClassDefFoundError). Это возможно потому, что

  • если вы читаете поле, то загрузка классов может быть отложена до тех пор, пока на самом деле использовать его
  • если вы пишете ненулевое значение, то вы уже загрузили тип в создать экземпляр
  • если вы пишете нуль в поле, то тип не имеет значения (так как нуль может быть присвоено любое значение)

Кстати, то же самое справедливо и для параметров и возвращаемых значений методы.

+0

«Необязательные зависимости лучше обрабатывать с помощью своего рода шлюза, который отделяет вашу бизнес-логику от зависимости». - Хорошая точка в целом, но ИМО в этом конкретном случае является одним из исключений. Мой пакет представляет собой легкую абстракцию над некоторыми зависимыми от платформы ресурсами, в ней не может быть реализована логика занятости. –

+0

@ DávidHorváth Из этого и вашего другого комментария кажется, что «Среда» уже может быть использована аналогично тому, что я пытался описать, то есть безопасно инкапсулирует доступ к «SomeType», предоставляет его бизнес-логике и ничего не делает. Если да, все в порядке. В противном случае это тоже нормально :), так как это ваш преднамеренный выбор, и вы единственный, кто может решить. –

 Смежные вопросы

  • Нет связанных вопросов^_^