I am trying to abstract some common checks for an Android library and add Nullability annotations at the same time but I am getting a warning.
Let's say I have an example method in this library:
public int method(#Nullable final String param) {
final int precheckResult = LibPrechecks.checkForMethod(param); // Does check for param not being null
if (LibPrechecks.checksFailed(precheckResult)) {
return precheckResult;
}
// Rest of logic
return internalMethod(param); // IDE is complaining that param cannot be null
}
That then calls another internal method of the library for some processing:
private int internalMethod(#NonNull String param) {
// processing logic
return 0;
}
And here is an example "precheck" class:
public class LibPrechecks {
public static int checkForMethod(#Nullable final String param) {
if (param == null) {
return -1;
}
return 0;
}
public static boolean checksFailed(final int precheckResult) {
return precheckResult < 0;
}
}
I am returning an error code upon a null so I know it's safe and non-null by the time the internal method is called with the param, but the IDE is still unhappy and thinks the param could be null. How would I fix the warning in Android Studio and do this properly?
The IDE doesn’t know what checkForMethod() or checksFailed() do, so you need to either suppress the warning or write some code that the IDE can statically analyze to prove that param is not null.
I think the best thing to do would be to assert that param is not null after the precheck code is done running. Either
assert param != null;
or
if (param == null) throw new AssertionError();
will work.
Related
hi I'm rewriting a java code in C# and I'm stuck here:
public void printSolveInstructions() {
System.out.print(getSolveInstructionsString());
}
public String getSolveInstructionsString() {
if (isSolved()) {
return historyToString(solveInstructions);
} else {
return "No solve instructions - Puzzle is not possible to solve.";
}
}
public List<LogItem> getSolveInstructions() {
if (isSolved()) {
return Collections.unmodifiableList(solveInstructions);
} else {
return Collections.emptyList();
}
}
I know how to rewrite the first two methods (it's for referencing the last one) but I don't know the equivalent for Collections.unmodifiableList() and Collections.emptyList()
solveInstructions is of type List here's the declaration in java and C#:
private ArrayList<LogItem> solveInstructions = new ArrayList<LogItem>() // java
private List<LogItem> solveInstructions = new List<LogItem>() // c#
update
I rewrote the getSolveInstructions() method in this way:
public List<LogItem> getSolveInstructions()
{
if (isSolved())
{
return solveInstructions.AsReadOnly();
}
else
{
return new List<LogItem>();
}
}
Now the problem is ide gives me an error when I use .AsReadOnly()
Your method returns either a List<LogItem>, or an IReadOnlyCollection<LogItem> (produced by call to List<T>.AsReadOnly() method; however, your return type is List<LogItem>, which is incompatible with the IReadOnlyCollection<LogItem>. Change your method return type to IList<LogItem>, which works for both types.
Note, since this method can return either a read-only or a read-write list, calling code should check the returned collection's IsReadOnly property, before attempting to modify it.
In my program I receive a message from a call, that has a variable of the type Optional and depending on whether something is inside of this variable or not I shall make a call of a method with a parameter or a call to the same method without a parameter, standard overloading.
The problem I am having is that the produced code becomes ugly, especially the more optionals I receive the more distinguishing the method call becomes. Currently the next method call is determined via an if-else.
Here is a simplified code for this question, first the Message Class:
public class FooMessage {
public Optional<String> receivedMessage;
public FooMessage(String message) {
this.receivedMessage = Optional.ofNullable(message);
}
}
and then the Main class:
public class Main {
public static FooMessage receiveMessageWithNull(){
return new FooMessage(null);
}
public static FooMessage receiveMessage(String s){
return new FooMessage(s);
}
public static void fooMethod() {
System.out.println("Message == null");
}
public static void fooMethod(String message) {
System.out.println("Message != null");
}
public static void main(String[] args) {
//Calls that return a Message either with content or without
FooMessage message = receiveMessage("foo");
FooMessage messageWithNull = receiveMessageWithNull();
//Resolving which version of the overloaded method to call
if (message.receivedMessage.isPresent()) {
fooMethod(message.receivedMessage.get());
} else {
fooMethod();
}
if (messageWithNull.receivedMessage.isPresent()) {
fooMethod(messageWithNull.receivedMessage.get());
} else {
fooMethod();
}
}
}
My question is if there is a possibility to clean the code up in a way that the method call itself is written to resolve the checks currently done in the if statements. I was thinking about something like:
fooMethod(message.receivedMessage.isPresent() ? message.receivedMessage.get() : ... );
Instead of ... there would be something that told the method to ignore the parameter.
Note: I cannot change fooMethod. I have to resolve which version of fooMethod has to be called in the calling method.
If you need to execute the method only if the Optional value is present, and you do not care for an absent value, you may go with
message.receivedMessage.ifPresent(Main::fooMethod);
I would avoid passing the Optional to a method that then distinguishes whether the value is present, but you can implement a support function that would hide the implementation details
private static void distinguish(String s) {
if (s == null) fooMethod();
else fooMethod(s);
}
and cal it via
distinguish(message.receivedMessage.orElse(null));
This is an acceptable way of using Òptional::orElse.
From the docs:
/**
* Return the value if present, otherwise return {#code other}.
*
* #param other the value to be returned if there is no value present, may
* be null
* #return the value, if present, otherwise {#code other}
*/
public T orElse(T other) {
return value != null ? value : other;
}
I would personally just stick with if (optional.isPresent()) as this is what optionals are intended for, so I wouldn't worry too much.
I have a class that extends org.apache.ant.tools.Task. This class has 5 variables which are set via public setters:
private String server;
private String username;
private String password;
private String appname;
private String version;
private String file;
And then there is a public execute() method which is invoked by ant:
public void execute() throws BuildException {
checkArgs()
... // my execute code goes here
}
Before execute runs, I want to check that none of my required variables are null and, if so, throw a BuildException() describing the problem, so the user back in ant has some idea what's wrong:
private void checkArgs() {
if (server == null) {
throw new BuildException("server cannot be null.");
}
if (username == null) {
throw new BuildException("username cannot be null.");
}
if (password == null) {
throw new BuildException("password cannot be null.");
}
if (file == null) {
throw new BuildException("file cannot be null.");
}
if (version == null) {
throw new BuildException("version cannot be null.");
}
}
Is there a less verbose way to do this? I hate the repeated use of if like this and if there's a more efficient way to do it, I'd love to see it. I can just imagine how it would look if I had, say, 20 different variables I need to check before execute() can run.
What is a good method for validating large numbers of different variables as a precursor continuing code execution or throwing a useful error message?
You could store the args in a HashMap<String, String> argMap, mapping the argument names to their values. Adjust your getters/setters accordingly. Then:
for (String key : argMap.keySet()) {
if (argMap.get(key) == null) {
throw new BuildException(key + " cannot be null.");
}
}
A little improvement could be achieved by using asserts:
public void execute()
throws BuildException
{
assert server!=null : "server cannot be null";
assert version!=null : "version cannot be null";
...
}
... And then running ant always with the -ea JVM option (Enable Asserts).
Yes, you still have to code one assert by variable, but at least it would be just one line per one of them.
If you prefer not to add the Map (as in Claudiu answer), you could use reflection:
private void checkArgs() throws BuildException, IllegalAccessException {
for (Field field: this.getClass().getDeclaredFields()) {
if (field.get(this) == null) {
throw new BuildException(field.getName() + " cannot be null.");
}
}
}
but pay attention: the getDeclaredFields() will return all the fields of the class (either private, protected or public).
hi guys I already searched a lot but weren't really satisfied with what I found. hope it's the right place to ask this question.
I'm doing Java now for a small amount of time (changed from C) and have problems of getting a grip of how to structure my code best for OOP.
let's give a simple example:
If I'm using some predefined strings (let's say e.g. filepaths or error messages) I'm currently creating an own class doing something like:
private static final String libPath = "\\this\\is\\a\\path\\";
private static final String notFoundMessage = "This hasn't been found";
public static String getLibPath() {
return libPath;
}
public static final String getNotFoundMessage() {
return notFoundMessage;
}
...
Would it be better to create a Map, add everything to it and get it by key?
Or am I doing it completely wrong?
Second example:
let's say I return an error string somewhere
public String getSomething() {
if (something != null) {
return something;
} else {
//handle error, return string below
}
return "I HAVE AN ERROR";
}
And anywhere else in my program I'm checking for the return value:
if (!string.equals("I HAVE AN ERROR")) {
//do something
}
else {
// handle error
}
that's obviously a bad way having to change the code twice once the error message changes. and yeah, I could define the error string the same way I'm doing it in the first example but as I'm not satisfied with that one either I'm reaching a dead end.
would be glad to hear some of your suggestions how to properly do OOP !
First example :
private static final String libPath = "\\this\\is\\a\\path\\";
private static final String notFoundMessage = "This hasn't been found";
public static String getLibPath() {
return libPath;
}
public static final String getNotFoundMessage() {
return notFoundMessage;
}
...
In this case, no need to create a Map. That is the right way to do it. Just note that the libPath would be better defined like this :
private static final Path libPath = Paths.get("this", "is", "a", "path");
(The class Path exists since Java 7, current version is Java 8)
Second example:
public String getSomething() {
if (something != null) {
return something;
} else {
//handle error, return string below
}
return "I HAVE AN ERROR";
}
No : Never return error codes in Java. Prefer using an exception.
Example :
public class ElementNotFoundException extends Exception {
...
}
public String getSomething() {
if (something == null) {
throw new ElementNotFoundException();
} else {
return something;
}
}
Then, you handle the exception like this :
try {
myObject.getSomething();
} catch(ElementNotFoundException e) {
//handle error
}
For the first example, take a look at Internationalization: http://docs.oracle.com/javase/tutorial/i18n/
You can use statics or maps, but sooner or later you will need to show the messages in several languages.
For the second example, it's better to use Exceptions as they are intended to be used when an abnormal condition (like an error) happens.
Anyway, with Exceptions take care not to use it as flow control structures: Why not use exceptions as regular flow of control?
Here are some examples for handling constants throug out your code:
1. Class
public final class MyConstants {
public static final int ERROR_CODE = -1;
}
if (getSomething() == MyConstants.ERROR_CODE) {
// ...
}
2. Interface
public interface MyConstantsHolder {
int ERROR_CODE = -1;
}
public MyClass implements MyConstantsHolder {
public void myMethod() {
if (getSomething() == ERROR_CODE) {
// ...
}
}
}
This is the code of the method that I want to simplify. The method name I call of SerializedExpFamMixture class is exactly the value of "model", my question is how to assign the value of "model" directly as the name of the method instead of using "if" to determine which method I should call. Since by using "if", I need to list all the possible values of "model" and judge which method I should use.
Thank you very much for help. I am new to java.
public static SerializedExpFamMixture RateMtxModel(String model)
{
SerializedExpFamMixture result=new SerializedExpFamMixture();
if(model=="kimura1980()")
result=SerializedExpFamMixture.kimura1980();
if(model=="accordance()")
result=SerializedExpFamMixture.accordance();
if(model=="pair()")
result=SerializedExpFamMixture.pair();
return result;
}
One way you can approach this is to use Reflection:
Method method = myClass.getClass().getMethod("doSomething", null);
method.invoke(myClass, null);
Since you are new to Java, it's time for some general pointers:
In Java, we usually name our methods with camelCase, so the first letter is lower case.
Also, in Java we usually leave the opening curly-bracket on the same line as the code (no newline).
Always use final on your variables. At least your parameters. That way you won't overwrite it, and thus won't have to try to figure out which value it actually has at runtime.
Use curly-brackets! Please!
The result variable is not actually needed.
Use the equals-method to compare Strings.
If you only want one result, use else-if
Fixing these things, your method looks like this:
public static SerializedExpFamMixture rateMtxModel(String model) {
if (model.equals("kimura1980()")) {
return SerializedExpFamMixture.kimura1980();
} else if (model.equals("accordance()")) {
return SerializedExpFamMixture.accordance();
} else if(model.equals("pair()")) {
return SerializedExpFamMixture.pair();
}
return new SerializedExpFamMixture();
}
Next, let's look at what you are actually trying to do here. You want to pass some Strings around, and use them as a basis for creating objects. And now, with the advice given here, you will do this using reflection. This does not sound like a very good idea to me. Say you were to go through with this, and this happened:
rateMtxModel("kinura1980");
Small typo, hard to spot, will give unexpected results. If you were actually calling a method the compiler would let you know that you messed up, now you will get no warning (btw did you see both errors in that method call?). The same if someone were to delete the accordance()-method, the compiler would not alert them that this will break the program.
If it was up to be I would just use the static factory-methods in SerializedExpFamMixture directly, but if you have to do it like this (if the task at hand is using a String input to create an object) I would do something like this:
public enum Something {
KIMURA1980("kimura1980()"),
ACCORDANCE("accordance()"),
PAIR("pair()");
private final String stringValue;
private Something(final String stringValue) {
this.stringValue = stringValue;
}
public static Something fromString(final String string) {
for (final Something something : values()) {
if (something.stringValue.equals(string)) {
return something;
}
}
return null;
}
}
public static SerializedExpFamMixture rateMtxModel(final String model) {
if (model == null) {
throw new IllegalArgumentException("model is null!");
}
final Something something = Something.fromString(model);
if (something == null) {
return new SerializedExpFamMixture();
}
switch(something) {
case KIMURA1980:
return SerializedExpFamMixture.kimura1980();
case ACCORDANCE:
return SerializedExpFamMixture.accordance();
case PAIR:
return SerializedExpFamMixture.pair();
default:
return new SerializedExpFamMixture();
}
}
This way, the one place where you will use the Strings is in the enum, the rest of the code will use the enum constants and thus have the safety of the compiler to rely on.
One could also leave the linking between operation and String to the enum, like this:
interface Operation<T> {
public T run();
}
public enum Something {
KIMURA1980("kimura1980()", new Operation<SerializedExpFamMixture>() {
public SerializedExpFamMixture run() {
return SerializedExpFamMixture.kimura1980();
}
}) ,
ACCORDANCE("accordance()", new Operation<SerializedExpFamMixture>() {
public SerializedExpFamMixture run() {
return SerializedExpFamMixture.accordance();
}
}),
PAIR("pair()", new Operation<SerializedExpFamMixture>() {
public SerializedExpFamMixture run() {
return SerializedExpFamMixture.pair();
}
}),
DEFAULT(null, new Operation<SerializedExpFamMixture>() {
public SerializedExpFamMixture run() {
return new SerializedExpFamMixture();
}
});
private final String stringValue;
private final Operation<SerializedExpFamMixture> operation;
private Something(final String stringValue, final Operation<SerializedExpFamMixture> operation) {
this.stringValue = stringValue;
this.operation = operation;
}
public static Something fromString(final String string) {
if (string != null) {
for (final Something something : values()) {
if (string.equals(something.stringValue)) {
return something;
}
}
}
return DEFAULT;
}
public SerializedExpFamMixture getCorrespondingSerializedExpFamMixture() {
return operation.run();
}
}
With this setup in the enum (I think the Operation-part can be trimmed out with Java8), the method will be as simple as:
public static SerializedExpFamMixture rateMtxModel(String model) {
return Something.fromString(model).getCorrespondingSerializedExpFamMixture();
}
Use reflection, but you need to consider a few things:
Bug alert! Comparing Strings using == doesn't work as expected in java - use .equals() instead. However, the solution below bypasses that problem
For the general case, which includes methods not visible to the invoker, you need to consider accessibility, both in finding the method and invoking it
You don't need the result variable, and even if using your code, don't need to initialize it
Try this:
String methodName = model.replace("(", "").replace(")", "");
try {
// getMethod() returns only public methods, getDeclaredMethod() returns any visibility
Method method = SerializedExpFamMixture.class.getDeclaredMethod(methodName);
// if the method is not guaranteed to be visible (eg public) you need this:
method.setAccessible(true);
return (SerializedExpFamMixture) method.invoke(null); // how to invoke on the class object
} catch (Exception forBrevity) {
return new SerializedExpFamMixture();
}