Ява"?"Оператор для проверки null-что это такое? (Не Троичный!)



Я читал статью, связанную с историей slashdot, и наткнулся на этот маленький лакомый кусочек:




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



С этим:




я прочесал интернет (хорошо, я потратил по крайней мере 15 минут на поиск вариантов "вопросительный знак java") и ничего не получил. Итак, мой вопрос: есть ли официальная документация по этому поводу? Я обнаружил, что C# имеет аналогичный оператор ("??"оператор), но я хотел бы получить документацию для языка, на котором я работаю. Или это просто использование тернарного оператора, который я никогда раньше не видел.



спасибо!



изменить: ссылка на статью: http://infoworld.com/d/developer-world/12-programming-mistakes-avoid-292

630   13  

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 7, но оно было отклонено:

http://tech.puredanger.com/java7/#null

один из способов обойти отсутствие "?"оператор, использующий 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

    Ничего не найдено.