How can I annotate my helper method so Eclipse knows its argument is non null if it returns true?

流过昼夜 提交于 2020-01-24 05:41:05

问题


I have a helper method, hasContent(String), which returns true iff its argument is both non-null and contains at least one non-whitespace character. I have just enabled null analysis in Eclipse and I have found that when I use this method to execute a block of code which is conditional on the result of my helper function indicating that the string has content (and therefore cannot be null), that nonetheless Eclipse complains that my String might still be null.

The helper function

public static boolean hasContent(String text) {
    if (text == null)
        return false;
    if (text.trim().length() == 0)
        return false;
    return true;
}

Example of use

...
String dataString;

try {
    dataString = readStringFromFile("somefile.txt");
} catch (IOException e) {
    System.err.println("Failed to read file due to error: " + e);
    dataString = null;
}

// At this point dataString may be null

if (hasContent(dataString)) {

    // At this point dataString must be non-null, but Eclipse warns:
    // "Potential null pointer access: The variable dataString may be null at this location"
    // at the following reference to dataString

    System.out.println("Read string length " + dataString.length());
}
...

What is the best practice for this situation? I don't want to suppress the warning if I can avoid it. I'd prefer to tell Eclipse that if hasContent() returns true then it's argument is definately non-null. Is this possible? If so, how?


回答1:


The contract of your method is that if hasContent returns true, then its argument is guaranteed to be non-null.

Eclipse cannot express or check this contract at compile time, at least without changing your code and degrading its style.

The Nullness Checker is a different tool that can express and check this contract at compile time. It does so without requiring you to change your code. You simply add the @EnsuresNonNullIf annotation your code:

@EnsuresNonNullIf(expression="#1", result=true)
public static boolean hasContent(String text) { ...

The Nullness Checker is distributed with the Checker Framework. There is an Eclipse plugin that enables you to run the Nullness Checker within Eclipse.




回答2:


It might not be the best practice, but: If an IOException is thrown, you can return false, or simply set a variable to false. If not, you can set the variable to true (in the try-block).

try {
    dataString = readStringFromFile("somefile.txt");
    hasContent = true;
} catch (IOException e) {
    System.err.println("Failed to read file due to error: " + e);
    hasContent = false;
}



回答3:


I cannot see a way to do exactly what you are attempting.

You could modify hasContent to return the string it is passed, rather than the a boolean and throw an Exception if the argument is null or empty. You would then annotate the function with @NonNull. This would however compromise your calling code in a way that I suspect you would not like since it would have to use try/catch logic rather than an if.

This would make the hasContent function:

@NonNull
public static String hasContent(String text) throws Exception {
    if (text == null)
        throw new Exception( "Null string" );
    if (text.trim().length() == 0)
        throw new Exception( "Empty string" );
    return text;        
}

and the calling code:

...
try {
    dataString = readStringFromFile("somefile.txt");
} catch (IOException e) {
    System.err.println("Failed to read file due to error: " + e);
    dataString = null;
}

// At this point dataString may be null
try {
    dataString = validateHasContent( dataString );
    // At this point dataString must be non-null

    System.out.println("Read string length " + dataString.length());
} catch( Exception e ) {        
}
...

If you were prepared to make this compromise then a dedicated exception would clearly be better.



来源:https://stackoverflow.com/questions/43611344/how-can-i-annotate-my-helper-method-so-eclipse-knows-its-argument-is-non-null-if

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!