Ответ 1
Вы не можете. В Java нет понятия подпакета, поэтому odp.proj и odp.proj.test являются полностью отдельными пакетами.
У меня есть два пакета в моем проекте: odp.proj
и odp.proj.test
. Существуют определенные методы, которые я хочу видеть только для классов в этих двух пакетах. Как я могу это сделать?
РЕДАКТИРОВАТЬ: Если в Java нет концепции субпакета, существует ли какой-либо способ этого? У меня есть определенные методы, которые я хочу получить только для тестировщиков и других членов этого пакета. Должен ли я просто выбросить все в один пакет? Использовать обширное отражение?
Вы не можете. В Java нет понятия подпакета, поэтому odp.proj и odp.proj.test являются полностью отдельными пакетами.
Имена ваших пакетов подсказывают, что приложение предназначено для модульного тестирования. Типичный шаблон используется для размещения классов, которые вы хотите протестировать, и кода unit test в том же пакете (в вашем случае odp.proj
), но в разных источниках. Поэтому вы ставите свои классы в src/odp/proj
и ваш тестовый код в test/odp/proj
.
У Java есть модификатор доступа "пакет", который является модификатором доступа по умолчанию, когда ни один не указан (т.е. вы не указываете public, private или protected). С модификатором доступа "пакет" доступ к методам будет иметь только классы в odp.proj
. Но имейте в виду, что в Java нельзя использовать модификаторы доступа для обеспечения соблюдения правил доступа, потому что с отражением возможен любой доступ. Модификаторы доступа просто наводящие на размышления (если только не существует ограничивающий диспетчер безопасности).
Это не имеет особого отношения между odp.proj
и odp.proj.test
- они просто называются как связанные.
Если пакет odp.proj.test просто предоставляет тесты, вы можете использовать одно и то же имя пакета (odp.proj
). IDE, такие как Eclipse и Netbeans, будут создавать отдельные папки (src/main/java/odp/proj
и src/test/java/odp/proj
) с тем же именем пакета, но с семантикой JUnit.
Обратите внимание, что эти IDE будут генерировать тесты для методов в odp.proj
и создать соответствующую папку для методов тестирования, которых она не существует.
Когда я делаю это в IntelliJ, мое исходное дерево выглядит так:
src // source root
- odp
- proj // .java source here
- test // test root
- odp
- proj // JUnit or TestNG source here
EDIT: если нет понятия subpackage в Java, есть ли способ вокруг этого? У меня есть определенные методы что я хочу быть доступным только для тестеров и других членов этого пакет.
Вероятно, это немного зависит от ваших мотивов, чтобы не отображать их, но если единственная причина в том, что вы не хотите загрязнять публичный интерфейс вещами, предназначенными только для тестирования (или какой-либо другой внутренней вещи), я бы поставил методы в отдельном публичном интерфейсе, и потребители "скрытых" методов используют этот интерфейс. Это не остановит других от использования интерфейса, но я не вижу причин, почему вы должны.
Для модульных тестов, и если это возможно без перезаписи партии, следуйте рекомендациям по использованию того же пакета.
Как объясняли другие, в Java нет такого понятия, как "подпакет": все пакеты изолированы и ничего не наследуют от своих родителей.
Простой способ получить доступ к защищенным членам класса из другого пакета - расширить класс и переопределить члены.
Например, чтобы получить доступ к ClassInA
в пакете ab
:
package a;
public class ClassInA{
private final String data;
public ClassInA(String data){ this.data = data; }
public String getData(){ return data; }
protected byte[] getDataAsBytes(){ return data.getBytes(); }
protected char[] getDataAsChars(){ return data.toCharArray(); }
}
сделайте класс в этом пакете, который переопределяет методы, которые вам нужны в ClassInA
:
package a.b;
import a.ClassInA;
public class ClassInAInB extends ClassInA{
ClassInAInB(String data){ super(data); }
@Override
protected byte[] getDataAsBytes(){ return super.getDataAsBytes(); }
}
Это позволяет вам использовать переопределяющий класс вместо класса в другом пакете:
package a.b;
import java.util.Arrays;
import a.ClassInA;
public class Driver{
public static void main(String[] args){
ClassInA classInA = new ClassInA("string");
System.out.println(classInA.getData());
// Will fail: getDataAsBytes() has protected access in a.ClassInA
System.out.println(Arrays.toString(classInA.getDataAsBytes()));
ClassInAInB classInAInB = new ClassInAInB("string");
System.out.println(classInAInB.getData());
// Works: getDataAsBytes() is now accessible
System.out.println(Arrays.toString(classInAInB.getDataAsBytes()));
}
}
Обратите внимание, что это работает только для защищенных членов, которые видимы для расширяющих классов (наследование), а не для закрытых для пакета членов, которые видимы только для подчиненных/расширяющих классов в одном и том же пакете. Надеюсь, это кому-нибудь поможет!
Не помещая модификатор доступа перед этим методом, вы говорите, что он закрыт.
Посмотрите на следующий пример.
package odp.proj;
public class A
{
void launchA() { }
}
package odp.proj.test;
public class B
{
void launchB() { }
}
public class Test
{
public void test()
{
A a = new A();
a.launchA() // cannot call launchA because it is not visible
}
}
С классом PackageVisibleHelper и сохраняйте его закрытым до того, как заморожен пакет PackageVisibleHelperFactory, мы можем вызвать метод launchA (by PackageVisibleHelper) в любом месте:)
package odp.proj;
public class A
{
void launchA() { }
}
public class PackageVisibleHelper {
private final PackageVisibleHelperFactory factory;
public PackageVisibleHelper(PackageVisibleHelperFactory factory) {
super();
this.factory = factory;
}
public void launchA(A a) {
if (factory == PackageVisibleHelperFactory.INSTNACNE && !factory.isSampleHelper(this)) {
throw new IllegalAccessError("wrong PackageVisibleHelper ");
}
a.launchA();
}
}
public class PackageVisibleHelperFactory {
public static final PackageVisibleHelperFactory INSTNACNE = new PackageVisibleHelperFactory();
private static final PackageVisibleHelper HELPER = new PackageVisibleHelper(INSTNACNE);
private PackageVisibleHelperFactory() {
super();
}
private boolean frozened;
public PackageVisibleHelper getHelperBeforeFrozen() {
if (frozened) {
throw new IllegalAccessError("please invoke before frozen!");
}
return HELPER;
}
public void frozen() {
frozened = true;
}
public boolean isSampleHelper(PackageVisibleHelper helper) {
return HELPER.equals(helper);
}
}
package odp.proj.test;
import odp.proj.A;
import odp.proj.PackageVisibleHelper;
import odp.proj.PackageVisibleHelperFactory;
public class Test {
public static void main(String[] args) {
final PackageVisibleHelper helper = PackageVisibleHelperFactory.INSTNACNE.getHelperBeforeFrozen();
PackageVisibleHelperFactory.INSTNACNE.frozen();
A a = new A();
helper.launchA(a);
// illegal access
new PackageVisibleHelper(PackageVisibleHelperFactory.INSTNACNE).launchA(a);
}
}