I have a very simple Java code, like this (this is just an excerpt):
for(;;)
{
AnObject object = null;
for(AnObject elem : list) // where the list is of the type List<AnObject>
{
if(<some dynamic condition goes here>)
{
object = elem;
}
}
Log.v(TAG, object.property); // was initially omitted, added for the answer
// more code skipped for simplicity
if(object == null)
{ //
break; //
} // this all is marked as dead code
}
In Eclipse, the fragment with comments is marked as a dead code. Why? There is no final elements in the condition. The object variable is not assigned anywhere to constant null, except for the very beginning of the cycle, after which it should be normally overriden, but it does not happen always. The object can very well be null and non-null.
Am I missing something?
The Answer
Well, I found the answer, and to show it I must add one line of code to my example, which I omitted by accident when tried to simplify the code excerpt, but it is important. The line is:
Log.v(TAG, object.property);
So the object must be non-null, otherwise the code unreachable by exception. This line was added temporary for debugging purposes, which is why it was out of my consideration.
I can't reproduce that warning in eclipse.
Could it be that you accidently forgot some piece of code in your original question which might lead to a situation where no code behind it is executed. As you marked the complete if statement as dead code and not just its body, this seems to be the case. That missing line could be something that actually uses object (probably as simple as a logging statement where you try to access one of object's properties).
Even if the if condition is not marked as dead, its body might still be. Either object is not null (and the if body would not be executed) or – if object is null – a NullPointerException would be thrown in that missing line so that the execution stops there.
Can't reproduce with the following program:
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
public class Test {
public static void main(String[] args) {
for(;;)
{
List<Object> list = new LinkedList<Object>();
Object object = null;
for(Object elem : list)
{
if(new Date().getSeconds() % 3 == 0)
{
object = elem;
}
}
if(object == null)
{
break;
}
}
}
}
This is Eclipse 3.7.2 with Java SE 1.7
Because, if list is null (in your code there's no init for list), you won't ever initialize Object.
My Trashtalk, my bad.
If the inner 'if' always go false, the dead code could be marked inside it.
If the elements are null, the comparisson in the end still applies.
If you return before your dead code block, it will raise an unreachable code error.
As others say, couldn't replicate it.
Related
This question already has answers here:
java.lang.NullPointerException is thrown using a method-reference but not a lambda expression
(2 answers)
Closed 3 years ago.
I work with some legacy code that goes back decades and has a lot of objects where a field being null means "we don't have that information". As such, it has a lot of methods where it wants to do some math on fields, but only if they are not null. This leads to many ugly if statements that look like a procession of null checks, and happen multiple times per method for various length sets of things that can't be null if the contents are going to be used.
For example
public class Foo
{
public Bar getBar()
{
//returns a Bar object that may or may not be null
}
}
Then, elsewhere
if(foo1 != null && foo1.getBar() != null && foo2 != null && .... etc) {
//do math with foo1.getBar(), foo2.getBar(), etc...
}
Anywho, I made a utility to help make these look a little nicer (and also quiet down SonarQube about too many checks in an if) by making a utility class that looks like this:
public class NullCheckUtil
{
private NullCheckUtil()
{}
public static Boolean anyNull(Object... objects)
{
return Stream.of(objects).anyMatch(Objects::isNull);
}
}
Then realized that if foo1 is null, will get NullPointerException before even going in the anyNull.
Ok, lets make it a stream, so they are not evaluated on declaration:
public static Boolean anyNull(Supplier<Object>.... suppliers)
{
return Stream.of(suppliers).map(Supplier::get).anyMatch(Objects::isNull);
}
Then if check can be
if(!NullCheckUtil.anyNull(foo1, foo1::getBar, foo2, foo2::getBar,.... etc){//do the math}
And my IDE seemed happy with that, no problems. But when I ran from console, I'd get NPE with the error claiming to be on the if line again. Whaaaa?
So I did some digging and at first thought maybe this is the reason:
Does Java's ArrayList.stream().anyMatch() guarantee in-order processing?
So I changed the anyNull again to
public static Boolean anyNull(Supplier<Object>... suppliers)
{
for(Supplier<Object> supplier : suppliers)
{
if(supplier == null || supplier.get() == null)
{
return true;
}
}
return false;
}
NOPE, still doesn't fix it (for console).
Experimenting to see what could do it I changed the if to
if(!NullCheckUtil.anyNull(()->foo1, ()->foo1.getBar(), ()->foo2, ()->foo2.getBar(), etc...)
And that works fine in IDE and also in console. Tried both in Java 8.151 and Java 8.221, same behavior.
In other words
try
{
NullCheckUtil.anyNull(()->foo1, ()->foo2, ()->foo1.getBar(), ()->foo2.getBar());
}
catch(NullPointerException npe)
{
//does not happen
}
try
{
NullCheckUtil.anyNull(()->foo1, ()->foo2, foo1::getBar, foo2::getBar);
}
catch(NullPointerException npe)
{
// *DOES* happen. What tha….?
}
So there is some difference between ()->obj.method() and obj::method lambdas in that the latter gets interpreted right away on declaration? What is that?
If the Objects you want to check are always Foo, then you can rewrite the method to:
public static boolean isAnyFooNullOrReturnsAnyGetBarNull(final Foo... foos) {
return Stream.of(foos)
.map(foo -> Objects.IsNull(foo) || Objects.isNull(foo.getBar()))
.reduce(false, Boolean::logicalOr);
}
Ideone example
Notice that this example uses an immutable class Foo. This property is essential since this guarantees that Foo::getBar() for a certain instance will always return the same Bar. If this property is not given, then the problem is not solvable in a streamified solution.
This is also the reason why the attempt of using a Producer<Bar> will not work: the first call to a producer could return a non-null value, while the second call will return a null value. Some classes behave this way, i.e. they allow only a single consumption of a resource/property.
If the parameter of the method has to be Object..., then the problem is not solvable with Streams.
Found older 100% applicable and correct answer after modifying the search terms (i had tried earlier with no luck): java.lang.NullPointerException is thrown using a method-reference but not a lambda expression
It even answers why Eclipse is behaving "nice" (Eclipse bug).
In my code, I am making a lot of checks for null so that I don't get a NullPointerException usually i am just doing like this:
if(variable != null){
//do something with the variable
}
Is the following better in any way or is it just a matter or personal belief?
if( !variable.equals(null) ){
//do something with the variable
}
Is there a more efficient way to make this check?
Btw I do have done my research already but I cant seem to find concrete evidence to prove either point.
P.S This is a NOT duplicate of Avoiding != null statements, on that the best answer is that you should either use Assert, which cannot be used to run code rather than just display a message, or actually throw the exception which I dont want either. This post is addressing a different issue of the same subject.
if(!variable.equals(null) ){
//do something with the variable
}
If variable is null NPE occurs. First method is far better.
EDIT:
Using Optional:
Consider that you have Person object and want to getSalary(). Unfortunately age can be null - in that case you want default value. You can do Integer salary = Optional.ofNullable(person.getSalary()).orElse(2000). It will return salarty from person or 2000 in case salary is null.
Or you can use java.util.Optional from Java 8.
Very nice examples are on JavaCodeGeeks.
Optional is usually used in java.util.stream lambdas for "functional-style operations".
As others already said, the variant
if(!variable.equals(null))
can NPE itself when variable is null. Furthermore, you have to be sure that the equals method also is null-safe for all object types you use. Thus, if you absolutely need to check, use ==.
As for better solutions (we're going opinion-based here): I think that this ecessive null-checking is a sign of brittle software and suboptimal interface definition. What I currently try to do more and more is use the javax.validation annotation #NotNull to harden my interfaces and get rid off all these runtime checks:
private #NotNull String getName() {...} // guaranteed not to return null
...
if(getName() == null) { // superfluos, your IDE gives a shout if configurd correctly
...
}
... give it a shot :)
Edit (as an answer to the comment, as I need code-formatting):
Here's a complete cut&paste-example from my current eclipse setup:
package stuff;
import javax.validation.constraints.NotNull;
public class Try3 {
public #NotNull String getName() { return ""; }
public void test() {
if(getName() == null)
System.out.println("Cannot happen due to contract");
}
}
Ensure, that the imported type is indeed javax.validation.constraints.NotNull (as other frameworks also have a NotNull annotation, which may be defined in a different way). For eclipse, you also have to check "Enable annotation-based null analysis" in the project settings under JavaCompiler / Errors/Warnings and customize the annotations to use, as eclipse defaults to some home-brewed annotations. The customization can be accessed via the link "Configure" after the checkbox for using default annotations in the same settings page. Hope that helps!
There are two approaches:
public void calculate(Class variable) {
Assert.notNull(variable, "variable was null");
//calculations
}
//and
if (variable == null) {
//bad
} else {
calculate(variable);
}
The second one is the most common one. If your variable is a String consider using Guava.StringUtils with it's fantastic isBlank method which checks if the String is null or ""
Summarizing:
if (variable == null) {
//bad
} else {
//good
}
The above is standard approach. The better approach will be:
private boolean isNull(Class variable) {
return variable == null;
}
if (isNull(variable)) {
} else {
}
I used to do call the below method all the time which checks for nullpointer exception
public static boolean isAvailable(Object data) {
return ((data!=null) && (data.toString().trim().length() > 0));
}
I am currently facing an issue with my code and I can't figure out why this statement is evaluating as it is. This is the first time I am using a finally block, so it may be that there is some fundamental behaviour I haven't understood.
What this method does is it gets a json document from an api and stores said document as this.thisPage. Then another method sliceItem does the splitting of the results field into an array of json objects.
A MalformedJsonException is thrown whenever the API returns a json that has bad fields (ex. String fields being stored as int, or int as double etc.). This is tried 10 times (handled by failsafeget) and if it failed 10 times, MalformedJsonException (RuntimeException) is thrown. What I would like slicePage to do in that case is get the next page instead of continuing with this page. To simplify this - each page has 100 entries; if the offset 3500 is broken, we want to get offset 3600.
The issue that I am facing currently is that resp always evaluates to null in the final block. I cannot understand why this is the case, since the try block can return something other than null (JSONObject type).
Any help would be greatly appreciated and if you need more information/code, I am willing to provide it.
public synchronized void slicePage(){
JSONObject resp=null; // otherwise java complains that not initialised
ApiClient apiClient = new ApiClient();
RestEndPoint pageUrl;
while (true) {
pageUrl = getNextPageEndPoint();
if(pageUrl == null) {
throw new IllegalStateException("We have reached the end and the code isn't designed to handle the end here"); // we have reached the end
}
currentPageNumber++;
try {
resp = apiClient.failSafeGet(pageUrl, getRetryCount());
break;
}
catch (MalformedJsonException e) {
logger.info(String.format("The json was still broken after %d retries. Skipping this page and notifying listeners", getRetryCount()));
for (Consumer<Integer> consumer: onSkipListenerList) {
consumer.accept(batchSize); // inform each listener that we are skipping this many entries
}
}
finally { // We need to set the next page end point no matter the outcome of the try catch. N.B. this gets executed even if there is a break
if(resp == null) {
// no next possible
setNextPageEndPoint(null); // don't consider next; we reached the max
this.thisPage = null;
} else {
if(currentPageNumber > maxPages - 1) {
// because a request has been made already, so reduce by 1
setNextPageEndPoint(null); // don't consider next; we reached the max
} else {
// else consider next page
setNextPageEndPoint(constructNextPageEndPoint(pageUrl, resp));
}
this.thisPage = this.parseResult(resp);
setTotalCount(resp.getInt("totalResults"));
}
}
}
}
EDIT I forgot to mention, that when I said it always evaluates to null, I meant that my IDE - Intellij IDEA, is warning me that the if condition always evaluates to null. The following is the help that shows up in Intellij (with Ctrl-F1).
Condition 'resp == null' is always 'true' less... (Ctrl+F1)
This inspection analyzes method control and data flow to report possible conditions that are always true or false, expressions whose value is statically proven to be constant, and situations that can lead to nullability contract violations.
Variables, method parameters and return values marked as #Nullable or #NotNull are treated as nullable (or not-null, respectively) and used during the analysis to check nullability contracts, e.g. report possible NullPointerException errors.
More complex contracts can be defined using #Contract annotation, for example:
#Contract("_, null -> null") — method returns null if its second argument is null #Contract("_, null -> null; _, !null -> !null") — method returns null if its second argument is null and not-null otherwise #Contract("true -> fail") — a typical assertFalse method which throws an exception if true is passed to it
The inspection can be configured to use custom #Nullable
#NotNull annotations (by default the ones from annotations.jar will be used)
EDIT 2
As it turns out, the code analysis is wrong, the value is non-null once run. Thank you everyone (including commentators) for sharing your insights and advice. Ultimately I inserted a logger.info with the value before the condition and everything seemed to work. The reason it seemed to stop working is because the graph server was running into timeouts.
This is normal behaviour. This call
apiClient.failSafeGet(pageUrl, getRetryCount());
throws the exception, so the value assignment to resp is never completed so in the finally block the value is null. So, either you method is always throwing an exception, or, if not, it is returning null at some point.
In your code:
try {
resp = apiClient.failSafeGet(pageUrl, getRetryCount());
break;
}
catch (MalformedJsonException e) {
logger.info(String.format("The json was still broken after %d retries. Skipping this page and notifying listeners", getRetryCount()));
for (Consumer<Integer> consumer: onSkipListenerList) {
consumer.accept(batchSize); // inform each listener that we are skipping this many entries
}
}
finally {.....
If resp = apiClient.failSafeGet(pageUrl, getRetryCount()); throws an exception, resp will be always null, because the program failed before assing the instance to resp.
Following code:
public void test()
{
#Nullable T first = null;
Graph<T> cycleG = new Graph<>();
ArrayList<Graph<T>> segments = GraphFactory.makeSegments(this, cycleG);
Graph<T> seg = segments.get(0);
for (T v : cycleG.vertices)
{
if (seg.hasVertex(v))
{
if (first == null) // redundant null check here
{
first = v;
}
}
}
assert first != null;
}
gives me a "redundant null check" warning at the indicated line. "T" is a type parameter, the class definition is
public class Graph<T extends Comparable<T>> implements IGraph
Is this a bug? A known one? Or am I overlooking something. Any tips on avoiding it?
Note: this code does not make sense, it is just a small subset that reproduces the problem. Using 'first' after the loop does not remove the warning.
This is java 8, Eclipse Luna 4.4.1.
This looks like a case of Eclipse bug 467482.
Sometimes the code analysis warnings like this do have false positives, particularly in tricky loops, but a small tweak to the code can cause such false warnings to evaporate. Alternatively, decorating the method with #SuppressWarnings("null") will shut it up.
I am currently implementing cross-referencing for my Xtext dsl. A dsl file can contain more then one XImportSection and in some special case an XImportSection does not necessariely contain all import statements. It means I need to customize the "XImportSectionNamespaceScopeProvider" to find/build the correct XimportSection. During the implementation I figured out an unexpected behavior of the editor and/or some validation.
I used the following dsl code snipped for testing my implementation:
delta MyDelta {
adds {
package my.pkg;
import java.util.List;
public class MyClass
implements List
{
}
}
modifies my.pkg.MyClass { // (1)
adds import java.util.ArrayList;
adds superclass ArrayList<String>;
}
}
The dsl source code is described by the following grammar rules (not complete!):
AddsUnit:
{AddsUnit} 'adds' '{' unit=JavaCompilationUnit? '}';
ModifiesUnit:
'modifies' unit=[ClassOrInterface|QualifiedName] '{'
modifiesPackage=ModifiesPackage?
modifiesImports+=ModifiesImport*
modifiesSuperclass=ModifiesInheritance?
'}';
JavaCompilationUnit:
=> (annotations+=Annotation*
'package' name=QualifiedName EOL)?
importSection=XImportSection?
typeDeclarations+=ClassOrInterfaceDeclaration;
ClassOrInterfaceDeclaration:
annotations+=Annotation* modifiers+=Modifier* classOrInterface=ClassOrInterface;
ClassOrInterface: // (2a)
ClassDeclaration | InterfaceDeclaration | EnumDeclaration | AnnotationTypeDeclaration;
ClassDeclaration: // (2b)
'class' name=QualifiedName typeParameters=TypeParameters?
('extends' superClass=JvmTypeReference)?
('implements' interfaces=Typelist)?
body=ClassBody;
To provide better tool support, a ModifiesUnit references the class which is modified. This Xtext specific implementation enables hyperlinking to the class.
I am currently working on customized XImportSectionScopeProvider which provides all namespace scopes for a ModifiesUnit. The default implemantation contain a method protected List<ImportNormalizer> internalGetImportedNamespaceResolvers(EObject context, boolean ignoreCase) assumes that there is only one class-like element in a source file. But for my language there can be more then one. For this reason I have to customize it.
My idea now is the following implementation (using the Xtend programming language):
override List<ImportNormalizer> internalGetImportedNamespaceResolvers(EObject context, boolean ignoreCase) {
switch (context) {
ModifiesUnit: context.buildImportSection
default: // ... anything else
}
}
Before I startet this work, the reference worked fine and nothing unexpected happend. My goal now is to build a customized XImportSection for the ModifiesUnit which is used by Xbase to resolve references to JVM types. To do that, I need a copy of the XImportSection of the referenced ClassOrInterface. To get access to the XImportSection, I first call ModifiesUnit.getUnit(). Directly after this call is executed, the editor shows the unexpected behaviour. The minimal implementation which leads to the error looks like this:
def XImportSection buildImportSection(ModifiesUnit u) {
val ci = u.unit // Since this expression is executed, the error occurs!
// ...
}
Here, I don't know what is going internally! But it calculates an error. The editor shows the follwoing error on the qualified name at (1): "Cyclic linking detected : ModifiesUnit.unit->ModifiesUnit.unit".
My questions are: What does it mean? Why does Xtext show this error? Why does it appear if I access the referenced object?
I also figured out a strange thing there: In my first approach my code threw a NullPointerException. Ok, I tried to figure out why by printing the object ci. The result is:
org.deltaj.scoping.deltaJ.impl.ClassOrInterfaceImpl#4642f064 (eProxyURI: platform:/resource/Test/src/My.dj#xtextLink_::0.0.0.1.1::0::/2)
org.deltaj.scoping.deltaJ.impl.ClassDeclarationImpl#1c70366 (name: MyClass)
Ok, it seems to be that this method is executed two times and Xtext resolves the proxy between the first and second execution. It is fine for me as long as the received object is the correct one once. I handle it with an if-instanceof statement.
But why do I get two references there? Does it rely on the ParserRule ClassOrInterface (2a) which only is an abstract super rule of ClassDeclaration (2b)? But why is Xtext not able to resolve the reference for the ClassOrInterface?
OK, now I found a solution for my problem. During I was experimenting with my implementation, I saw that the "Problems" view stil contained unresolved references. This was the reason to rethink what my implementation did. At first, I decided to build the returned list List<ImportNormalizer directly instead of building an XImportSection which then will be converted to this list. During implementing this, I noticed that I have built the scope only for ModifiesUnitelements instead of elements which need the scope within a ModifiesUnit. This is the reason for the cyclic linking error. Now, I am building the list only if it is needed. The result is that the cyclic linking error occurs does not occur any more and all references to JVM types are resolved correctly without any errors in the problems view.
My implementation now looks like this:
class DeltaJXImportSectionNamespaceScopeProvider extends XImportSectionNamespaceScopeProvider {
override List<ImportNormalizer> internalGetImportedNamespaceResolvers(EObject context, boolean ignoreCase) {
// A scope will only be provided for elements which really need a scope. A scope is only necessary for elements
// which are siblings of a JavaCompilationUnit or a ModifiesUnit.
if (context.checkElement) { // (1)
return Collections.emptyList
}
// Finding the container which contains the import section
val container = context.jvmUnit // (2)
// For a non null container create the import normalizer list depending of returned element. If the container is
// null, no scope is needed.
return if (container != null) { // (3)
switch (container) {
JavaCompilationUnit: container.provideJcuImportNormalizerList(ignoreCase)
ModifiesUnit: container.provideMcuImportNormalizerList(ignoreCase)
}
} else {
Collections.emptyList
}
}
// Iterates upwards through the AST until a ModifiesUnit or a JavaCompilationUnit is found. (2)
def EObject jvmUnit(EObject o) {
switch (o) {
ModifiesUnit: o
JavaCompilationUnit: o
default: o.eContainer.jvmUnit
}
}
// Creates the list with all imports of a JCU (3a)
def List<ImportNormalizer> provideJcuImportNormalizerList(JavaCompilationUnit jcu, boolean ignoreCase) {
val is = jcu.importSection
return if (is != null) {
is.getImportedNamespaceResolvers(ignoreCase)
} else {
Collections.emptyList
}
}
// Creates the list of all imports of a ModifiesUnit. This implementation is similar to
// getImportedNamespaceResolvers(XImportSection, boolean) // (3b)
def List<ImportNormalizer> provideMcuImportNormalizerList(ModifiesUnit mu, boolean ignoreCase) {
val List<ImportNormalizer> result = Lists.newArrayList
result.addAll((mu.unit.jvmUnit as JavaCompilationUnit).provideJcuImportNormalizerList(ignoreCase))
for (imp : mu.modifiesImports) {
if (imp instanceof AddsImport) {
val decl = imp.importDeclaration
if (!decl.static) {
result.add(decl.transform(ignoreCase))
}
}
}
result
}
// Creates an ImportNormalizer for a given XImportSection
def ImportNormalizer transform(XImportDeclaration decl, boolean ignoreCase) {
var value = decl.importedNamespace
if (value == null) {
value = decl.importedTypeName
}
return value.createImportedNamespaceResolver(ignoreCase)
}
// Determines whether an element needs to be processed. (1)
def checkElement(EObject o) {
return o instanceof DeltaJUnit || o instanceof Delta || o instanceof AddsUnit || o instanceof ModifiesUnit ||
o instanceof RemovesUnit
}
}
As one can see, elements which do not need namespaces for correct scopes, will be ignored (1).
For each element which might need namespace for a correct scope the n-father element which directly contains the imports is determined (2).
With the correct father element the namespace list can be calculated (3) for JCU's (3a) and MU's (3b).