Re[3]: Boolean и его замыкания
От: vsb Казахстан  
Дата: 03.05.20 09:34
Оценка: +2
Здравствуйте, Pavel Dvorkin, Вы писали:

GIV>>Второе.


PD>Гм.


PD>
PD>public final class Boolean implements java.io.Serializable, Comparable<Boolean>
PD>//...
PD>    private final boolean value;
PD>//...
PD>    public Boolean(boolean value) {
PD>        this.value = value;
PD>    }
PD>    public Boolean(String s) {
PD>        this(parseBoolean(s));
PD>    }


PD>


PD>Вполне обычный боксинг.


PD>Boolean b = false;


PD>===


PD>Boolean b = new Boolean(false);


Это не так. Это эквивалентно Boolean b = Boolean.valueOf(false);
Re[5]: Boolean и его замыкания
От: vsb Казахстан  
Дата: 03.05.20 11:21
Оценка: +2
Здравствуйте, Pavel Dvorkin, Вы писали:

vsb>>Это не так. Это эквивалентно Boolean b = Boolean.valueOf(false);


PD>М-да. Сэкономить решили. Ну, в общем, правильно. Я просто полагал, что делается по аналогии с другими типами — оболочками.


С другими типами тоже valueOf() (: Причём по умолчанию тот же Integer от -128 до 127 тоже кешируется. Поэтому всякие приколы возникают вида

        Integer n1 = 100;
        Integer n2 = 100;
        System.out.println(n1 == n2); // true
        n1 = 1000;
        n2 = 1000;
        System.out.println(n1 == n2); // false
Re[3]: Boolean и его замыкания
От: GarryIV  
Дата: 03.05.20 07:11
Оценка: +1
Здравствуйте, Pavel Dvorkin, Вы писали:

PD>Вполне обычный боксинг.


Есть боксинг а есть аутобоксинг, немного разные вещи
WBR, Igor Evgrafov
Re[4]: Boolean и его замыкания
От: StanislavK Великобритания  
Дата: 05.05.20 15:03
Оценка: +1
Здравствуйте, GarryIV, Вы писали:

SK>>Не, точно не прописано. Это просто оптимизация.


GIV>https://docs.oracle.com/javase/specs/jls/se14/html/jls-5.html#jls-5.1.7

GIV>

GIV>If the value p being boxed is the result of evaluating a constant expression (§15.29) of type boolean, byte, char, short, int, or long, and the result is true, false, a character in the range '\u0000' to '\u007f' inclusive, or an integer in the range -128 to 127 inclusive, then let a and b be the results of any two boxing conversions of p. It is always the case that a == b


И правда, наврал я. Зря они так, я бы это максимум рекомендацией сделал, как бы детали реализации.
Boolean и его замыкания
От: f95.2  
Дата: 02.05.20 19:00
Оценка:
Добрый вечер.
У меня два разных, но взаимосвязанных вопроса, поэтому спрошу их в одной теме.

1. Пусть есть код
Boolean b = false;


Что здесь происходит? Создается новый объект Boolean, и ему присваивается значение false (которое он сохраняет где-то внутри),
или просто ссылке b присваивается значение Boolean.FALSE?

Откуда следует ответ на предыдущий вопрос? Он прописан в стандарте (я его не читал еще, разбираюсь же только), или зависит от реализации?


2. Пусть есть код

Boolean flag = false;
Consumer<Object> handler = (Object) -> {
    synchronized (flag) {
        flag = true;
        flag.notifyAll();
    }
};


Компилятор ругается на него: "local variables referenced from a lambda expression must be final or effectively final", причем в трех местах — на synchronized, на присваивание true и на notifyAll.
Почему?

На присваивание true вроде понятно — если flag: это ссылка на Boolean.FALSE, то получается, что мы меняем ссылку (она начинает ссылаться на Boolean.TRUE).
Но почему компилятор не дает синхронизироваться и сделать нотификацию? Ведь тут нет изменений ссылки.


P.S.
3. А как правильно из лямбды просигналить о завершении работы?
Re: Boolean и его замыкания
От: C0s Россия  
Дата: 02.05.20 19:44
Оценка:
Здравствуйте, f95.2, Вы писали:

F2>3. А как правильно из лямбды просигналить о завершении работы?


использовать CompletableFuture со всеми его навороченными возможностями (например, whenComplete)
Re: Boolean и его замыкания
От: GarryIV  
Дата: 02.05.20 19:54
Оценка:
Здравствуйте, f95.2, Вы писали:

F2>Добрый вечер.

F2>У меня два разных, но взаимосвязанных вопроса, поэтому спрошу их в одной теме.

F2>1. Пусть есть код

F2>
F2>Boolean b = false;
F2>


F2>Что здесь происходит? Создается новый объект Boolean, и ему присваивается значение false (которое он сохраняет где-то внутри),

F2>или просто ссылке b присваивается значение Boolean.FALSE?
Второе.

F2>Откуда следует ответ на предыдущий вопрос? Он прописан в стандарте (я его не читал еще, разбираюсь же только), или зависит от реализации?

Хз, должно быть прописано. Искать влом.

F2>2. Пусть есть код


F2>
F2>Boolean flag = false;
F2>Consumer<Object> handler = (Object) -> {
F2>    synchronized (flag) {
F2>        flag = true;
F2>        flag.notifyAll();
F2>    }
F2>};
F2>


F2>Компилятор ругается на него: "local variables referenced from a lambda expression must be final or effectively final", причем в трех местах — на synchronized, на присваивание true и на notifyAll.

F2>Почему?

Потому, что "local variables referenced from a lambda expression must be final or effectively final" — даже не знаю, что добавить. Так написано в JLS.

F2>На присваивание true вроде понятно — если flag: это ссылка на Boolean.FALSE, то получается, что мы меняем ссылку (она начинает ссылаться на Boolean.TRUE).

F2>Но почему компилятор не дает синхронизироваться и сделать нотификацию? Ведь тут нет изменений ссылки.

Вообще смысл на локальной переменной синхронизироваться? И никогда не синхронизируйся на глобальных объектах JVM типа Boolean.FALSE. Прикинь вас таких умных двое будет

F2>P.S.

F2>3. А как правильно из лямбды просигналить о завершении работы?

Да много как можно, вернуть из лямбды Future (CompletableFuture) например. Все эти wait/notify забудь, используй примитивы java.util.concurrent.

Ты расскажи что делаешь то.
WBR, Igor Evgrafov
Re[2]: Boolean и его замыкания
От: f95.2  
Дата: 02.05.20 20:05
Оценка:
Здравствуйте, GarryIV, Вы писали:

GIV>Потому, что "local variables referenced from a lambda expression must be final or effectively final" — даже не знаю, что добавить. Так написано в JLS.

Ну так и почему ошибка-то? СИнхронизация разве изменяет ссылку и заставляет ее указывать на другой объект?
Нотификация разве меняет ссылку и заставляет ее указывать на другой объект?
Или под "local variables" понимается не ссылка, а объект, на который она указывает?

GIV>Вообще смысл на локальной переменной синхронизироваться? И никогда не синхронизируйся на глобальных объектах JVM типа Boolean.FALSE. Прикинь вас таких умных двое будет

Ну вот я не был еще уверен, что это глобальный объект.

GIV>Все эти wait/notify забудь, используй примитивы java.util.concurrent.

А что не так с wait/notify ? В java.util.concurrent я пока что побаиваюсь лезть, т.к. еще базовые концепции не совсем понимаю.

GIV>Ты расскажи что делаешь то.

Джаву изучаю java — язык для java men, блин.
Re[3]: Boolean и его замыкания
От: f95.2  
Дата: 02.05.20 20:20
Оценка:
F2>Ну так и почему ошибка-то? СИнхронизация разве изменяет ссылку и заставляет ее указывать на другой объект?
F2>Нотификация разве меняет ссылку и заставляет ее указывать на другой объект?
F2>Или под "local variables" понимается не ссылка, а объект, на который она указывает?

Так, тут разобрался. Если убрать присваивание внутри лямбды, то ссылка становится финальной, и
компилятор перестает ругаться на синхронизацию и нотификацию.
Re[2]: Boolean и его замыкания
От: f95.2  
Дата: 02.05.20 20:36
Оценка:
Здравствуйте, GarryIV, Вы писали:

GIV>Второе.


Блин, вот смотрю код Boolean, Integer... у них вообще нет возможности изменить состояние существующего объекта,
только создать новый и присвоить значение существующей ссылке.

Почему был выбран такой странный дизайн?
Re[3]: Boolean и его замыкания
От: GarryIV  
Дата: 02.05.20 20:48
Оценка:
Здравствуйте, f95.2, Вы писали:

F2>Здравствуйте, GarryIV, Вы писали:


GIV>>Потому, что "local variables referenced from a lambda expression must be final or effectively final" — даже не знаю, что добавить. Так написано в JLS.

F2>Ну так и почему ошибка-то? СИнхронизация разве изменяет ссылку и заставляет ее указывать на другой объект?
F2>Нотификация разве меняет ссылку и заставляет ее указывать на другой объект?
Boolean flag = false;
Consumer<Object> handler = (Object) -> {
    synchronized (flag) {
        // flag = true;
        flag.notifyAll();
    }
};

handler.accept(null);


Закоментируй изменение и все будет компилироваться, тогда flag станет effectivy final и его можно будет использовать в лямбде.
synchronized самому по себе пофиг на мутабельность.

F2>Или под "local variables" понимается не ссылка, а объект, на который она указывает?

"local variables" это ссылка, но синхронизируется таки на объекте, на который она указывает.

import java.util.function.Consumer;

public class Main {

    static Boolean flag = false;

    public static void main(String[] args) {

        Consumer<Object> handler = (Object) -> {
            synchronized (flag) {
                flag = true;
                flag.notifyAll();
            }
        };

        handler.accept(null);   
    }
}



Вот это компилируется нормально но будет падать с
Exception in thread "main" java.lang.IllegalMonitorStateException
    at java.lang.Object.notifyAll(Native Method)
    at com.garryiv.test1.Main.lambda$main$0(Main.java:14)
    at com.garryiv.test1.Main.main(Main.java:18)


Тут лочится Boolean.FALSE а notifyAll пытается уже Boolean.TRUE

GIV>>Все эти wait/notify забудь, используй примитивы java.util.concurrent.

F2>А что не так с wait/notify ? В java.util.concurrent я пока что побаиваюсь лезть, т.к. еще базовые концепции не совсем понимаю.
Наоборот. Изучи happens before, volatile, synchronized и java.util.concurrent. Там все проще и понятнее, хардкор с wait/notify можно оставить на потом.
WBR, Igor Evgrafov
Re[3]: Boolean и его замыкания
От: GarryIV  
Дата: 02.05.20 20:58
Оценка:
Здравствуйте, f95.2, Вы писали:

F2>Блин, вот смотрю код Boolean, Integer... у них вообще нет возможности изменить состояние существующего объекта,

F2>только создать новый и присвоить значение существующей ссылке.

F2>Почему был выбран такой странный дизайн?


И слава богу нельзя. Сейчас можно написать final Boolean b = false и быть уверенным что оно именно false всегда и никто это не поменяет. Шрить мутабельные объекты между потоками грех и бог убивает по котенку каждый раз когда кто-то это делает. И вообще шарить мутабельные объекты грешновато.

PS: http://henrikeichenhardt.blogspot.com/2013/06/why-shared-mutable-state-is-root-of-all.html
WBR, Igor Evgrafov
Re[4]: Boolean и его замыкания
От: f95.2  
Дата: 02.05.20 21:21
Оценка:
GIV>>>Все эти wait/notify забудь, используй примитивы java.util.concurrent.
F2>>А что не так с wait/notify ? В java.util.concurrent я пока что побаиваюсь лезть, т.к. еще базовые концепции не совсем понимаю.
GIV>Наоборот. Изучи happens before, volatile, synchronized и java.util.concurrent. Там все проще и понятнее, хардкор с wait/notify можно оставить на потом.

Если что я с плюсов пришел. Так что happens before я понимаю.
Чего я пока не понимаю, так это обилия разного рода фьючей, экзекуторов и когда каждый из них должен применяться.
Но разберусь со временем.

А вот что хардкорного в wait/notify ты так и не ответил.
Re[5]: Boolean и его замыкания
От: Слава  
Дата: 02.05.20 21:33
Оценка:
Здравствуйте, f95.2, Вы писали:

F2>А вот что хардкорного в wait/notify ты так и не ответил.


А вот ты попиши на них — и узнаешь, что хардкорного.
Re[6]: Boolean и его замыкания
От: f95.2  
Дата: 02.05.20 21:40
Оценка:
С>А вот ты попиши на них — и узнаешь, что хардкорного.

Ок. Спасибо за конструктивную дискуссию.
Re[5]: Boolean и его замыкания
От: GarryIV  
Дата: 02.05.20 21:44
Оценка:
Здравствуйте, f95.2, Вы писали:

F2>А вот что хардкорного в wait/notify ты так и не ответил.


Оно неудбное древнее говно мамонта. А так сама по себе штука простая.
WBR, Igor Evgrafov
Re[5]: Boolean и его замыкания
От: vsb Казахстан  
Дата: 02.05.20 21:49
Оценка:
Здравствуйте, f95.2, Вы писали:

F2>А вот что хардкорного в wait/notify ты так и не ответил.


Ими сложно пользоваться для написания корректного кода. Это низкоуровневые примитивы. Поэтому в стандартной библиотеке Java написали уйму классов, позволяющих решать большинство мультипоточных проблем более высокоуровневым способом. Считается, что таким образом проще писать и читать корректный мультипоточный код.

Впрочем если ты гуру по мультипоточности, хорошо понимаешь, что ты делаешь и твой код будут читать такие же гуру, можно и пользоваться, почему бы нет, оно работает.
Re[6]: Boolean и его замыкания
От: f95.2  
Дата: 02.05.20 21:58
Оценка:
vsb>Ими сложно пользоваться для написания корректного кода. Это низкоуровневые примитивы. Поэтому в стандартной библиотеке Java написали уйму классов, позволяющих решать большинство мультипоточных проблем более высокоуровневым способом. Считается, что таким образом проще писать и читать корректный мультипоточный код.

Понятно.
А вот смотри, в java.util.concurrent есть куча довольно специализированных контейнеров, например, DelayQueue, TransferQueue, LinkedBlockingQueue, LinkedTransferQueue.
Насколько часто они используются (и насколько часто о них спрашивают на собеседованиях)?

Ожидают ли от типичного разработчика их знания?
Точнее, не знания об их существовании, а понимания алгоритмов, которые за ними стоят, их сильных и слабых сторон.
Re[7]: Boolean и его замыкания
От: vsb Казахстан  
Дата: 02.05.20 22:06
Оценка:
Здравствуйте, f95.2, Вы писали:

vsb>>Ими сложно пользоваться для написания корректного кода. Это низкоуровневые примитивы. Поэтому в стандартной библиотеке Java написали уйму классов, позволяющих решать большинство мультипоточных проблем более высокоуровневым способом. Считается, что таким образом проще писать и читать корректный мультипоточный код.


F2>Понятно.

F2>А вот смотри, в java.util.concurrent есть куча довольно специализированных контейнеров, например, DelayQueue, TransferQueue, LinkedBlockingQueue, LinkedTransferQueue.
F2>Насколько часто они используются (и насколько часто о них спрашивают на собеседованиях)?

F2>Ожидают ли от типичного разработчика их знания?

F2>Точнее, не знания об их существовании, а понимания алгоритмов, которые за ними стоят, их сильных и слабых сторон.

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

Впрочем все исходники в JDK открыты, при большом желании можно с этим разобраться.

Лично мне эти классы использовать не приходилось. Я использовал ArrayBlockingQueue, а все эти связные списки по-моему на современных процессорах только тормозят. Но могу ошибаться, мне важно было написать корректный код, в производительность этих кусков я не упирался и оптимизировать не пробовал, наверное есть случаи, когда и эти классы могут пригодиться.
Отредактировано 02.05.2020 22:07 vsb . Предыдущая версия .
Re[4]: Boolean и его замыкания
От: bzig  
Дата: 03.05.20 02:16
Оценка:
GIV>Шрить мутабельные объекты между потоками грех и бог убивает по котенку каждый раз когда кто-то это делает. И вообще шарить мутабельные объекты грешновато.

Это правда. Но требование делать final переменную при передаче в лямбду растёт корнями не отсюда.

GIV>И слава богу нельзя. Сейчас можно написать final Boolean b = false и быть уверенным что оно именно false всегда и никто это не поменяет.


"final List mutable = new ArrayList()" прекрасно передастся в лямбду, при этом объект вполне себе мутабельный.

Требование иметь final локальные переменные произрастает из размещения этих переменных на стэке. Даже если лямбда сразу в этом потоке вызовется стэк при этом изменяется. А уж если лямбда в другой поток уйдёт или будет использоваться после завершения данной функции, так вообще удар по памяти будет.

Соответственно, переменную со стэка копируют в поле лямбды. Теоретически, ничто не мешало бы позволять менять в лямбде это поле-копию, но тогда весь интернет был бы завален вотзефаками, потому что по коду нигде поле не объявляется и при чтении кода видна только одна переменная.

С помощью final проблему красиво решили — раз переменную менять нельзя, то можно смело создать её копию.
Re[2]: Boolean и его замыкания
От: Pavel Dvorkin Россия  
Дата: 03.05.20 05:43
Оценка:
Здравствуйте, GarryIV, Вы писали:

F2>>Что здесь происходит? Создается новый объект Boolean, и ему присваивается значение false (которое он сохраняет где-то внутри),

F2>>или просто ссылке b присваивается значение Boolean.FALSE?
GIV>Второе.

Гм.

public final class Boolean implements java.io.Serializable, Comparable<Boolean>
//...
    private final boolean value;
//...
    public Boolean(boolean value) {
        this.value = value;
    }
    public Boolean(String s) {
        this(parseBoolean(s));
    }


Вполне обычный боксинг.

Boolean b = false;

===

Boolean b = new Boolean(false);
With best regards
Pavel Dvorkin
Re[5]: Boolean и его замыкания
От: GarryIV  
Дата: 03.05.20 07:09
Оценка:
Здравствуйте, bzig, Вы писали:

B>"final List mutable = new ArrayList()" прекрасно передастся в лямбду, при этом объект вполне себе мутабельный.


И? Речь вообще сейчас не об этом.
WBR, Igor Evgrafov
Re[5]: Boolean и его замыкания
От: vsb Казахстан  
Дата: 03.05.20 09:33
Оценка:
Здравствуйте, bzig, Вы писали:

GIV>>Шрить мутабельные объекты между потоками грех и бог убивает по котенку каждый раз когда кто-то это делает. И вообще шарить мутабельные объекты грешновато.


B>Это правда. Но требование делать final переменную при передаче в лямбду растёт корнями не отсюда.


GIV>>И слава богу нельзя. Сейчас можно написать final Boolean b = false и быть уверенным что оно именно false всегда и никто это не поменяет.


B>"final List mutable = new ArrayList()" прекрасно передастся в лямбду, при этом объект вполне себе мутабельный.


B>Требование иметь final локальные переменные произрастает из размещения этих переменных на стэке. Даже если лямбда сразу в этом потоке вызовется стэк при этом изменяется. А уж если лямбда в другой поток уйдёт или будет использоваться после завершения данной функции, так вообще удар по памяти будет.


Собственно если не понятно, как оно работает, рекомендуется попробовать заменить лямбду сначала на анонимный класс, а потом этот анонимный класс на именованный не-внутренний класс. Тогда станет очевидно, что все эти значения просто передадутся в конструктор этого класса и сохранятся как поля объекта. А лямбда это просто сахар, автоматически создающий все эти конструкторы и поля, что создаёт впечатление, будто переменная используется магическим образом, но реально магии нет.

B>Соответственно, переменную со стэка копируют в поле лямбды. Теоретически, ничто не мешало бы позволять менять в лямбде это поле-копию, но тогда весь интернет был бы завален вотзефаками, потому что по коду нигде поле не объявляется и при чтении кода видна только одна переменная.


B>С помощью final проблему красиво решили — раз переменную менять нельзя, то можно смело создать её копию.


На самом деле могли бы и решить полностью. Для этого вместо переменной int надо объявлять что-то вроде new int[1] и вместо чтения/записи переменной читать/записывать элемент массива. Ну или завести специализированный класс-холдер. Просто не захотели заморачиваться.
Re[4]: Boolean и его замыкания
От: Pavel Dvorkin Россия  
Дата: 03.05.20 11:16
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Это не так. Это эквивалентно Boolean b = Boolean.valueOf(false);


М-да. Сэкономить решили. Ну, в общем, правильно. Я просто полагал, что делается по аналогии с другими типами — оболочками.
With best regards
Pavel Dvorkin
Re[6]: Boolean и его замыкания
От: Pavel Dvorkin Россия  
Дата: 03.05.20 11:23
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>С другими типами тоже valueOf() (: Причём по умолчанию тот же Integer от -128 до 127 тоже кешируется. Поэтому всякие приколы возникают вида


Да, сейчас посмотрел и хотел об этом упомянуть, отредактировав свое сообщение.
With best regards
Pavel Dvorkin
Re[4]: Boolean и его замыкания
От: Pavel Dvorkin Россия  
Дата: 03.05.20 11:27
Оценка:
Здравствуйте, GarryIV, Вы писали:

GIV>Есть боксинг а есть аутобоксинг, немного разные вещи


Дело не в этом, а в реализации valueOf, как верно отметил vsb

Integer v = i;

public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}

приведет к вызову конструктора при !(i >= IntegerCache.low && i <= IntegerCache.high), а иначе так же, как и Boolean
With best regards
Pavel Dvorkin
Re[5]: Boolean и его замыкания
От: GarryIV  
Дата: 03.05.20 13:06
Оценка:
Здравствуйте, Pavel Dvorkin, Вы писали:

GIV>>Есть боксинг а есть аутобоксинг, немного разные вещи


PD>Дело не в этом, а в реализации valueOf, как верно отметил vsb


PD>Integer v = i;


Ну да, у интов по другому.
WBR, Igor Evgrafov
Re[2]: Boolean и его замыкания
От: StanislavK Великобритания  
Дата: 05.05.20 06:53
Оценка:
Здравствуйте, GarryIV, Вы писали:

F2>>Откуда следует ответ на предыдущий вопрос? Он прописан в стандарте (я его не читал еще, разбираюсь же только), или зависит от реализации?

GIV>Хз, должно быть прописано. Искать влом.

Не, точно не прописано. Это просто оптимизация.
Re[3]: Boolean и его замыкания
От: GarryIV  
Дата: 05.05.20 09:31
Оценка:
Здравствуйте, StanislavK, Вы писали:

F2>>>Откуда следует ответ на предыдущий вопрос? Он прописан в стандарте (я его не читал еще, разбираюсь же только), или зависит от реализации?

GIV>>Хз, должно быть прописано. Искать влом.

SK>Не, точно не прописано. Это просто оптимизация.


https://docs.oracle.com/javase/specs/jls/se14/html/jls-5.html#jls-5.1.7

If the value p being boxed is the result of evaluating a constant expression (§15.29) of type boolean, byte, char, short, int, or long, and the result is true, false, a character in the range '\u0000' to '\u007f' inclusive, or an integer in the range -128 to 127 inclusive, then let a and b be the results of any two boxing conversions of p. It is always the case that a == b

WBR, Igor Evgrafov
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.