I'm employing a private lib. One of the objects has a method that delivers either a double or a null.
How could I perform:
if (object.method != null) {
// do some numeric operations with the returned value
}
Additional details:
library = org.apache.commons.collections4.map
class = LRUmap
method = get
My code is:
public class ExampleNode extends GeneralNode {
private LRUMap<Integer, Double> cache;
public ExampleNode() {
this.setCache(new LRUMap<Integer,Double>(100));
}
public void setCache(LRUMap<Integer, Double> lruMap) {
this.cache = lruMap;
}
public double getDatumCacheDebug(int llave){
return this.cache.get((Object)llave,false);
}
}
And then I call:
//outside ExampleNode
if ( actualNode.getDatumCacheDebug(k) != null ) {
Eclipse Neon3 says: "The operator != is undefined for the argument type(s) double,null."
When the method returns a primitive double (and not the Double class), it can never be null. A primitive value will always have a value of its type (i. e. you can't do double d = null;).
Thus this check would never return true and the compiler does not allow you to do it.
The signature of the library method is:
public V get(Object key,
boolean updateToMRU)
in class LRUMap<K,V>
The returned value is a Double, and therefore could be null, but it is being unboxed to double before the null test:
public double getDatumCacheDebug(int llave){
return this.cache.get((Object)llave,false);
}
I suggest changing the signature of this method to return Double instead of double, so that the information about whether the result was null is preserved and can be tested. Otherwise, it will throw NullPointerException if get returns null.
A working variant of your code will be:
if (object.method != 0) {
// do some numeric operations with the returned value
}
But it is better practice to refactor your method object.method() to return a specific number for your "null cases"- example: a method that is searching for an index in a list - returns the index number if found and -1 if not found or exception is thrown during the search (a null case for the search)
Related
Suppose I have a method to parse a number and whose return value nullability contract should be inferred from its argument:
#...
public static Integer tryParse(#Nullable final String in, #... final Integer defaultValue) {
if ( in == null ) {
return defaultValue;
}
#Nullable
final Integer out = Ints.tryParse(in); // from Google Guava, does not accept nulls
if ( out == null ) {
return defaultValue;
}
return out;
}
where the #... marks stand for some nullability transition. Having that, I'd also have something like:
final int n = tryParse("foo", 0) (safe in all cases: the n is considered never to have null so unboxing won't cause NullPointerException)
#Nullable final Integer n = tryParse("foo", null) (safe: both hands are null-aware)
final int n = tryParse(someVar, null) (unsafe: may cause an NPE if someVar is not a valid int string representation).
Is there a way to bind the returned value nullability depending on the argument passed to the method parameter nullability, or should I just create an overload with clearly segregated boxed and primitive default values (this might be fine for this case, but primitive types are not the only situation I'd like to handle)?
If it matters: I don't use static analysis tools in my build, but I use the nullability inspections in IntelliJ IDEA (javax.annotation, not org.jetbrains.annotations) with the warning severity set.
I continue to research method emulation and getting actual value when passing instruction ILOAD. After Holger's help with Interpreter
and after adding new operations with local variable in main() method I stucked with merge(V a, V b) method, which must be overriden when extending Interpreter.
#Override
public LocalValue merge(LocalValue valueA, LocalValue valueB) {
if (Objects.equals(valueA, valueB)) return valueA;
else return new LocalValue(basicInterpreter.merge(valueA.type, valueB.type), null);
}
But it seems this not correctly written. I can try different logic vars what to return but without understanding, in what cases values can merge, I can't find that. There is no useful info I tried to find in javadocs and asm-4 tutorial. So, what I need to return, when:
- One value is null, and other is not
- Both values are not null, same type, but different objects (such as 0 and 5)
- Both values are not null, different types
basicInterpreter:
private BasicInterpreter basicInterpreter = new BasicInterpreter();
LocalValue:
public static class LocalValue implements Value {
Object value;
BasicValue type;
public LocalValue(BasicValue type, Object value) {
this.value = value;
this.type = type;
}
#Override public int getSize() {return type.getSize();}
#Override public String toString() {return value == null ? "null" : value.toString();}
#Override
public boolean equals(Object obj) {
if (!(obj instanceof LocalValue)) return false;
LocalValue otherV = (LocalValue) obj;
return Objects.equals(otherV.type, type) && Objects.equals(otherV.value, value);
}
}
Values need to be merged when an instruction can be reached through different code paths, e.g when you have conditionals, loops or exception handlers.
So when the value is the same, regardless of which code path has been taken, you can keep it, otherwise the value is not a predictable constant anymore. So in my code, where null has been used to denote unknown values, it always returns null when the values differ.
So when you have code like
void foo(int arg) {
int i = 1;
int j = arg%2==0? i: arg;
}
The values for arg, i, and the value on the operand stack get merged right before the assignment to j. arg does already have an unpredictable value, i has the value 1 in each code path, but the value on the operand stack, to be assigned to j has different values, 1 or “unknown”, depending on which code path has been taken.
You may decide to maintain a set of possible value, if you like, but when one of the possible values is “unknown”, the result of the merging cold be any value, hence, is “unknown”.
According to the official documentation for the Java Hashtable class (https://docs.oracle.com/javase/7/docs/api/java/util/Hashtable.html), the get() opperation will return one of it's recorded values, if said value has a key that returns true when the parameter is fed into that key's equals() opperation.
So, in theory, the following code should return "Hello!" for both of the Hashtable's get() queries:
public static class Coordinates implements Serializable {
private int ex;
private int why;
public Coordinates(int xCo, int yCo) {
ex = xCo;
why = yCo;
}
public final int x() {
return ex;
}
public final int y() {
return why;
}
public boolean equals(Object o) {
if(o == null) {
return false;
} else if(o instanceof Coordinates) {
Coordinates c = (Coordinates) o;
return this.x() == c.x() && this.y() == c.y();
} else {
return false;
}
}
}
Hashtable<Coordinates, String> testTable = new Hashtable<Coordinates, String>();
Coordinates testKey = new Coordinates(3, 1);
testTable.put(testKey, "Hello!");
testTable.get(testKey); //This will return the "Hello" String as expected.
testTable.get(new Coordinates(3, 1)); //This will only return a null value.
However, get() doesn't work as it's supposed to. It seems to only work if you litterally feed it the exact same object as whatever was the original key.
Is there any way to correct this and get the Hashtable to function the way it's described in the documentation? Do I need to make any adjustments to the custom equals() opperation in the Coordinates class?
To be able to store and retrieve objects from hash-based collections you should implement/oeverride the equals() as well as hashCode() methods of the Object class. In your case, you have overridden the equals() and left the hashCode() method to its default implementation inherited from the Object.
Here is the general contract of the hashCode() method you must consider while implementing it:
Whenever it is invoked on the same object more than once during an execution of a Java application, the hashCode method must consistently return the same integer, provided no information used in equals comparisons on the object is modified. This integer need not remain consistent from one execution of an application to another execution of the same application.
If two objects are equal according to the equals(Object) method, then calling the hashCode method on each of the two objects must produce the same integer result.
It is not required that if two objects are unequal according to the equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hash tables.
And here is an example implementation that is generated from my IDE (as alread mentioned by #Peter in the comment area) which you can modify to suit your requirements:
#Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ex;
result = prime * result + why;
return result;
}
String x = (String) null;
Why there is no exception in this statement?
String x = null;
System.out.println(x);
It prints null. But .toString() method should throw a null pointer exception.
You can cast null to any reference type without getting any exception.
The println method does not throw null pointer because it first checks whether the object is null or not. If null then it simply prints the string "null". Otherwise it will call the toString method of that object.
Adding more details: Internally print methods call String.valueOf(object) method on the input object. And in valueOf method, this check helps to avoid null pointer exception:
return (obj == null) ? "null" : obj.toString();
For rest of your confusion, calling any method on a null object should throw a null pointer exception, if not a special case.
You can cast null to any reference type. You can also call methods which handle a null as an argument, e.g. System.out.println(Object) does, but you cannot reference a null value and call a method on it.
BTW There is a tricky situation where it appears you can call static methods on null values.
Thread t = null;
t.yield(); // Calls static method Thread.yield() so this runs fine.
This is by design. You can cast null to any reference type. Otherwise you wouldn't be able to assign it to reference variables.
Casting null values is required for following construct where a method is overloaded and if null is passed to these overloaded methods then the compiler does not know how to clear up the ambiguity hence we need to typecast null in these cases:
class A {
public void foo(Long l) {
// do something with l
}
public void foo(String s) {
// do something with s
}
}
new A().foo((String)null);
new A().foo((Long)null);
Otherwise you couldn't call the method you need.
Println(Object) uses String.valueOf()
public static String valueOf(Object obj) {
return (obj == null) ? "null" : obj.toString();
}
Print(String) does null check.
public void print(String s) {
if (s == null) {
s = "null";
}
write(s);
}
Many answers here already mention
You can cast null to any reference type
and
If the argument is null, then a string equal to "null"
I wondered where that is specified and looked it up the Java Specification:
The null reference can always be assigned or cast to any reference type (§5.2, §5.3, §5.5).
If the reference is null, it is converted to the string "null" (four ASCII characters n, u, l, l).
As others have written, you can cast null to everything.
Normally, you wouldn't need that, you can write:
String nullString = null;
without putting the cast there.
But there are occasions where such casts make sense:
a) if you want to make sure that a specific method is called, like:
void foo(String bar) { ... }
void foo(Object bar) { ... }
then it would make a difference if you type
foo((String) null) vs. foo(null)
b) if you intend to use your IDE to generate code; for example I am typically writing unit tests like:
#Test(expected=NullPointerException.class)
public testCtorWithNullWhatever() {
new MyClassUnderTest((Whatever) null);
}
I am doing TDD; this means that the class "MyClassUnderTest" probably doesn't exist yet. By writing down that code, I can then use my IDE to first generate the new class; and to then generate a constructor accepting a "Whatever" argument "out of the box" - the IDE can figure from my test that the constructor should take exactly one argument of type Whatever.
This language feature is convenient in this situation.
public String getName() {
return (String) memberHashMap.get("Name");
}
If memberHashMap.get("Name") returns null, you'd still want the method above to return null without throwing an exception. No matter what the class is, null is null.
Print:
Print an object. The string produced by the String.valueOf(Object) method is translated into bytes
ValueOf:
if the argument is null, then a string equal to "null"; otherwise, the value of obj.toString() is returned.
It wil simply return a string with value "null" when the object is null.
This is very handy when using a method that would otherwise be ambiguous. For example: JDialog has constructors with the following signatures:
JDialog(Frame, String, boolean, GraphicsConfiguration)
JDialog(Dialog, String, boolean, GraphicsConfiguration)
I need to use this constructor, because I want to set the GraphicsConfiguration, but I have no parent for this dialog, so the first argument should be null. Using
JDialog(null, String, boolean, Graphicsconfiguration)
is ambiguous, so in this case I can narrow the call by casting null to one of the supported types:
JDialog((Frame) null, String, boolean, GraphicsConfiguration)
public void m1(Integer f) {
...
}
public void m1(Float f) {
...
}
public void main() {
m1(null); // error: the method m1(Integer) is ambiguous for the type Main
m1((Integer) null); // success
}
Given the above example, we can admit in some ways that null is typed. So why do the following lines print true? Sure o1 and o2 both have no value (i.e. null), but they aren't from the same type (Integer vs Float). I firstly thought false would have been printed.
Integer i = null;
Object o1 = (Object) i;
Float f = null;
Object o2 = (Object) f;
System.out.println(o1 == o2); // prints true
// in short:
System.out.println(((Object) ((Integer) null)) == ((Object) ((Float) null))); // prints true
All null values are untyped and are equal. You can pass it to different reference types but it makes no difference for comparison purposes.
It is not the null value which is typed but the reference to the null which can be typed.
A common question is what happens here
class A {
public static void hello() { System.out.println("Hello World"); }
public static void main(String... args) {
A a = null;
a.hello();
System.out.println("a is an A is " + (a instanceof A)); // prints false.
}
}
The compiler sees the type of a as an A so the static method is called. But the value referenced is null and untyped.
The only operations you can perform with null without causing a NullPointerException is to assign or pass it without examining it or comparing it with another reference.
BTW
In short: The compiler will select a method based on the type of the reference, at runtime the execution is based on the class of the object referenced. At runtime null is treated as any type or no type or you get a NullPointerException if you try to dereference it.
"==" in Java checks to see if it is the same instance rather than simply "are they equal?". There is no concept of multiple instances of null in Java. If you compare null to null, you will always receive true regardless of type.
The reason why you cannot then pass null as an argument to a method with the same name as another with different parameter types is because either method could be a candidate to be called without further type context. Rather than guess which one that might be, it correctly indicates an error.
see http://docs.oracle.com/javase/specs/jls/se7/html/jls-4.html#jls-4.1
null belongs to the "null type". The "null type" has only one value - the null.
The null type is a subtype of every reference type. Therefore we can do
Integer i = null;
(Integer)null
In another word, null is a valid value in every reference type.
(Think of a type as a set of values; the types of a value is the sets it belongs to; "subtype" means "subset". )
Given the above example, we can admit that null is NOT typed: when you call m1(null), compiler cannot determine the type of the actual parameter and cannot decide which method to invoke. All nulls are equal and not typed, and so (null==null)==true.
Null does not have a type, but a reference (to null or anything else) has a type. We can declare two reference variables with different types, but the null they refer to is the same thing in both cases:
Integer a = null;
Double b = null;
In your example,
m1((Integer) null);
the compiler uses the type of the reference it is passed to work out which overloaded method to call, not the type of the null value itself.
In your example it proves that the compiler cannot identity the type (of null) and decide which method to call. So you have to explicity give the type. Also null == null will be always true; no matter whatever cast you do it doesnt change or give null a type.This post has a long description on null.