Ява"?"Оператор для проверки null-что это такое? (Не Троичный!)
Я читал статью, связанную с историей slashdot, и наткнулся на этот маленький лакомый кусочек:
возьмите последнюю версию Java, которая
пытается сделать проверку нулевого указателя
проще, предлагая сокращенный синтаксис
для бесконечного тестирования указателя. Просто
добавление вопросительного знака к каждому методу
вызов автоматически включает в себя
тест для null-указателями, замена
крысиное гнездо если-то утверждений, таких
как:
С этим:
я прочесал интернет (хорошо, я потратил по крайней мере 15 минут на поиск вариантов "вопросительный знак java") и ничего не получил. Итак, мой вопрос: есть ли официальная документация по этому поводу? Я обнаружил, что C# имеет аналогичный оператор ("??"оператор), но я хотел бы получить документацию для языка, на котором я работаю. Или это просто использование тернарного оператора, который я никогда раньше не видел.
спасибо!
изменить: ссылка на статью: http://infoworld.com/d/developer-world/12-programming-mistakes-avoid-292
13 ответов:
оригинальная идея исходит от groovy. Это было предложено для Java 7 в рамках проекта Coin:https://wiki.openjdk.java.net/display/Coin/2009 + предложения+TOC (Elvis и другие Null-Безопасные операторы), но еще не приняты.
оператора, связанные с Элвисом ?: было предложено сделать
x ?: yобозначениеx != null ? x : y, особенно полезно, когда x является сложным выражением.
этот синтаксис не существует в Java, и он не планируется включать в любую из предстоящих версий, о которых я знаю.
один из способов обойти отсутствие "?"оператор, использующий Java 8 без накладных расходов try-catch (который также может скрыть a
NullPointerExceptionвозник в другом месте, как уже упоминалось), чтобы создать класс для "трубных" методов в стиле Java-8-Stream.public class Pipe<T> { private T object; private Pipe(T t) { object = t; } public static<T> Pipe<T> of(T t) { return new Pipe<>(t); } public <S> Pipe<S> after(Function<? super T, ? extends S> plumber) { return new Pipe<>(object == null ? null : plumber.apply(object)); } public T get() { return object; } public T orElse(T other) { return object == null ? other : object; } }тогда данный пример станет:
public String getFirstName(Person person) { return Pipe.of(person).after(Person::getName).after(Name::getGivenName).get(); }
[EDIT]
при дальнейшем размышлении я понял, что на самом деле можно достичь того же самого только с помощью стандартного Java 8 классы:
public String getFirstName(Person person) { return Optional.ofNullable(person).map(Person::getName).map(Name::getGivenName).orElse(null); }в этом случае даже можно выбрать значение по умолчанию (например,
"<no first name>") вместоnullпередав его в качестве параметраorElse.
см.:https://blogs.oracle.com/darcy/project-coin:-the-final-five-or-so (в частности, "Элвис и другие безопасные операторы null").
в результате эта функция была рассмотрена для Java 7, но не была включена.
Это на самом деле оператор безопасного разыменования Groovy. Вы не можете использовать его в чистой Java (к сожалению), так что сообщение просто неверно (или, скорее всего, немного вводит в заблуждение, если оно утверждает, что Groovy является "последней версией Java").
можно определить методы util, которые решают это почти красивым способом с помощью Java 8 lambda.
Это вариант решение H-MANs но он использует перегруженные методы с несколькими аргументами для обработки нескольких шагов вместо того, чтобы ловить
NullPointerException.даже если я думаю, что это решение является своего рода прохладно я думаю, что я предпочитаю Гельдер Перейра секунды один, так как это не требует каких-либо методов util.
void example() { Entry entry = new Entry(); // This is the same as H-MANs solution Person person = getNullsafe(entry, e -> e.getPerson()); // Get object in several steps String givenName = getNullsafe(entry, e -> e.getPerson(), p -> p.getName(), n -> n.getGivenName()); // Call void methods doNullsafe(entry, e -> e.getPerson(), p -> p.getName(), n -> n.nameIt()); } /** Return result of call to f1 with o1 if it is non-null, otherwise return null. */ public static <R, T1> R getNullsafe(T1 o1, Function<T1, R> f1) { if (o1 != null) return f1.apply(o1); return null; } public static <R, T0, T1> R getNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, R> f2) { return getNullsafe(getNullsafe(o0, f1), f2); } public static <R, T0, T1, T2> R getNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, T2> f2, Function<T2, R> f3) { return getNullsafe(getNullsafe(o0, f1, f2), f3); } /** Call consumer f1 with o1 if it is non-null, otherwise do nothing. */ public static <T1> void doNullsafe(T1 o1, Consumer<T1> f1) { if (o1 != null) f1.accept(o1); } public static <T0, T1> void doNullsafe(T0 o0, Function<T0, T1> f1, Consumer<T1> f2) { doNullsafe(getNullsafe(o0, f1), f2); } public static <T0, T1, T2> void doNullsafe(T0 o0, Function<T0, T1> f1, Function<T1, T2> f2, Consumer<T2> f3) { doNullsafe(getNullsafe(o0, f1, f2), f3); } class Entry { Person getPerson() { return null; } } class Person { Name getName() { return null; } } class Name { void nameIt() {} String getGivenName() { return null; } }
Я не уверен, что это даже сработает; если, скажем, ссылка на человека была нулевой, что бы среда выполнения заменила ее? Новый человек? Это потребует от человека некоторой инициализации по умолчанию, которую вы ожидаете в этом случае. Вы можете избежать исключений с нулевыми ссылками, но вы все равно получите непредсказуемое поведение, если не планируете эти типы настроек.
The ?? оператор в C# лучше всего назвать оператором "coalesce"; вы можете связать несколько выражений, и это будет верните первый, который не является нулем. К сожалению, Java не имеют. Я думаю, что лучшее, что вы можете сделать, это использовать тернарный оператор для выполнения нулевых проверок и оценки альтернативы всему выражению, если какой-либо элемент в цепочке равен null:
return person == null ? "" : person.getName() == null ? "" : person.getName().getGivenName();вы также можете использовать try-catch:
try { return person.getName().getGivenName(); } catch(NullReferenceException) { return ""; }
вот он, нулевой безопасный вызов в Java 8:
public void someMethod() { String userName = nullIfAbsent(new Order(), t -> t.getAccount().getUser() .getName()); } static <T, R> R nullIfAbsent(T t, Function<T, R> funct) { try { return funct.apply(t); } catch (NullPointerException e) { return null; } }
Если кто-то ищет альтернативу для старых версий java, вы можете попробовать этот я написал:
/** * Strong typed Lambda to return NULL or DEFAULT VALUES instead of runtime errors. * if you override the defaultValue method, if the execution result was null it will be used in place * * * Sample: * * It won't throw a NullPointerException but null. * <pre> * {@code * new RuntimeExceptionHandlerLambda<String> () { * @Override * public String evaluate() { * String x = null; * return x.trim(); * } * }.get(); * } * <pre> * * * @author Robson_Farias * */ public abstract class RuntimeExceptionHandlerLambda<T> { private T result; private RuntimeException exception; public abstract T evaluate(); public RuntimeException getException() { return exception; } public boolean hasException() { return exception != null; } public T defaultValue() { return result; } public T get() { try { result = evaluate(); } catch (RuntimeException runtimeException) { exception = runtimeException; } return result == null ? defaultValue() : result; } }
вы можете проверить код, который вы предоставили, и он даст синтаксис error.So, он не поддерживается в Java. Groovy поддерживает его, и он был предложен для Java 7 (но никогда не включался).
тем не менее, вы можете использовать дополнительный, предоставленный в Java 8. Это может помочь вам в достижении чего-то подобного линия. https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html
Java не имеет точно синтаксис но по состоянию на JDK-8, у нас есть дополнительный API с различными методами в нашем распоряжении. Итак, версия C# с использованием нуль, условный оператор:
return person?.getName()?.getGivenName();может быть написано следующим образом в Java с дополнительный API:
return Optional.ofNullable(person) .map(e -> e.getName()) .map(e -> e.getGivenName()) .orElse(null);если
person,getNameилиgetGivenNameравно null, затем возвращается null.
Если это не проблема с производительностью, вы можете написать
public String getFirstName(Person person) { try { return person.getName().getGivenName(); } catch (NullPointerException ignored) { return null; } }
Comments