Java 8 Mejor guía opcional

Número público reimpreso: Wang Er silencioso

Nunca es demasiado tarde para aprender, especialmente por las cosas buenas de Java 8. Opcional es uno de ellos. Esta clase proporciona una solución de nivel de clase para representar valores opcionales en lugar de referencias nulas. Como programador de Java, estoy realmente harto de NullPointerException (NPE), aunque estoy familiarizado con él como un viejo amigo, sabiendo que también es necesario: el programa está usando un objeto pero descubrió que el valor de este objeto es nulo Entonces, la máquina virtual Java lo arrojó con ira y lo usó como chivo expiatorio.

Por supuesto, nuestros programadores son responsables y no se sientan a mirar, por lo que hay muchas verificaciones de valor nulo. Aunque tales inspecciones a veces son innecesarias, estamos acostumbrados a los asuntos de rutina. Finalmente, Java 8 no puede soportarlo más, por lo que Opcional se introdujo para que el código que escribimos ya no sea tan rígido.

Java 8 Mejor guía opcional

 

01, cuál será el problema sin Opcional

Simulemos un escenario de aplicación real. Xiao Wang fue a trabajar el primer día y llevó a Lao Ma a organizar una tarea para él, pidiéndole que extraiga el nombre de un miembro de la base de datos en función de la identificación del miembro y luego lo imprima en la consola. Aunque es nuevo, pero esta tarea no puede fallar Xiao Wang, por lo que escribió este código en 10 minutos:

public class WithoutOptionalDemo {
    class Member {
        private String name;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

    public static void main(String[] args) {
        Member mem = getMemberByIdFromDB();
        if (mem != null) {
            System.out.println(mem.getName());
        }
    }

    public static Member getMemberByIdFromDB() {
        // 当前 ID 的会员不存在
        return null;
    }
}

Dado que el miembro con el ID actual no existe, el método getMemberByIdFromDB () devuelve nulo como resultado de no obtener el miembro, lo que significa que al imprimir el nombre del miembro, primero debe juzgar mem vacío, de lo contrario arrojará una excepción NPE ¿No lo crees? Deje que Xiaowang intente eliminar si (mem! = Null), la consola imprime inmediatamente la pila de errores para darle un vistazo.

Exception in thread "main" java.lang.NullPointerException
    at com.cmower.dzone.optional.WithoutOptionalDemo.main(WithoutOptionalDemo.java:24)

02. ¿Cómo resuelve este problema Opcional?

Después de que Xiao Wang envió el código, felizmente fue a Lao Ma para una nueva tarea. Con una mente abierta, Xiao Wang le pidió a Lao Ma que le eche un vistazo a su código, por lo que Lao Wang le dijo que debería intentar Opcional para evitar la comprobación innecesaria de valores nulos. Ahora, veamos cómo Xiao Wang resuelve los problemas anteriores a través de Opcional.

public class OptionalDemo {
    public static void main(String[] args) {
        Optional<Member> optional = getMemberByIdFromDB();
        optional.ifPresent(mem -> {
            System.out.println("会员姓名是:" + mem.getName());
        });
    }

    public static Optional<Member> getMemberByIdFromDB() {
        boolean hasName = true;
        if (hasName) {
            return Optional.of(new Member("沉默王二"));
        }
        return Optional.empty();
    }
}
class Member {
    private String name;

    public String getName() {
        return name;
    }

    // getter / setter
}

El método getMemberByIdFromDB () devuelve Opcional <Member> como resultado, lo que significa que el Miembro puede o no existir. En este momento, puede usar la expresión Lambda en el método ifPresent () de Opcional para imprimir directamente el resultado.

La razón por la cual Opcional puede resolver el problema de NPE es porque nos dice claramente que no necesitamos juzgarlo vacío. Es como una señal de tráfico en una encrucijada, que le indica claramente a dónde ir.

03, crear objeto opcional

1) Puede usar el método estático empty () para crear un objeto opcional vacío

Optional<String> empty = Optional.empty();
System.out.println(empty); // 输出:Optional.empty

2) Puede usar el método estático de () para crear un objeto opcional no vacío

Optional<String> opt = Optional.of("沉默王二");
System.out.println(opt); // 输出:Optional[沉默王二]

Por supuesto, el parámetro pasado al método of () debe ser no nulo, es decir, no puede ser nulo, de lo contrario, se lanzará NullPointerException.

String name = null;
Optional<String> optnull = Optional.of(name);

3) Puede usar el método estático de Nullable () para crear un objeto Opcional que esté vacío y no sea anulable

String name = null;
Optional<String> optOrNull = Optional.ofNullable(name);
System.out.println(optOrNull); // 输出:Optional.empty

