introducción
NPE (NullPointerException) es la excepción más común en los programas de depuración. Google tiene muchas discusiones sobre si el método debe devolver un objeto nulo o nuevo vacío.
Al comienzo del artículo, hablemos primero sobre el problema del NPE. El problema NPE es la NullPointerException que a menudo encontramos en el desarrollo. Supongamos que tenemos dos clases, y su diagrama de clase UML se muestra en la siguiente figura
En este caso, existe el siguiente código
user.getAddress (). GetProvince ();
Esta forma de escribir puede informar una NullPointerException cuando el usuario es nulo. Para resolver este problema, se adopta el siguiente método de escritura
if (user! = null) {dirección dirección = user.getAddress (); if (dirección! = null) {string province = dirección.getProvince (); }}Este estilo de escritura es relativamente feo. Para evitar el estilo de escritura feo anterior, el diseño feo se vuelve elegante. Java8 proporciona una clase opcional para optimizar este método de escritura, y la siguiente sección de texto se explicará en detalle.
Introducción de API
Permítanme presentar primero la API. A diferencia de otros artículos, este artículo adopta un método de analogía y combina el código fuente. A diferencia de otros artículos, cada listas de API hace que las personas no puedan encontrar los puntos clave.
(1) Opcional (valor t), vacía (), de (valor t), de Notullable (valor t)
Estas cuatro funciones tienen correlaciones, por lo que se colocan en un grupo para la memoria.
Permítanme explicar primero que opcional (valor t), es decir, el constructor, es un permiso privado y no se puede llamar externamente. Las otras tres funciones son permisos públicos para que los llamemos. Luego, la esencia de opcional es almacenar un valor real internamente, y al construir, se juzga directamente si su valor está vacío. Ok, eso sigue siendo bastante abstracto. Cargue directamente el código fuente del constructor opcional (valor t), como se muestra en la figura a continuación
Entonces, el código fuente de (valor t) es el siguiente
public static <t> opcional <t> de (t value) {return new Opcional <> (valor); } En otras palabras, el constructor se llama internamente por la función de (valor t). Según el código fuente del constructor, podemos sacar dos conclusiones:
(1) Cuando el valor del valor está vacío, aún se informará una NullPointerException.
(2) El objeto opcional construido por la función de (valor t) se puede construir normalmente cuando el valor del valor no está vacío.
Además, la clase opcional también mantiene un objeto con valor nulo, probablemente como el siguiente
Public Final Clase Opcional <T> {// omitir ...... private estático final opcional <?> vacía = nuevo opcional <> (); privado opcional () {this.value = null; } // omitir ... public static <t> opcional <t> vacía () {@supplesswarnings ("sin verificar") opcional <t> t = (opcional <t>) vacía; regresar t; }} Luego, la función de vacía () es devolver el objeto vacío.
Bueno, se han puesto muchas preparaciones. Se puede decir que Of Nillable (T Value) tiene la función, y se agrega el código fuente.
Public Static <T> Opcional <T> OfNullable (t value) {return value == null? vacía (): de (valor); } Bueno, todos deberían entender lo que significa. La diferencia en comparación con (valor t) es que cuando el valor del valor es nulo, de (valor t) informará una nullpointerexception; OfNullable (T Value) no lanzará una excepción, OfNullable (valor t) devuelve directamente un objeto vacío.
¿Eso significa que solo usamos la función anulable en lugar de la función en nuestro proyecto?
No, si algo existe, naturalmente tendrá valor. Cuando estamos ejecutando, no queremos ocultar nullpointerexception. En cambio, debe informar de inmediato, y en este caso, usar la función de. Pero tengo que admitir que realmente hay pocas escenas de este tipo. El blogger solo ha utilizado esta función al escribir casos de prueba JUnit.
(2) orelse (t otro), orelseget (el proveedor <? Extiende t> otro) y orelsethrow (el proveedor <? Extiende x> excepciones de apoyo)
Estas tres funciones se memorizan en un grupo y se llaman cuando el valor aprobado por el constructor es nulo. El uso de Orelse y Orelseget es el siguiente. Cuando el valor es nulo, se da un valor predeterminado:
@Testpublic void test () {user user = null; user = Opcional.ofnullable (usuario) .orelse (createUser ()); user = Oppectional.ofnullable (usuario) .orelseget (() -> createUser ()); } Public User CreateUser () {User User = New User (); user.setName ("Zhangsan"); devolver el usuario;} La diferencia entre estas dos funciones: cuando el valor del usuario no es nulo, la función ORELSE aún ejecutará el método CreateUser (), mientras que la función ORELSEGT no ejecutará el método CreateUser (), por lo que puede probarlo usted mismo.
En cuanto a Orelsethrow, cuando el valor es nulo, se extrae directamente una excepción. El uso es el siguiente
Usuario user = null; opcional.ofnullable (usuario) .orelsethrow (()-> nueva excepción ("el usuario no existe"));(3) mapa (función <? Super t, "extiende u> mapper) y platero (función <? Super t, opcional <u>> mapeador)
Estas dos funciones se colocan en un conjunto de memoria, y estas dos funciones hacen el funcionamiento de los valores de conversión.
Cargar directamente el código fuente
Public Final Clase Opcional <T> {// omitir ...... public <u> opcional <u> map (function <? Super t, "extiende u> mapper) {objetssquirenonnull (mapper); if (! isPresent ()) return vacía (); else {return Oppectional.ofNullable (mApper.apply (valor)); }} // omitir ... public <u> opcional <u> platmap (function <? Super t, opcional <u>> mapper) {objects.requirenonnull (mapper); if (! isPresent ()) return vacía (); else {return Objects.requirenonnull (mapper.apply (valor)); }}} No hay diferencia entre estas dos funciones en el cuerpo de la función. La única diferencia es el parámetro de entrada. El tipo de parámetro de entrada aceptado por la función de mapa es la función <? Super T ,? extiende u>, mientras que el tipo de parámetro de entrada de flapmap es function <? Super T, opcional <u>>.
En términos de uso específico, para el mapa:
Si la estructura del usuario es la siguiente
Usuario de clase pública {nombre de cadena privada; public String getName () {nombre de retorno; }}En este momento, el método de escritura para tomar el nombre es el siguiente
String City = Oppectional.ofNullable (usuario) .map (u-> u.getName ()). Get ();
Para platero:
Si la estructura del usuario es la siguiente
Usuario de clase pública {nombre de cadena privada; Public Opcional <String> getName () {return Oppectional.ofNullable (nombre); }}En este momento, el método de escritura para tomar el nombre es el siguiente
String City = Oppectional.ofNullable (usuario) .flatmap (u-> u.getName ()). Get ();
(4) ISPresent () e IfPresent (consumidor <? Super t> consumidor)
Coloque estas dos funciones juntas y memoríquelas. ISPresent significa determinar si el valor está vacío, y si es presente significa hacer algunas operaciones cuando el valor no está vacío. Los códigos fuente de estas dos funciones son los siguientes
Public Final Clase Opcional <T> {// omitir ...... public boolean isPresent () {return value! = null; } // omitir ... public void IfPresent (Consumer <? Super t> Consumer) {if (valor! = Null) consumer.accept (valor); }}Necesita una explicación adicional, no
if (user! = null) {// todo: haz algo}Escrito
Usuario user = opcional.ofnullable (usuario); if (opcional.ispresent ()) {// toDo: hacer algo} Debido a esto, la estructura del código sigue siendo fea. El blogger dará el método de escritura correcto más tarde
En cuanto a IfPresent (consumidor <? Super t> consumidor), el uso también es muy simple, como se muestra a continuación
Opcional.ofnullable (usuario) .ifpresente (u-> {// tODO: hacer algo});(5) Filtro (predicado <? Super t> predicción)
Sin más ADO, simplemente cargue el código fuente
Public Final Clase Opcional <T> {// omitir ...... objetos.requirenonnull (predicado); if (! isPresent ()) devuelve esto; el más return predicte.test (valor)? esto: vacía ();} El método de filtro acepta un predicado para filtrar los valores contenidos en opcional. Si los valores incluidos cumplen con las condiciones, entonces el opcional aún se devolverá; De lo contrario, se devolverá el opcional.Epty.
El uso es el siguiente
Opcional <Ser User> user1 = Oppectional.ofnullable (usuario) .filter (u -> u.getName (). Longitud () <6);
Como se muestra arriba, si la longitud del nombre del usuario es inferior a 6, entonces regrese. Si es mayor de 6, se devuelve un objeto vacío.
Uso práctico
Ejemplo 1
En el método de función
Escritura anterior
public String getCity (usuario usuario) lanza la excepción {if (user! = null) {if (user.getAddress ()! = null) {dirección de dirección = user.getAddress (); if (dirección.getCity ()! = NULL) {return diride.getCity (); }}} tire nueva expetión ("error de valor"); }Método de escritura Java8
public String getCity (usuario usuario) lanza la excepción {return Opcional.ofnullable (usuario) .map (u-> u.getaddress ()) .map (a-> a.getCity ()) .orelsethrow (()-> nueva excepción ("error de fetch));};}Ejemplo 2
Por ejemplo, en el programa principal
Escritura anterior
if (user! = null) {dosomething (usuario);}Método de escritura Java8
Opcional.ofnullable (usuario) .ifpresente (u-> {dosomething (u);});Ejemplo 3
Escritura anterior
Public User GetUser (usuario usuario) lanza la excepción {if (user! = null) {string name = user.getName (); if ("zhangsan" .equals (nombre)) {return user; }} else {user = new User (); user.setName ("Zhangsan"); devolver el usuario; }}Método de escritura Java8
Public User GetUser (usuario de usuario) {return Oppectional.ofnullable (usuario) .filter (u-> "zhangsan" .equals (u.getName ())) .orelseget ()-> {user user1 = new user (); user1.setName ("zhangsan"); return user1;};}Otros ejemplos no se enumerarán uno por uno. Sin embargo, el blogger cree que usar esta programación en cadena es realmente elegante en el código. Sin embargo, la lógica no es tan obvia y la legibilidad se reduce. Lo usamos de acuerdo con la situación en el proyecto.
Resumir
Lo anterior es todo el contenido de este artículo. Espero que el contenido de este artículo tenga cierto valor de referencia para el estudio o el trabajo de todos. Si tiene alguna pregunta, puede dejar un mensaje para comunicarse. Gracias por su apoyo a Wulin.com.