Как ограничить доступ к методам классов библиотеки для проекта?

404
03 февраля 2017, 04:15

Есть библиотека, в ней, к примеру, есть такой класс:

public class SimpleObject {
    private object;
    public void setObject(Object object) { ... }
    public Object getObject() { ... }
}

Рядом, в соседнем пакете, находится класс ObjectHandler, который принимает этот объект и, на основании результата метода .getObject(), что-то делает.

Нужно сделать так, чтобы пользователь, получив или создав объект SimpleObject, не мог использовать метод .getObject() (чтобы метод для пользователя был что-то вроде private), а класс ObjectHandler - мог и видел его.

Как это сделать?

Это нужно для того, чтобы не показывать пользователю лишние методы (и ему удобнее, и мне безопаснее). Сейчас для достижения этой цели приходится кидать объект и его обработчик в один пакет (что выглядит немного непонятно), а метод get делать доступным в пределах пакета.

Answer 1

В Java нельзя "где-то сбоку" от protected или public (равно как и в начале файла) указать пакеты, в которых метод будет доступен. В документации говорится только при каких модификаторах есть доступ в рамках пакета, а при каких - "во всём мире".
Также нет такого понятия как "подпакет" ("sub-package"). По этому поводу на enSO есть хороший ответ.

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

  1. Оставить SimpleObject и ObjectHandler в одном пакете, если это оправданно или другие варианты не подходят.
  2. Пересмотреть архитектуру классов. Например, возможно, что вместо ObjectHandler можно использовать суперкласс для SimpleObject, содержащий необходимый функционал.

Допустим, класс SimpleObject выглядит так:

package test2;
public class SimpleObject
{
    private Object object;
    public void setObject(Object object) { this.object = object; }
    protected Object getObject() { return object; }
}

"Костыльные" решения:

  1. В пакете, в котором находится 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());
    
  2. "Пуститься во все тяжкие" и получать доступ к методу через рефлексию:

    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) { }
    
Answer 2

От "глупостей" "пользователей" защититься нельзя. Если Ваш 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;
    }
}
READ ALSO
wsimport не парсит wsdl файл с 2 any свойствами в sequence

wsimport не парсит wsdl файл с 2 any свойствами в sequence

Существует wsdl файл из которого я пытаюсь сгенерировать java классы при помощи утилиты wsimportГенерация завершается ошибкой:

434
Меняется состояние visibility у select bootstrap

Меняется состояние visibility у select bootstrap

Есть такое модальное окно

343
Размещение ромбов на странице

Размещение ромбов на странице

Здравствуйте ! Нам нужно разместить ромбы на главной странице сайта, как на картинкеКак это лучше сделать ? Попробовали несколько способов,...

356