El método ofNullable () tiene una expresión ternaria en su interior. Si el parámetro es nulo, devuelve la constante privada VACÍO; de lo contrario, se crea un nuevo objeto Opcional utilizando la nueva palabra clave; no se generarán más excepciones NPE.

04. Determine si el valor existe

El método isPresent () se puede usar para determinar si existe un objeto Opcional. Si existe, el método devuelve verdadero, de lo contrario, devuelve falso en lugar de obj! = Nulo.

Optional<String> opt = Optional.of("沉默王二");
System.out.println(opt.isPresent()); // 输出:true

Optional<String> optOrNull = Optional.ofNullable(null);
System.out.println(opt.isPresent()); // 输出:false

Después de Java 11, también puede juzgar el resultado opuesto de isPresent () por el método isEmpty ().

Optional<String> opt = Optional.of("沉默王二");
System.out.println(opt.isPresent()); // 输出:false

Optional<String> optOrNull = Optional.ofNullable(null);
System.out.println(opt.isPresent()); // 输出:true

05, expresión no vacía

La clase Opcional tiene un método muy moderno ifPresent (), que nos permite ejecutar algún código usando programación funcional, por lo que lo llamo una expresión no vacía. Si no existe tal método, generalmente necesitamos juzgar el objeto Opcional por el método isPresent () y luego ejecutar el código correspondiente:

Optional<String> optOrNull = Optional.ofNullable(null);
if (optOrNull.isPresent()) {
    System.out.println(optOrNull.get().length());
}

Con ifPresent (), la situación es completamente diferente, puede pasar directamente la expresión de Lambda al método, el código es más conciso y más intuitivo.

Optional<String> opt = Optional.of("沉默王二");
opt.ifPresent(str -> System.out.println(str.length()));

Después de Java 9, también puede ejecutar dos resultados a través del método ifPresentOrElse (action, emptyAction), ejecutar action cuando no esté vacío y ejecutar emptyAction cuando esté vacío.

Optional<String> opt = Optional.of("沉默王二");
opt.ifPresentOrElse(str -> System.out.println(str.length()), () -> System.out.println("为空"));

06. Establecer (obtener) el valor predeterminado

A veces, cuando creamos (obtenemos) un objeto Opcional, necesitamos un valor predeterminado, y los métodos orElse () y orElseGet () son útiles.

El método orElse () se utiliza para devolver el valor envuelto en el objeto Opcional. Si el valor no es nulo, devuelve; de ​​lo contrario, devuelve el valor predeterminado. El tipo de parámetro de este método es consistente con el tipo de valor.

String nullName = null;
String name = Optional.ofNullable(nullName).orElse("沉默王二");
System.out.println(name); // 输出:沉默王二

El método orElseGet () es similar al método orElse (), pero con diferentes tipos de parámetros. Si el valor en el objeto Opcional es nulo, se ejecuta la función en el parámetro.

String nullName = null;
String name = Optional.ofNullable(nullName).orElseGet(()->"沉默王二");
System.out.println(name); // 输出:沉默王二

A juzgar por los resultados de salida y la forma del código, estos dos métodos son muy similares. Esto inevitablemente plantea nuestras dudas. ¿Es necesario que los diseñadores de la biblioteca de clases de Java hagan esto?

Supongamos ahora que existe un método para obtener valores predeterminados, de una manera muy tradicional.

public static String getDefaultValue() {
    System.out.println("getDefaultValue");
    return "沉默王二";
}

Luego, llame al método getDefaultValue () a través del método orElse () y el método orElseGet () respectivamente para devolver el valor predeterminado.

public static void main(String[] args) {
    String name = null;
    System.out.println("orElse");
    String name2 = Optional.ofNullable(name).orElse(getDefaultValue());

    System.out.println("orElseGet");
    String name3 = Optional.ofNullable(name).orElseGet(OrElseOptionalDemo::getDefaultValue);
}

Nota: Nombre de clase :: El nombre del método es una sintaxis introducida en Java 8. No hay () después del nombre del método, lo que indica que no se llama necesariamente al método.

El resultado es el siguiente:

orElse
getDefaultValue

orElseGet
getDefaultValue

El resultado es similar, no muy diferente, esto es cuando el valor del objeto Opcional es nulo. ¿Qué pasa si el valor del objeto opcional no es nulo?

public static void main(String[] args) {
    String name = "沉默王三";
    System.out.println("orElse");
    String name2 = Optional.ofNullable(name).orElse(getDefaultValue());

    System.out.println("orElseGet");
    String name3 = Optional.ofNullable(name).orElseGet(OrElseOptionalDemo::getDefaultValue);
}

El resultado es el siguiente:

orElse
getDefaultValue
orElseGet

Hola, o ElseGet () no llamó a getDefaultValue (). ¿Qué método tiene mejor rendimiento, entiendes?

07, obtén el valor

