Есть библиотека, в ней, к примеру, есть такой класс:
public class SimpleObject {
private object;
public void setObject(Object object) { ... }
public Object getObject() { ... }
}
Рядом, в соседнем пакете, находится класс ObjectHandler, который принимает этот объект и, на основании результата метода .getObject(), что-то делает.
Нужно сделать так, чтобы пользователь, получив или создав объект SimpleObject, не мог использовать метод .getObject() (чтобы метод для пользователя был что-то вроде private), а класс ObjectHandler - мог и видел его.
Как это сделать?
Это нужно для того, чтобы не показывать пользователю лишние методы (и ему удобнее, и мне безопаснее). Сейчас для достижения этой цели приходится кидать объект и его обработчик в один пакет (что выглядит немного непонятно), а метод get делать доступным в пределах пакета.
В Java нельзя "где-то сбоку" от protected или public (равно как и в начале файла) указать пакеты, в которых метод будет доступен. В документации говорится только при каких модификаторах есть доступ в рамках пакета, а при каких - "во всём мире".
Также нет такого понятия как "подпакет" ("sub-package"). По этому поводу на enSO есть хороший ответ.
Получается, что с помощью модификаторов доступа желаемого результата не добиться. В таком случае остаются такие варианты:
SimpleObject и ObjectHandler в одном пакете, если это оправданно или другие варианты не подходят.ObjectHandler можно использовать суперкласс для SimpleObject, содержащий необходимый функционал.Допустим, класс SimpleObject выглядит так:
package test2;
public class SimpleObject
{
private Object object;
public void setObject(Object object) { this.object = object; }
protected Object getObject() { return object; }
}
"Костыльные" решения:
В пакете, в котором находится ObjectHandler, создать класс MySimpleObject extends SimpleObject и переопределить в нём нужные методы:
package test3;
import test2.SimpleObject;
public class MySimpleObject extends SimpleObject
{
protected Object getObject() { return super.getObject(); }
}
После чего использовать MySimpleObject вместо SimpleObject:
MySimpleObject mso = new MySimpleObject();
mso.setObject("Str");
System.out.println(mso.getObject());
"Пуститься во все тяжкие" и получать доступ к методу через рефлексию:
SimpleObject so = new SimpleObject();
so.setObject("Str");
try
{
Method method = so.getClass().getDeclaredMethod("getObject");
method.setAccessible(true);
System.out.println(method.invoke(so));
}
catch (Exception e) { }
От "глупостей" "пользователей" защититься нельзя.
Если Ваш SimpleObject относится к уровню сущностей (@Entity), то все его getters & setters должны быть public. Это правильно и логично. И нет ничего плохого в том, что кто-то будет создавать и полноценно использовать Вашу сущность SimpleObject.
Но, если SimpleObject — это некий API-метод, то действительно нужно .getObject() защитить от "пользователя", то есть контролировать защиту от получения некорректного значения или вызова .getObject() в неподходящий момент по логике вашего проекта.
В таком случае, я рекомендую оставить модификатор видимости public getObject(), но защититься от неправильного использования через Exception.
Создайте свой Exception или используйте существующий. Например:
public class MyLogicalException extends Exception {
public MyLogicalException(String message) {
super(message);
}
}
И объявите, что метод getObject() может выбрасывать исключение MyLogicalException при определенных обстоятельствах. Например:
public Object getObject() throws MyLogicalException {
if (object == null) {
throw new MyLogicalException("object не может быть пустым!");
} else {
return object;
}
}
Продвижение своими сайтами как стратегия роста и независимости