Много написано о том, что хорошей практикой является объявление полей экземпляра класса с модификатором private, а чтение и модификацию их осуществлять с помощью public геттера и/или сеттера. Действительно, этот приём даёт уверенность, что вся логика, предусмотренная разработчиком для событий чтения/записи, будет выполнена в случае использования класса кем-либо. Однако, разработчик класса в методах по-прежнему имеет возможность читать и записывать значение поля напрямую! Чтобы избежать этого, предлагаю следующий трюк. Потребуется чуть больше кода, но теперь даже IDE не сможет подсовывать это поле в подсказках.

Для каждого "super private" поля нам потребуется интерфейс расширяющий Supplier и Consumerи объект анонимного класса, реализующего этот интерфейс, в который мы помещаем поле value. Вся логика геттера и сеттера происходит в этом классе. Сами геттер и сеттер - лишь обёртки для public доступа.

Всё понятно из примера ниже.

import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * Пример использования "super private" поля value, доступ к которому
 * возможен только через геттер и сеттер даже из методов самого класса
 */
public class GetterSetter {

    interface SupplierConsumer<T> extends Supplier<T>, Consumer<T> {}

    /**
     * объект анонимного класса имплементирущего SupplierConsumer,
     * содержащий поле value.
     * Используется в обёртке сеттера setValue(...) и геттера getValue()
     */
    private final SupplierConsumer<String> get_set_value = 
            new SupplierConsumer<>() {
        /**
         * Само поле value
         */
        String value;

        /**
         * Реализация интерфейса Supplier
         * @return - значение поля value
         */
        @Override
        public String get() {
            return value;
        }

        /**
         * Реализация интерфейса Consumer
         * @param another_value - новое значение для поля value
         */
        @Override
        public void accept(String another_value) {
            /*
            Здесь можно выполнить нужные проверки и другие действия
             */
            value = another_value;
        }
    };

    /**
     * Геттер для поля value
     * @return значение поля value
     */
    public String getValue() {
        return get_set_value.get();
    }

    /**
     * Сеттер для поля value
     * @param value - новое значение для поля value
     */
    public void setValue(String value) {
        get_set_value.accept(value);
    }

    static public void main(String[] args) {
        GetterSetter gs = new GetterSetter();

        System.out.println(gs.getValue());

        gs.setValue("Здравствуй, мир!");

        System.out.println(gs.getValue());
    }

}

Запуск класса выводит, как и ожидалось:

"java.exe" GetterSetter
null
Здравствуй, мир!