О технике безопасного конструктора в Java - PullRequest
1 голос
/ 27 марта 2019

Я прочитал статью IBM о методах безопасного конструктора в Java.Основная идея статьи в том, что вы не должны явно или неявно выставлять эту ссылку в конструкторе.Но ничего не сказано о лямбдах.Насколько я знаю, лямбды захватывают локальный контекст (только конечные или фактически конечные переменные), поэтому, если вы ссылаетесь на какой-либо метод класса внутри лямбда-тела, тогда эта ссылка доступна?

У меня следующий вопрос: это хорошая практика для разработки классов, которые принимают Runnable, Function, Predicate в качестве аргумента в конструкторе?Если вы передаете простую лямбду (не ссылается на методы класса) такому конструктору, то, как я понимаю, в этом нет ничего плохого, но с другой стороны, он обеспечивает способ передачи анонимного внутреннего класса в качестве аргумента в результате this ссылка может быть раскрыта.

public class ClassA {
    private ClassB classB;

    public ClassA() {
        // fine
        classB = new ClassB(integer -> integer % 2 == 0);
        // oops
        classB = new ClassB(new Function<Integer, Boolean>() {
            @Override
            public Boolean apply(Integer integer) {
                return integer % 2 == 0;
            }
        });
    }
}

public class ClassB {
    private final Function<Integer, Boolean> function;

    public ClassB(Function<Integer, Boolean> function) {
        this.function = function;
    }
}

Ответы [ 2 ]

1 голос
/ 27 марта 2019

это хорошая практика для разработки классов, которые принимают Runnable, Function, Predicate в качестве аргумента в конструкторе?

Да, как любой другой объект.Пока вы не выставляете ссылку this, вы можете передавать конструктору все, что хотите.

В нашем примере ClassA не работает, а ClassB поточно-ориентированный.Вы неявно позволяете ссылочной this экранировать от ClassA (родительский объект), создавая внутренний анонимный класс в его конструкторе и передавая его другому объекту.Но класс (ClassB) с параметром Function создан безопасно.

0 голосов
/ 27 марта 2019

это хорошая практика для разработки классов, которые принимают Runnable

Если вы посмотрите на java.lang.Thread, вы можете найти такой конструктор

public Thread(Runnable target) {}

Ответ yes, даже Oracle делает это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...