Necesito distinguir entre una propiedad que tiene un valor nulo y una propiedad que no existe en absoluto. Podría usar un mapa, pero por razones de rendimiento, intento usar una matriz de tamaño fijo.
En la matriz, podría usar null para indicar cuándo una propiedad no existe en absoluto. Pero, para una propiedad que existe y tiene un valor nulo, ¿existe una forma estándar de representarla en una matriz?
Pensé en mantener un miembro estático, por ejemplo
class MyClass { private static final Object NULL = new Object(); // null wrapper private Object[] m_arr = new Object[10]; // 'i' represents the index of a property in the array boolean exists(int i) { return m_arr[i] != null; } Object value(int i) { if( !exists(i) ) throw new NullPointerException(); // does not exist if( m_arr[i] == NULL ) return null; // ... handling for other data types ... } }¿Otra posibilidad de representar nulo podría ser una enumeración?
class MyClass { ... enum Holder { NULL } ... // to check for a null value use m_arr[i] == Holder.NULL }NO... pero Java ahora tiene Optional , que podría verse como lo mismo. También puede crear una clase para representar un objeto nulo, lo que se puede hacer siguiendo el "Patrón de objeto nulo". Escribí sobre esto en un blog: https://www.professorfontanez.com/2020/04/the-beauty-of-null-object-pattern.html
Utilice Opcional , por ejemplo
private Optional<String> myField;Hay tres estados. He aquí cómo manejarlos:
myfield = Optional.of("foo"); // attribute has non-null value myfield = Optional.empty(); // attribute is present, but null myfield = null; // attribute is not present La deserialización json de Jackson (es decir, Spring boot) es compatible con esto desde el primer momento, lo cual es muy útil para manejar métodos PATCH que requieren la distinción entre una clave json especificada pero nula y no especificada.
Apache commons ObjectUtils tiene un campo NULL para este propósito, si no desea definir el suyo propio.
¿Java tiene un tipo de contenedor para Null?
No.
Pero cómo resolvería este problema significa que no necesita un contenedor: solo mantenga un conjunto de índices que representen valores nulos "explícitos".
class MyClass { private Object[] m_arr = new Object[10]; private Set<Integer> presentButNullIndices = new HashSet<>(); // 'i' represents the index of a property in the array Object value(int i) { if (m_arr[i] == null && !presentButNullIndices.contains(i)) { throw new NullPointerException(); } // ... handling for other data types ... } // just an example of how to maintain the set void insert(int i, Object value) { if (value == null) { presentButNullIndices.add(i); } else { presentButNullIndices.remove(i); } m_arr[i] = value; } } En el peor de los casos, la complejidad del espacio se duplica, pero eso es solo para clientes que hacen un uso intensivo de valores nulos. contains en un conjunto es O(1)
También consideraría simplemente prohibir valores nulos en primer lugar. Algunas implementaciones de mapas hacen eso y nunca me he encontrado en una situación en la que desearía que no lo hicieran.