I gotta make an array of method in Java because I have to call methods in a loop and the method called depends to the value of a figure (for example if figure is equal to 8, it's assert8(), etc...) I can do it in a simple if else if statement but it's not going to be clean.
So i wrote this :
boolean assertionsArray[] = {assert0(), assert1(), assert2(), assert3(), assert4(),
assert5(), assert6(), assert7(), assert8(), assert9()};
and now I'm searching to make that if my figure is 2, I call assertionsArray[2] etc...
Thank you !
What you've got is not an array of methods, it is an array of booleans. Each method is called at the moment the array is created, and the return values of these ten methods become values in the array.
If you would like to make an array of something that you can call, make an array of interface implementations that have a method returning boolean. The way you do this depends on the version of Java. Prior to Java 8, you would do it like this:
interface Predicate {
boolean test();
}
Predicate[] assertionsArray = new Predicate[] {
new Predicate() {public boolean test() {return assert0(); }}
, new Predicate() {public boolean test() {return assert1(); }}
, new Predicate() {public boolean test() {return assert2(); }}
...
, new Predicate() {public boolean test() {return assert9(); }}
};
Now you can call the assertions like this:
if (assertionsArray[figureIndex].test()) {
...
}
Starting with Java 8 you can use the predicate interface included with Java, and use lambdas instead of anonymous implementations:
Predicate<Object>[] assertionsArray = new Predicate<Object>[] {
o -> assert0(), o -> assert1(), o -> assert2(), o -> assert3(),
, o -> assert4(), ...
};
...
if (assertionsArray[figureIndex].test(null)) {
...
}
If you do this:
assert0();
You will call that method and the return value of that method comes into boolean array, which is not what you want.
When you want to call a method in an array, you are looking at the reflection package, however this is very, very bad practise to do. I am not going to provide sample code of that as that is not helping you.
As #Dragan pointed out, you are much better of using a switch statement, such as:
switch( figureNumber ) {
case 0: assert0(); break;
case 1: ... ; // etc
}
Putting aside that you cannot do that in java versions lower than 8, you'll be much better off calling a single method that can handle various input.
You provided sparse code, so I'm going to take a shot in the dark here and suggest a switch statement perharps.
What you are doing here will result in an array of boolean, with the results from all your assertX() methods, at the time of array creation.
What you are trying to do here reminds me of function pointers in C, which AFAIK is not possible in Java.
Consider this alternative;
Have one method called: assertByIntArgument(int n) which calls the appropriate assertX() method, based on the argument n
Something like this:
private boolean assertByInt(int n){
switch(n){
case 1: return assert1(); break;
case 2: return assert2(); break;
// ...
}
}
With Java 8, you could have the following:
Supplier<Boolean> assertionsArray = {
SomeClass::assert0(),
SomeOtherClass::assert1(),
SomeClass::assert2(),
SomeClass::assert3(),
SomeClass::assert4(),
SomeClass::assert5(),
SomeClass::assert6(),
SomeClass::assert7(),
SomeClass::assert8(),
this::assert9()
};
Then, in a loop or somewhere else:
boolean result = assertionsArray[i].get();
This answer is more of a 'as a matter of interest' than a real solution. The best solution in non-Java 8 environment is probably a switch. Another lead would have been reflection, as presented below, but please be aware that:
it is less efficient and performant;
it leaves your IDE (and compiler) blind and hinders you when navigating your code;
too much reflection makes code just impossible to read.
Use at your own risk.
If you want to stick to several methods though, you could use reflection.
If your methods are declared in MyClass, invoking a no-arg method would be the following:
MyClass.class.getDeclaredMethod("assert" + i).invoke();
If you need to pass arguments (let's say an int and a String), update to the following:
MyClass.class.getDeclaredMethod("assert" + i, int.class, String.class).invoke(3, "Hello");
Related
In most cases when an object is optional, it is possible to use Guava to help in if null checks. But in cases where the statement is used to decide if the method is going to return earlier (from what I experienced) even that is not enough.
My question regards the use of nested if-statements to return a default value instead of continuing with the method execution.
Here's an example of what I mean:
private MyObject myMethod(Object object, Object object1, Object object2) {
/* inherent implementations for first if-statement... */
if (object == null) {
/* inherent implementations for second if-statement... */
if (object1 == null) {
return new MyObject();
}
/* inherent implementations for third if-statement... */
if (object2 == null) {
return new MyObject();
}
} else {
/*same structure shown in if-statement...*/
}
/* inherent implementations before last return statement... */
return new MyObject(/* with args */);
}
I am looking for a solution that solves the problems of cognitive complexity indicated sonarQube in which the amount of 'if' and nested 'if' statements used in the method increments the complexity of the code.
In other words, ways to extract the statements from the method into another method or solving them through other ways that don't involve if-statements.
EDIT(05/09): First, thanks for all of the answers provided, but I believe there's a bit of a detail I forgot to mention. Each of the /* implementations... */ that are mentioned in the code snippet I provided have some type of functionality that must be fulfilled before the next if-statement so suggestions like if (object1 == null || object2 == null) are a no-go. About the suggestion of using Java 9's Optional.or: from what I heard, Java 8 is the currently most stable version of Java so worst case scenario I would wind up having to wait for Java 11. Also each of the /* implementations... */ mentioned have to be executed in in order, so in order to make each of those details more explicit I have reworked a bit of the code snippet I provided earlier.
The answers from clean code perspective:
Don't go with so many arguments. It sounds silly first, but: the real answer is to design interfaces that take as few parameters as possible. So, instead of passing a, b, c as parameters one could create a class around them. Which gives you more options to think about default values, and so on.
Of course, early returns are possible as well.
Your code says same structure as shown in if statement. Then the simple solution is to do
if (object1 == null) return new MyObject();
if (object2 == null) return new MyObject();
once, before any other code. The point is to avoid the nesting of conditions. And when you just repeat conditions, then put them in a different place and avoid the repetition.
To check if some of your parameters are null you can create a method like that :
public boolean hasNull(Object... objects) {
return Arrays.stream(objects).anyMatch(Objects::isNull);
}
Now you can check as much as parameters you want :
private MyObject myMethod(Object object, Object object1, Object object2, Object object3, Object object4) {
if (hasNull(object1, object2, object3, object4)) {
return new MyObject();
}
/* implementations... */
return new MyObject(/* with args */);
}
In this question the author uses the following example:
#Override
public final OptionalInt max() {
return reduce(Math::max); //this is the gotcha line
}
So in this case it looks as if max() is a proxy for Math.max on the instance of this class. However there are no arguments passed to max, so does java 8 compile this to something like (Pseudo code):
#Override
public final OptionalInt max(Integer a, Integer b) {
//If neither a or b are null
return new OptionalInt.of(Math.max(a,b));
//Otherwise return empty because we can't compare the numbers
return OptionalInt.empty()
}
Also how would one write the javadoc for something like this?
So in this case it looks as if max() is a proxy for Math.max on the instance of this class. However there are no arguments passed to max, so does java 8 compile this to something like (Pseudo code):
#Override
public final OptionalInt max(Integer a, Integer b) {
//If neither a or b are null
return new OptionalInt.of(Math.max(a,b));
//Otherwise return empty because we can't compare the numbers
return OptionalInt.empty()
}
Not quite :). Let's start by figuring out what the reduce operator actually does. The documentation explains that it performs a reduction on a sequence of numbers by applying an algorithm that is logically equivalent to the following:
public OptionalInt reduce(IntBinaryOperator op) {
boolean foundAny = false;
int result = 0;
for (int element : [this stream]) {
if (!foundAny) {
foundAny = true;
result = element;
}
else {
result = op.applyAsInt(result, element);
}
}
return foundAny ? OptionalInt.of(result)
: OptionalInt.empty();
}
Seems simple enough. If you can tell it how to take two numbers and 'reduce' or 'combine' them into one, then reduce knows how to extend that logic to reduce an entire sequence into a single number. It handles the edge cases and the aggregation for you. All it needs from you is a function that takes in two numbers and gives it one back. That function should conform to the functional interface IntBinaryOperator.
A functional interface is an interface that is meant to describe a single function. Specifically, it describes the argument types and the return type. The rest is largely superfluous. The signature for an IntBinaryOperator looks like this:
int applyAsInt(int left, int right);
You can provide a function that conforms to this specification in several ways. Prior to Java 8, you might have done something like this:
stream.reduce(
new IntBinaryOperator() {
public int applyAsInt(int a, int b) {
return b > a ? b : a;
}
}
);
Java 8 gives us a shorthand form for functional interfaces called lambda expressions. These are a bit more concise, and while they are conceptually similar to anonymous inner classes, they're not quite the same thing.
stream.reduce((a, b) -> b > a ? b : a);
Both functions above are equivalent: they take in two numbers and return the larger of the two. As it turns out, every standard programming library has a function that does exactly the same thing. In Java, that function is Math.max. So rather than writing this logic myself, I can delegate to Math.max:
stream.reduce((a, b) -> Math.max(a, b));
But wait! All reduce wants is a function that takes two numbers and returns one. Math.max does that, so do I even need to wrap it in a lambda? It turns out I don't; I can tell reduce to just call Math.max directly:
stream.reduce(Math::max);
This says "I know you want a function, so I'm show you by name where to find one that's already been written". The compiler knows that Math.max conforms to the (int, int) -> int specification we need, so it emits some bytecode telling the VM how to 'bootstrap' it once it's needed. When the JVM hits your call to reduce, it calls a special method that generates a wrapper class implementing IntBinaryOperator that delegates to Math.max in its implementation of applyAsInt. It only performs this 'bootstrapping' step once. Since calling Math.max doesn't rely on anything other than the two numbers that get passed in, it can cache that implementation and use it the next time you wind up on this code path.
Pre Java 8, this would have been written as:
public MyMathInteface {
OptionalInt max(Integer a, Integer b);
}
public static final MyMathInterface reducing = new MyMathInterface() {
#Override
public OptionalInt max(Integer a, Integer b) {
return OptionalInt.of(Math.max(a, b));
}
};
#Override
public final OptionalInt max() {
return reduce(reducing);
}
Then reduce would be defined as:
public static OptionalInt reduce(MyMathInteface toReduce) {
return toReduce.max(someValueA, someValueB);
}
So to answer your question, no arguments are passed to Math::max, because those values are retrieved by the reduce function. They could be constants or they could be retrieved from some other place.
In any case, the use of the max method in this way is called a method reference, that is where you do SomeObject::method. That :: operator creates a method reference. It returns a function, but does not call the function. The user (reduce) is responsible for calling the function.
if you have any suggestions on how to modify the question title in order to be more descriptive, please feel free to say so .
Suppose you have a class method that returns an Object, is there a best practice or standard way of where to create the object within the method ? To clarify, see below :
public MyCustomObject myMethod(String arg1, String arg2){
try{
if (something){
...
} else {
...
}
} catch ( SomeException e ){
...
} catch ( SomeOtherException e ){
...
}
return myCustomObject;
}
MyCustomObject has an empty constructor, a constructor with 5 fields and getters/setters. I need to return a valid MyCustomObject in every case of the (simplified) flow above. Please do not focus on the control flow itself.
I think that I can either :
a) Initialize a variable of type MyCustomObject with null in the beginning of the method. Assign a new MyCustomObject to it for every different case in the control flow. Return it in the end.
b) Instantiate a MyCustomObject in the beginning by using the empty constructor. Modify the object with the setters for each of the cases in the flow.
Can you think of reasons why one of the above or a different way is preferable ?
Thanks
I prefer option 3 which you didn't mention: Create a new MyCustomObject for every different case in the control flow, and return it immediately. No variable required, usually:
if (foo) {
return new MyCustomObject("foo");
}
if (bar) {
return new MyCustomObject("x", "y");
}
// etc
This usually ends up with less nesting, and it's easier to read, in that as soon as you hit the return statement, you're done.
Some people hold on to the dogma of only having a single exit point, but I regard that as somewhat pointless these days - it made sense in languages where you needed to do clean-up before returning, but with garbage collection and finally blocks for other resource clean-up, it's unnecessary.
If you return as soon as you can, you can often end up with less nesting within the code - which greatly increases readability.
so either:
MyCustomObject result = null;
if (something) {
result = new MyCustomObject(a, b, c, d, e);
} else {
result = new MyCustomObject(a, b, x, y, z);
}
Or
MyCustomObject result = new MyCustomObject();
if (something) {
result.Name = arg1;
} else {
result.Phone = arg2;
}
return result;
?
I can't really see why I should pick one over the other! I would probably use B to make sure I didn't forget initializing the result... but that's hardly a good reason I think.
In my work, I personally prefer the first method (i.e., declaring your return variable, assigning it to null, and then allowing the actual logic of the program to instantiate an appropriate object as needed).
The reason I find this more useful is because wherever you're calling the method from probably wants to know if something went wrong in the creation of the object, or whether a useful one was created at all. It's much easier to perform a null check than to try to figure out if an instantiated object is a dummy object. You'll find that null checking is usually a huge part of the control flow of a complex program. If I always return an object, regardless of what happens, my checker will have to be more complicated.
For example, let's say I have a method called readItem() which returns a custom Item object. In this readItem(), it goes and fetches some data from a table and populates the Item with it. Now, let's say nothing goes wrong in the processing of readItem() that warrants throwing an exception, but the criteria for the Item we want read simply isn't in the table (for example, maybe we have supplied an item ID for which no item exists or something). Then if I return an instantiated Item rather than null, this is much harder to figure out.
Option 1:
MyCustomObject myCustomObj = null;
for( index > list of cases ){
myCustomObj = myMethod(param1, param2);
}
Perfect : You are declaring the variable once and modifying the value.
Option 2:
for( index > list of cases ){
MyCustomObject myCustomObj = myMethod(param1, param2);
}
Good : You are redeclaring the variable again and again and modifying the value.
Option 3:
MyCustomObject myCustomObj = new MyCustomObject();
for( index > list of cases ){
myCustomObj = myMethod(param1, param2);
}
Bad : You are wasting memory in the first line , because the reference is nowhere used.But still causes no harm
I have a Java method something like this
public boolean ReadBool(String ValueName, Boolean Value)
{
boolean Retval = ...;
...
Value = true;
...
return bRetval;
}
that I call from native code (C++) like this:
jMethodID MethodId = pEnv->GetMethodID(ClassId, "ReadBool", "(Ljava/lang/String;Ljava/lang/Boolean;)Z");
// What goes instead of "??" ?
bool bOk = pEnv->CallBooleanMethod(myobject, MethodId, pEnv->NewStringUTF("Value1"), "??");
My intention is for the Java method to "return" a boolean value in Value. I understand that a built-in boolean will not work for this purpose. Is it possible to do this with a Boolean wrapper? How does one construct the object to pass in place of "??" ?
I have googled around, but some questions remain. For example, I suppose I could pass an object created by calling Boolean's <init> "method". But wouldn't the assignment in the Java ReadBool make Value refer to a newly created wrapper, throwing away that first object? In that case I would have called <init> for nothing. I think it should be possible to create (in the native code) something that Java sees as an object that is null and whose type is Boolean. Is that possible? Or am I on the wrong track altogether?
Booleans are immutable in Java, so you need your own wrapper class, which can be really simple though:
public class BooleanWrapper {
public boolean val;
// public is fine here imo, but you can obviously use [g|s]etters as well
}
Or if you don't want this, we can use a.. well not really pretty, but nice to know hack:
public void hack(boolean[] vals) {
vals[0] = true; // voila, now you change the value itself
}
Has some obvious drawbacks when calling (and looks strange), but if you're fine with keeping a specific parameter sequence, you can do:
public void hack(boolean.. vals) {
vals[0] = true; // voila, now you change the value itself
}
that way the caller doesn't have to use stuff like new boolean[] {};
You can obviously cheat and change the internal state of the Boolean object itself, but that will have unwanted consequences (booleans are cached ergo if you change the Boolean.TRUE instance to false internally this will give interesting results). So don't do that.
I have a recursive algorithm which steps through a string, character by character, and parses it to create a tree-like structure. I want to be able to keep track of the character index the parser is currently at (for error messages as much as anything else) but am not keen on implementing something like a tuple to handle multiple returned types.
I tried using an Integer type, declared outside the method and passed into the recursive method, but because it's final, recursive call increments are "forgotten" when I return. (Because the increment of the Integer value makes the passed-by-value object reference point at a new object)
Is there a way to get something similar to work which won't pollute my code?
Since you've already discovered the pseudo-mutable integer "hack," how about this option:
Does it make sense for you to make a separate Parser class? If you do this, you can store the current state in a member variable. You probably need to think about how you're going to handle any thread safety issues, and it might be overkill for this particular application, but it might work for you.
It's kind of a hack, but sometimes I use an AtomicInteger, which is mutable, to do things like this. I've also seen cases where an int[] of size 1 is passed in.
The current solution I am using is:
int[] counter = {0};
and then pass it to the recursive algorithm:
public List<Thing> doIt (String aString, int[] counter) { ... }
and when I want to increment it:
counter[0]++;
Not super elegant, but it works...
Integers are immutable, which means that when you pass it as an argument it creates a copy rather than a reference to the same item. (explanation).
To get the behavior you're looking for, you can write your own class which is like Integer only mutable. Then, just pass it to the recursive function, it is incremented within the recursion, and when you access it again after the recursion is over it will still maintain its new values.
Edit: Note that using an int[] array is a variation on this method... In Java, arrays are also passed by reference rather than copied like primitives or immutable classes.
You could just use a static int class variable that gets incremented each time your doIt method is called.
You could also do:
private int recurse (int i) {
if (someConditionkeepOnGoing) {
i = recurse(i+1);
}
return i;
}
To be honest I would recode the function to make it a linear algorithm that uses a loop. This way you have no chance of running out of heap space if you are stepping through an extremely large string. Also, you would not need to have a the extra parameter just to keep track of the count.
This also would probably have the result of making the algorithm faster because it does not need to make a function call for every character.
Unless of course there is a specific reason it needs to be recursive.
One possibility I can think of is to store the count in a member variable of the class. This of course assumes that the public doIt method is only called by a single thread.
Another option is to refactor the public method to call a private helper method. The private method takes the list as a parameter and returns the count. For example:
public List<Thing> doIt(String aString) {
List<Thing> list = new ArrayList<Thing>();
int count = doItHelper(aString, list, 0);
// ...
return list;
}
private int doItHelper(String aString, List<Thing> list, int count) {
// ...
// do something that updates count
count = doItHelper(aString, list, count);
// ...
return count;
}
This assumes that you can do the error handling in the public doIt method, since the count variable isn't actually passed back to the caller. If you need to do that, you could of course throw an exception:
public List<Thing> doIt(String aString) throws SomeCustomException {
List<Thing> list = new ArrayList<Thing>();
int count = doItHelper(aString, list, 0);
// ...
if (someErrorOccurred) {
throw new SomeCustomException("Error occurred at chracter index " + count, count);
}
return list;
}
It's difficult to know whether that will help without knowing more about how your algorithm actually works.