¿Por qué debería aprender sobre nulo en Java?
Porque si no le prestas atención a null, puedes estar seguro de que Java te hará sufrir terriblementejava.lang.NullPointerExceptiony aprenderás la lección, pero irás por el camino más difícil. Escribir código resistente a fallas es un arte y su equipo, clientes y usuarios lo apreciarán. En mi experiencia, una de las razones principales NullPointerExceptiones la falta de conocimiento sobre nulos en Java. Muchos de ustedes ya están familiarizados con null, el resto podrá aprender algunas cosas nuevas y antiguas sobre la palabra clave null. Repasemos o aprendamos algunas cosas importantes sobre nulo en Java.
¿Qué es nulo en Java?
Como dije, nulo es un concepto muy, muy importante en Java. Originalmente se inventó para indicar la ausencia de algo, como la ausencia de un usuario, un recurso o lo que sea, pero ha estado desconcertando a los programadores de Java con muchosnull pointer exception. En este tutorial, aprenderemos los datos básicos sobre la palabra clave nula en Java y aprenderemos algunos trucos para evitar problemas null pointer exceptionsy minimizar las comprobaciones de nulos.
-
Lo primero es lo primero, nulo es una palabra clave en Java, al igual que
publico . Las mayúsculas y minúsculas son sensibles, no puede escribir nulo como Nulo o NULL, el compilador no lo reconocerá y se generará un error.staticfinalObject obj = NULL; // Not Ok Object obj1 = null //OkEsto lo encuentran a menudo los programadores que han cambiado de otros lenguajes de programación, pero cuando utilizan IDE modernos, el problema se vuelve insignificante. Hoy en día, los IDE como Eclipse o NetBeans pueden corregir este error mientras escribes, pero en la era del Bloc de notas, Vim y Emacs, este era un problema común que podía consumir mucho tiempo valioso.
-
Так же, Cómo каждый примитив имеет significado по умолчанию, например, у
intэто 0, у boolean это false, null это significado по умолчанию любых ссылочных типов, проще говоря, для всех un objetoов. Так же, Cómo при создании логической переменной ее significado по умолчанию равно false, так и любые ссылочные переменные в Java по умолчанию будут равны null. Это истинно для всех типов переменных: переменной-члена o локальной переменной, переменной экземпляра o статической переменной, кроме того, компилятор будет ругаться, если Вы используете локальную переменную не проинициализировав ее.private static Object myObj; public static void main(String args[]){ System.out.println("What is value of myObjc : " + myObj); } What is value of myObjc : nullЭто истинно Cómo для статических, так и для не статических un objetoов, Cómo Вы можете видеть здесь, я сделал
myObjстатической ссылкой, так что я могу использовать ее непосредственно в методеmain, который является статическим методом и не позволяет обращаться к не статическим переменным изнутри. -
Несмотря на распространенное заблуждение, null это не un objeto (
Object) и ни тип. Это просто специальное significado, которое может быть назначено любому ссылочному типу, и Вы можете привести null к любому типу, Cómo показано ниже:String str = null; // null can be assigned to String Integer itr = null; // you can assign null to Integer also Double dbl = null; // null can also be assigned to Double String myStr = (String) null; // null can be type cast to String Integer myItr = (Integer) null; // it can also be type casted to Integer Double myDbl = (Double) null; // yes it's possible, no errorКак Вы можете видеть, приведение null к любому ссылочному типу пройдет успешно Cómo во время компиляции, так и во время выполнения программы. В отличии от того, что многие из Вас возможно подумали, это не приведет к выбрасыванию
NullPointerException. -
null может быть назначен только ссылочному типу, Вы не можете назначить null примитивной переменной вроде
int,double,floatoboolean. Компилятор выразит Вам свое недовольство если Вы сделаете Cómo показано ниже:int i = null; // type mismatch : cannot convert from null to int short s = null; // type mismatch : cannot convert from null to short byte b = null: // type mismatch : cannot convert from null to byte double d = null; //type mismatch : cannot convert from null to double Integer itr = null; // this is ok int j = itr; // this is also ok, but NullPointerException at runtimeКак Вы можете видеть, когда мы непосредственно присваиваем null примитиву, то получаем ошибку процесса компиляции, но, если присвоить null un objetoу класса-обертки, а затем присвоить этот un objeto соответствующему примитивному типу, компилятор не отреагирует, но мы будем вознаграждены
null pointer exceptionво время выполнения. Это происходит из-за авто упаковки (autoboxing) в Java, и мы еще встретимся с ним в следующем пункте. -
Любой класс-обертка со significadoм null будет выбрасывать
java.lang.NullPointerExceptionкогда Java распакует(unbox) его в примитивную переменную. Некоторые программисты делают ошибку допуская, что авто упаковка(autoboxing) позаботится о конвертации null в significado по умолчанию для соответствующего примитивного типа, например, 0 дляint, false дляbooleanи т.д., но это не верно, в чем можно убедиться ниже:Integer iAmNull = null; int i = iAmNull; // Remember - No Compilation ErrorНо, когда Вы запустите данный фрагмент códigoа, в консоли Вы увидите
Exception in thread "main" java.lang.NullPointerExceptionЭто часто происходит при работе с
HashMapиInteger key. Выполнение códigoа, показанного ниже прервется, Cómo только Вы его запустите.import java.util.HashMap; import java.util.Map; /** * An example of Autoboxing and NullPointerExcpetion * * @author WINDOWS 8 */ public class Test { public static void main(String args[]) throws InterruptedException { Map numberAndCount = new HashMap<>(); int[] numbers = {3, 5, 7,9, 11, 13, 17, 19, 2, 3, 5, 33, 12, 5}; for(int i : numbers){ int count = numberAndCount.get(i); numberAndCount.put(i, count++); // NullPointerException here } } }
Output: Exception in thread "main" java.lang.NullPointerException at Test.main(Test.java:25)Este código parece muy simple e inofensivo. Simplemente cuenta cuántas veces aparece un número en una matriz, una técnica clásica para encontrar duplicados. El desarrollador toma la cantidad contada anteriormente, la aumenta en uno y la vuelve a insertar en
Map. Podría pensar que el auto-boxing se encargará de la conversiónIntegeraint, como lo hace cuando se llama al métodoput(), pero olvida que si el número aún no ha sido contado, el métodoget()devolveráHashMapnulo, no cero, porque el valor predeterminado es un número entero, esto es nulo, no 0, y el boxeo automático se produciránull pointer exceptional intentar convertir un número entero en una variableint. -
El operador
instanceofdevolverá falso si se especifica como parámetro cualquier variable de referencia con el valor nulo o nulo. Ejemplo:Integer iAmNull = null; if(iAmNull instanceof Integer){ System.out.println("iAmNull is instance of Integer"); }else{ System.out.println("iAmNull is NOT an instance of Integer"); }
Output : iAmNull is NOT an instance of IntegerEsta es una propiedad importante del operador
instanceofque lo hace útil para probar conversiones de tipos. -
Usted sabe que no puede llamar a un método no estático en una variable de referencia nula, llamará
NullPointerException, pero es posible que no sepa que puede llamar a un método estático en una variable de referencia nula. Porque Los métodos estáticos utilizan enlaces estáticos, no se desechanNullPointerException. He aquí un ejemplo:public class Testing { public static void main(String args[]){ Testing myObject = null; myObject.iAmStaticMethod(); myObject.iAmNonStaticMethod(); } private static void iAmStaticMethod(){ System.out.println("I am static method, can be called by null reference"); } private void iAmNonStaticMethod(){ System.out.println("I am NON static method, don't date to call me by null"); } }
Output: I am static method, can be called by null reference Exception in thread "main" java.lang.NullPointerException at Testing.main(Testing.java:11) -
Puede pasar null como parámetro a un método que acepte cualquier tipo de referencia, por ejemplo:
public void print(Object obj)se puede llamar como
print(null)Esto es normal desde el punto de vista del compilador, pero el comportamiento posterior depende completamente del método. Un método seguro para nulos no arrojará
NullPointerException, sino que simplemente saldrá con gracia. Si la lógica empresarial lo permite, se recomienda escribir métodos seguros para nulos. -
Puede comparar nulos usando los operadores
==(igual) y!=(no igual), pero no puede usarlo con otros operadores aritméticos o lógicos como<(menor que) o>(mayor que). A diferencia de SQL, Javanull == nulldevolverá verdadero como se muestra a continuación:public class Test { public static void main(String args[]) throws InterruptedException { String abc = null; String cde = null; if(abc == cde){ System.out.println("null == null is true in Java"); } if(null != null){ System.out.println("null != null is false in Java"); } // classical null check if(abc == null){ // do something } // not ok, compile time error if(abc > null){ } } }
Output: null == null is true in Java
NullPointerException, podrá hacer que su código sea seguro. Porque null puede tratarse como un valor vacío o no inicializado, lo que suele ser fuente de confusión, por lo que es importante documentar el comportamiento de un método cuando se ingresa un valor nulo. Recuerde siempre que nulo es el valor predeterminado de las variables de referencia y no puede llamar a métodos de instancia ni acceder a variables de instancia utilizando una referencia nula en Java.
GO TO FULL VERSION