Intuitivamente, semánticamente, el método get () es el método más auténtico para obtener el valor del objeto Opcional, pero desafortunadamente, este método es defectuoso, porque si el valor del objeto Opcional es nulo, el método arrojará la excepción NoSuchElementException. Esto es completamente contrario a nuestra intención original de usar la clase Opcional.

public class GetOptionalDemo {
    public static void main(String[] args) {
        String name = null;
        Optional<String> optOrNull = Optional.ofNullable(name);
        System.out.println(optOrNull.get());
    }
}

Este programa lanzará una excepción cuando se ejecute:

Exception in thread "main" java.util.NoSuchElementException: No value present
    at java.base/java.util.Optional.get(Optional.java:141)
    at com.cmower.dzone.optional.GetOptionalDemo.main(GetOptionalDemo.java:9)

Aunque la excepción lanzada es NoSuchElementException en lugar de NPE, en nuestra opinión, obviamente es "cinco pasos y cien pasos". Se recomienda que el método orElseGet () obtenga el valor del objeto Opcional.

08, valor de filtro

Xiao Wang actualizó el código anterior a través de la clase Opcional, y felizmente corrió para encontrar el viejo caballo para completar la tarea. Lao Ma siente que este tipo es bueno, flexible, activo y que vale la pena cultivar, por lo que le dio a Xiao Wang una nueva tarea: verificar la longitud de la contraseña cuando el usuario se registra.

Después de que Xiao Wang obtuvo la tarea, Le abrió las flores porque solo tenía que aprender el método filter () de la clase Opcional, que fue útil.

public class FilterOptionalDemo {
    public static void main(String[] args) {
        String password = "12345";
        Optional<String> opt = Optional.ofNullable(password);
        System.out.println(opt.filter(pwd -> pwd.length() > 6).isPresent());
    }
}

El tipo de parámetro del método filter () es Predicate (una interfaz funcional agregada en Java 8), lo que significa que una expresión Lambda se puede pasar al método como condición, y si el resultado de la expresión es falso, un VACÍO Objeto opcional, de lo contrario, devuelve el objeto opcional filtrado.

En el ejemplo anterior, debido a que la longitud de la contraseña es 5, el resultado de la salida del programa es falso. Suponiendo que la longitud de la contraseña debe estar entre 6 y 10 dígitos, se puede agregar otra condición. Mire el código después de que Xiao Wang aumentó la dificultad.

Predicate<String> len6 = pwd -> pwd.length() > 6;
Predicate<String> len10 = pwd -> pwd.length() < 10;

password = "1234567";
opt = Optional.ofNullable(password);
boolean result = opt.filter(len6.and(len10)).isPresent();
System.out.println(result);

Esta vez, el resultado de la salida del programa es verdadero, porque la contraseña se ha convertido en 7 dígitos, entre 6 y 10 dígitos. Imagine cuánto tiempo duraría el código si Xiao Wang usara if-else para realizar esta tarea.

09, valor de conversión

Después de verificar la longitud de la contraseña, Xiao Wang todavía siente que no es suficiente y siente que se debe verificar la seguridad de la contraseña. Por ejemplo, la contraseña no puede ser "contraseña". Entonces comenzó a estudiar el método map (), que puede convertir el objeto opcional original en un nuevo objeto opcional de acuerdo con ciertas reglas, y el objeto opcional original no cambiará.

Veamos primero un ejemplo simple escrito por Xiao Wang:

public class OptionalMapDemo {
    public static void main(String[] args) {
        String name = "沉默王二";
        Optional<String> nameOptional = Optional.of(name);
        Optional<Integer> intOpt = nameOptional
                .map(String::length);

        System.out.println( intOpt.orElse(0));
    }
}

En el ejemplo anterior, el parámetro String :: length del método map () significa que se debe generar un nuevo objeto Opcional de tipo Integer de acuerdo con la longitud de la cadena del tipo de cadena original Opcional.

Después de descubrir el uso básico del método map (), Xiao Wang decidió combinar el método map () con el método filter (). El primero se usa para convertir la contraseña a minúsculas, y el segundo se usa para determinar la longitud y si es "contraseña" .

public class OptionalMapFilterDemo {
    public static void main(String[] args) {
        String password = "password";
        Optional<String>  opt = Optional.ofNullable(password);

        Predicate<String> len6 = pwd -> pwd.length() > 6;
        Predicate<String> len10 = pwd -> pwd.length() < 10;
        Predicate<String> eq = pwd -> pwd.equals("password");

        boolean result = opt.map(String::toLowerCase).filter(len6.and(len10 ).and(eq)).isPresent();
        System.out.println(result);
    }
}
238 artículos originales publicados · Me gusta 68 · Visitas 30,000+

Supongo que te gusta

Origin blog.csdn.net/qq_45401061/article/details/104798446
Recomendado
Clasificación