codigo - para que sirve settitle en java
Usos para Opcional (13)
1 - Como tipo de retorno de método público cuando el método podría devolver nulo:
Aquí hay un buen artículo que muestra la utilidad de usecase # 1. Hay este codigo
...
if (user != null) {
Address address = user.getAddress();
if (address != null) {
Country country = address.getCountry();
if (country != null) {
String isocode = country.getIsocode();
if (isocode != null) {
isocode = isocode.toUpperCase();
}
}
}
}
...
se transforma en esto
String result = Optional.ofNullable(user)
.flatMap(User::getAddress)
.flatMap(Address::getCountry)
.map(Country::getIsocode)
.orElse("default");
utilizando Opcional como valor de retorno de los métodos getter respectivos.
Habiendo estado usando Java 8 ahora por más de 6 meses, estoy muy contento con los nuevos cambios en la API. Un área en la que aún no confío es en cuándo usar Optional
. Parece que me muevo entre querer usarlo en todas partes, algo puede ser null
y en ninguna parte.
Parece que hay muchas situaciones en las que podría usarlo, y nunca estoy seguro de si agrega beneficios (legibilidad / seguridad nula) o si solo genera una sobrecarga adicional.
Por lo tanto, tengo algunos ejemplos y me interesaría saber qué piensa la comunidad sobre si lo Optional
es beneficioso.
1 - Como tipo de retorno de método público cuando el método podría devolver null
:
public Optional<Foo> findFoo(String id);
2 - Como parámetro de método cuando el parámetro puede ser null
:
public Foo doSomething(String id, Optional<Bar> barOptional);
3 - Como miembro opcional de un bean:
public class Book {
private List<Pages> pages;
private Optional<Index> index;
}
4 - En Collections
:
En general no creo:
List<Optional<Foo>>
agrega cualquier cosa, especialmente porque se puede usar filter()
para eliminar valores null
, etc., pero ¿hay algún buen uso para Optional
en las colecciones?
¿Algún caso me he perdido?
Aquí hay un uso interesante (creo) para ... Pruebas.
Tengo la intención de probar en gran medida uno de mis proyectos y, por lo tanto, construyo afirmaciones; solo hay cosas que tengo que verificar y otras que no.
Por lo tanto, construyo cosas para afirmar y uso una afirmación para verificarlas, como esto:
public final class NodeDescriptor<V>
{
private final Optional<String> label;
private final List<NodeDescriptor<V>> children;
private NodeDescriptor(final Builder<V> builder)
{
label = Optional.fromNullable(builder.label);
final ImmutableList.Builder<NodeDescriptor<V>> listBuilder
= ImmutableList.builder();
for (final Builder<V> element: builder.children)
listBuilder.add(element.build());
children = listBuilder.build();
}
public static <E> Builder<E> newBuilder()
{
return new Builder<E>();
}
public void verify(@Nonnull final Node<V> node)
{
final NodeAssert<V> nodeAssert = new NodeAssert<V>(node);
nodeAssert.hasLabel(label);
}
public static final class Builder<V>
{
private String label;
private final List<Builder<V>> children = Lists.newArrayList();
private Builder()
{
}
public Builder<V> withLabel(@Nonnull final String label)
{
this.label = Preconditions.checkNotNull(label);
return this;
}
public Builder<V> withChildNode(@Nonnull final Builder<V> child)
{
Preconditions.checkNotNull(child);
children.add(child);
return this;
}
public NodeDescriptor<V> build()
{
return new NodeDescriptor<V>(this);
}
}
}
En la clase NodeAssert, hago esto:
public final class NodeAssert<V>
extends AbstractAssert<NodeAssert<V>, Node<V>>
{
NodeAssert(final Node<V> actual)
{
super(Preconditions.checkNotNull(actual), NodeAssert.class);
}
private NodeAssert<V> hasLabel(final String label)
{
final String thisLabel = actual.getLabel();
assertThat(thisLabel).overridingErrorMessage(
"node''s label is null! I didn''t expect it to be"
).isNotNull();
assertThat(thisLabel).overridingErrorMessage(
"node''s label is not what was expected!/n"
+ "Expected: ''%s''/nActual : ''%s''/n", label, thisLabel
).isEqualTo(label);
return this;
}
NodeAssert<V> hasLabel(@Nonnull final Optional<String> label)
{
return label.isPresent() ? hasLabel(label.get()) : this;
}
}
¡Lo que significa que la afirmación realmente solo se activa si quiero comprobar la etiqueta!
Creo que la Guava Opcional y su página wiki lo ponen bastante bien:
Además del aumento en la legibilidad que viene de dar un nombre nulo, la mayor ventaja de la Opcional es su idoneidad a prueba de idiotas. Le obliga a pensar activamente en el caso de ausencia si desea que su programa se compile, ya que tiene que desenvolver activamente el Opcional y abordar ese caso. Null hace que sea inquietantemente fácil simplemente olvidar las cosas, y aunque FindBugs ayuda, no creemos que aborde el problema tan bien.
Esto es especialmente relevante cuando devuelve valores que pueden o no estar "presentes". Es mucho más probable que usted (y otros) olviden que otro método (a, b) podría devolver un valor nulo de lo que probablemente olvidará que un podría ser nulo cuando está implementando otro método. Devolver Opcional hace que sea imposible para las personas que llaman olvidar ese caso, ya que tienen que desenvolver el objeto por sí mismos para compilar su código. - (Fuente: Guava Wiki - Usar y evitar null - ¿Cuál es el punto? )
Optional
agrega algo de sobrecarga, pero creo que su clara ventaja es que explícita que un objeto puede estar ausente y que los programadores manejan la situación. ¡Evita que alguien se olvide del cheque querido != null
.
Tomando el ejemplo de 2 , creo que es un código mucho más explícito para escribir:
if(soundcard.isPresent()){
System.out.println(soundcard.get());
}
que
if(soundcard != null){
System.out.println(soundcard);
}
Para mí, la Optional
captura mejor el hecho de que no hay una tarjeta de sonido presente.
Mis 2 ¢ sobre tus puntos:
-
public Optional<Foo> findFoo(String id);
- No estoy seguro de esto. Quizás devolvería unResult<Foo>
que podría estar vacío o contener unFoo
. Es un concepto similar, pero no es realmente unOptional
. -
public Foo doSomething(String id, Optional<Bar> barOptional);
- Preferiría @Nullable y una verificación de errores, como en 2 - vea también esta discusión . - Su ejemplo de libro: no estoy seguro de si usaría el Opcional internamente, eso podría depender de la complejidad. Para la "API" de un libro, usaría un
Optional<Index> getIndex()
para indicar explícitamente que el libro podría no tener un índice. - No lo usaría en colecciones, en lugar de no permitir valores nulos en colecciones
En general, trataría de minimizar el paso de null
s. (Una vez quemado ...) Creo que vale la pena encontrar las abstracciones adecuadas e indicar a los demás programadores lo que realmente representa un cierto valor de retorno.
Desde el tutorial de Oracle :
El propósito de Opcional no es reemplazar cada referencia nula en su base de código, sino ayudar a diseñar mejores API en las que, solo con leer la firma de un método, los usuarios pueden decir si deben esperar un valor opcional. Además, la Opcional lo obliga a desenvolver activamente una Opcional para tratar la ausencia de un valor; como resultado, protege su código contra excepciones de puntero nulo no deseadas.
El punto principal de Optional
es proporcionar un medio para que una función devuelva un valor para indicar la ausencia de un valor de retorno. Vea esta discusión . Esto permite a la persona que llama continuar con una cadena de llamadas de métodos fluidos.
Esto concuerda más con el caso de uso # 1 en la pregunta del OP. Aunque, la ausencia de un valor es una formulación más precisa que nula, ya que algo como IntStream.findFirst
nunca podría devolver nulo.
Para el caso de uso n . ° 2 , al pasar un argumento opcional a un método, esto podría funcionar, pero es bastante torpe. Supongamos que tiene un método que toma una cadena seguida de una segunda cadena opcional. Aceptar un Optional
como el segundo argumento resultaría en un código como este:
foo("bar", Optional.of("baz"));
foo("bar", Optional.empty());
Incluso aceptar nulo es mejor
foo("bar", "baz");
foo("bar", null);
Probablemente lo mejor es tener un método sobrecargado que acepte un solo argumento de cadena y proporcione un valor predeterminado para el segundo:
foo("bar", "baz");
foo("bar");
Esto tiene limitaciones, pero es mucho mejor que cualquiera de los anteriores.
Los casos de uso # 3 y # 4 , que tienen un Optional
en un campo de clase o en una estructura de datos, se consideran un mal uso de la API. Primero, va en contra del objetivo principal de diseño de Optional
como se indica en la parte superior. En segundo lugar, no agrega ningún valor.
Hay tres formas de lidiar con la ausencia de un valor en una Optional
: proporcionar un valor sustituto, llamar a una función para proporcionar un valor sustituto o lanzar una excepción. Si está almacenando en un campo, lo haría en el momento de la inicialización o asignación. Si agrega valores a una lista, como se mencionó en el OP, tiene la opción adicional de simplemente no agregar el valor, por lo tanto "aplanar" los valores ausentes.
Estoy seguro de que alguien podría idear algunos casos ideados donde realmente quieran almacenar un Optional
en un campo o una colección, pero en general, es mejor evitar hacer esto.
Java SE 8 introduce una nueva clase llamada java.util.Optional,
Puede crear un opcional vacío u opcional con valor nulo.
Optional<String> emptyOptional= Optional.empty();
Y aquí hay un opcional con un valor no nulo:
String valueString = new String("TEST");
Optional<String > optinalValueString = Optional.of(valueString );
Hacer algo si un valor está presente
Ahora que tiene un objeto opcional, puede acceder a los métodos disponibles para tratar explícitamente la presencia o ausencia de valores. En lugar de tener que recordar hacer un cheque nulo, como sigue:
String nullString = null;
if(nullString != null){
System.out.println(nullString );
}
Puede usar el método ifPresent () de la siguiente manera:
Optional<String> optinalString= null;
optinalString.ifPresent(System.out::println);
package optinalTest;
import java.util.Optional;
public class OptionalTest {
public Optional<String> getOptionalNullString() {
return null;
// return Optional.of("TESt");
}
public static void main(String[] args) {
OptionalTest optionalTest = new OptionalTest();
Optional<Optional<String>> optionalNullString = Optional.ofNullable(optionalTest.getOptionalNullString());
if (optionalNullString.isPresent()) {
System.out.println(optionalNullString.get());
}
}
}
Llego tarde al juego, pero para lo que valga, quiero agregar mis 2 centavos. Van en contra del objetivo de diseño de Optional
, que está bien resumido por la respuesta de Stuart Marks , pero todavía estoy convencido de su validez (obviamente).
Uso opcional en todas partes
En general
Escribí una publicación de blog completa sobre el uso de Optional
pero básicamente se trata de esto:
- Diseña tus clases para evitar la opcionalidad siempre que sea posible
- en todos los casos restantes, el valor predeterminado debe ser utilizar
Optional
lugar denull
- posiblemente haga excepciones para:
- variables locales
- Devuelve valores y argumentos a métodos privados.
- bloques de código críticos para el rendimiento (sin conjeturas, use un generador de perfiles)
Las dos primeras excepciones pueden reducir la sobrecarga percibida de envolver y desempaquetar referencias en Optional
. Se eligen de tal manera que un nulo nunca puede pasar legalmente un límite de una instancia a otra.
Tenga en cuenta que esto casi nunca permitirá s Optional
en colecciones, que es casi tan mala como null
. Simplemente no lo hagas. ;)
Respecto a tus preguntas.
- Sí.
- Si la sobrecarga no es una opción, sí.
- Si otros enfoques (subclasificación, decoración, ...) no son una opción, sí.
- ¡Por favor no!
Ventajas
Hacer esto reduce la presencia de null
s en su base de código, aunque no los erradique. Pero ese ni siquiera es el punto principal. Hay otras ventajas importantes:
Aclara la intención
El uso de Optional
expresa claramente que la variable es, bueno, opcional. Cualquier lector de su código o consumidor de su API será golpeado en la cabeza con el hecho de que podría no haber nada allí y que es necesario realizar una verificación antes de acceder al valor.
Elimina la incertidumbre
Sin Optional
el significado de una ocurrencia null
no está claro. Podría ser una representación legal de un estado (ver Map.get
) o un error de implementación, como una inicialización faltante o fallida.
Esto cambia dramáticamente con el uso persistente de Optional
. Aquí, ya la aparición de null
significa la presencia de un error. (Debido a que si se permitiera que faltara el valor, se habría utilizado un Optional
). Esto hace que la depuración de una excepción de puntero nulo sea mucho más fácil, ya que la pregunta sobre el significado de este null
ya está respondida.
Más cheques nulos
Ahora que ya nada puede ser null
, esto puede aplicarse en todas partes. Ya sea con anotaciones, aserciones o comprobaciones simples, nunca debe pensar si este argumento o ese tipo de retorno puede ser nulo. No se puede
Desventajas
Por supuesto, no hay bala de plata ...
Actuación
Ajustar los valores (especialmente los primitivos) en una instancia adicional puede degradar el rendimiento. En bucles apretados, esto podría volverse perceptible o incluso peor.
Tenga en cuenta que el compilador podría burlar la referencia adicional para tiempos de vida cortos de Optional
s. En Java 10 , los tipos de valor podrían reducir o eliminar aún más la penalización.
Publicación por entregas
Optional
no es serializable pero una workaround no es demasiado complicada.
Invariancia
Debido a la invariancia de los tipos genéricos en Java, ciertas operaciones se vuelven engorrosas cuando el tipo de valor real se inserta en un argumento de tipo genérico. Aquí se da un ejemplo (ver "Polimorfismo paramétrico") .
No creo que Opcional sea un sustituto general de los métodos que potencialmente devuelven valores nulos.
La idea básica es: la ausencia de un valor no significa que esté potencialmente disponible en el futuro. Es una diferencia entre findById (-1) y findById (67).
La información principal de Optionals para el llamante es que puede que no cuente con el valor dado, pero puede estar disponible en algún momento. Tal vez desaparezca y vuelva más tarde una vez más. Es como un interruptor de encendido / apagado. Tienes la "opción" para encender o apagar la luz. Pero no tiene opción si no tiene una luz para encender.
Por lo tanto, me parece demasiado complicado introducir Optionals en todos los lugares donde antes se devolvía potencialmente nulo. Seguiré usando nulo, pero solo en áreas restringidas como la raíz de un árbol, inicialización lenta y métodos de búsqueda explícitos.
Parece Optional
solo es útil si el tipo T en Opcional es un tipo primitivo como int
, long
, char
, etc. Para las clases "reales", no tiene sentido para mí, ya que puede usar un valor null
todos modos.
Creo que fue tomado de aquí (o de otro concepto de lenguaje similar).
En C # esta Nullable<T>
se introdujo hace mucho tiempo para envolver los tipos de valor.
Personalmente, prefiero usar la herramienta de inspección de código de IntelliJ para usar los controles @NotNull
y @Nullable
, ya que estos son en gran medida el tiempo de compilación (puede tener algunos controles de tiempo de ejecución) Esto tiene una sobrecarga menor en términos de legibilidad de código y rendimiento de tiempo de ejecución. No es tan riguroso como el uso de Opcional, sin embargo, esta falta de rigor debe estar respaldada por pruebas de unidades decentes.
public @Nullable Foo findFoo(@NotNull String id);
public @NotNull Foo doSomething(@NotNull String id, @Nullable Bar barOptional);
public class Book {
private List<Pages> pages;
private @Nullable Index index;
}
List<@Nullable Foo> list = ..
Esto funciona con Java 5 y no es necesario envolver y desenvolver valores. (o crear objetos envoltorios)
Si no te gusta comprobar de esta manera
if(obj!=null){
}
Entonces puedes hacerlo de esta manera, eso es todo lo que veo.
if(Optional.ofNullable(obj).isPresent()){
}
Básicamente, es para dar la ilusión de que maneja los valores nulos de manera más efectiva.
Ya hay varios recursos sobre esta característica:
- ¿Cansado de las excepciones de puntero nulo? Considere el uso de Java SE 8 opcional
- Tipo de opción : "un tipo polimórfico que representa la encapsulación de un valor opcional"
- Java 8 Opcional: Cómo usarlo
- El diseño de opcionales
- Java monádica
- Procesando datos con Java SE 8 Streams
Optional
clase Optional
permite evitar el uso null
y brindar una mejor alternativa:
Esto alienta al desarrollador a realizar comprobaciones de presencia para evitar las
NullPointerException
no detectadas.La API se documenta mejor porque es posible ver, dónde esperar los valores que pueden estar ausentes.
Optional
proporciona una API conveniente para seguir trabajando con el objeto: isPresent()
; get()
; orElse()
; orElseGet()
; orElseThrow()
; map()
; filter()
; flatmap()
.
Además, muchos marcos usan activamente este tipo de datos y los devuelven desde su API.