2017-01-18 15 views
1

Я хотел клонировать объект предиката, моя первая попытка была:Клонирование предикат

Predicate<String> p1 = str -> str.isEmpty(); 
Predicate<String> p2 = str -> p1.test(str); 

Но в том случае, если изменение p1, p2 изменение тоже. Есть ли способ клонировать предикат так, чтобы p2 не менялся?

+3

Что клонируется здесь? Ваши предикаты не имеют гражданства, поэтому у вас не должно быть проблем. – teppic

+0

Почему вы не можете повторно использовать старый? – Moira

+0

Ввести другую переменную. Если tou пусть p1 окончательно и ввести p3 = p1, вы можете использовать p1 как неизменяемый, а p3 - как mutable ref. –

ответ

2

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

Создание временной переменной, чтобы захватить значение p1 «s исправить эту проблему:

Predicate<String> p1 = str -> str.isEmpty(); 
final Predicate<String> pTemp = p1; 
Predicate<String> p2 = str -> pTemp.test(str); 

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

Когда вы добавляете pTemp, старый предикат будет ссылаться на две переменные, а именно: p1 и pTemp. На этом этапе повторное присвоение p1 не влияет на pTemp, поэтому поведение p2 останется неизменным.

Я предполагаю, что это было бы более полезно в цикле, когда вы строите предикат постепенно.

+1

Спасибо, это работает, хотя я понимаю, почему вы можете объяснить, что происходит за сценой, пожалуйста? – DBLouis

+0

Помимо бесполезности клонирования как такового, вы можете просто использовать 'Predicate p2 = p1 :: test;' постоянно связывать 'p1' с новым' Predicate'. Затем последующие изменения в 'p1' не влияют на' p2'. Чтобы проиллюстрировать, почему клонирование бесполезно, вы можете добиться того же, просто используя «Predicate p2 = p1;», он не клонирует, но имеет тот же эффект, предикаты, на которые ссылаются 'p1' и' p2', имеют такое же поведение и последующие изменения в 'p1' не влияют на' p2' ... – Holger