Refactor code with return statements - java

The "if" blocks with checkcustomers are exactly used in other methods in this class, so there is a lot of code dublication for same checks. But I cant also directly extract this checksomethings to one single method because they have return values.
Some good ideas to refactor this code? I just modified this code to simplify here, so dont get caught on minor issues in this code(if any), Basically question is how to a extract a piece of code to a method(because it is dublicated on other methods) when there are many returns in that current method.
public Details getCustomerDetails(){
if(checkifcustomerhasnoboobs){
..worry about it..
return new Details("no");
}
if(checkifcustomerplaytenniswell){
..do find a tennis teacher
return new Details("no cantplay");
}
//...ok now if customer passed the test, now do the some real stuff
//
//
CustomerDetails details= getCustomerDetailsFromSomewhere();
return details;
}

How about this?
public Result checkSomethings() {
if ( checksomething1 ) {
return ResultCheckSomething1;
}
if ( checksomething2 ) {
return ResultCheckSomething2;
}
return ResultCheckNone;
}
public Details getCustomerDetails(){
Result result = checkSomethings();
switch ( result ) {
case ResultCheckSomething1:
return new Details("message1");
case ResultCheckSomething2:
return new Details("message2");
default:
return getCustomerDetailsFromSomewhere();
}
}
The Result... codes would be in an enum.

Maybe something like this?
public Details getCustomerDetails(){
boolean isError = checksomething1() || checksomething2();
String message = checksomething1() ? "message1" : "message2";
return isError ? new Details(message) : getCustomerDetailsFromSomewhere();
}
If you try to avoid call check functions twice just keep it results
public Details getCustomerDetails(){
boolean check1 = checksomething1();
boolean check2 = checksomething2();
String message = check1 ? "message1" : "message2";
return (check1 || check2) ? new Details(message) : getCustomerDetailsFromSomewhere();
}

Replace the returns with assignments to a result variable that remains null until the first assignment to it. Each block could be replaced by a function that returns null if its condition for changing the result is false.
As pointed out in a comment by herman, this only works if null is not a possible result of one of calls.
public Details getCustomerDetails(){
Details result = null;
if(checksomething1){
..error
result = new Details("message1");
}
if(result == null) {
if(checksomething2){
..error
result = new Details("message2");
}
if(result == null){
result = getCustomerDetailsFromSomewhere();
}
return result;
}

I would do this:
public Details getCustomerDetails(){
Details invalidDetails = checkForInvalidCustomer();
if (invalidDetails !=null) {
return (invalidDetails);
}
//...ok now if customer passed the test, now do the some real stuff
//
//
CustomerDetails details= getCustomerDetailsFromSomewhere();
return details;
}
public Details checkForInvalidCustomer() {
if(checkifcustomerhasnoboobs){
..worry about it..
return new Details("no");
}
if(checkifcustomerplaytenniswell){
..do find a tennis teacher
return new Details("no cantplay");
}
// nulls means valid customer
return (null);
}
Basically, for your specific example, I'm using null so that I can differentiate the case where none of the conditions matched, vs either condition matched. That way I can use a single if statement. Now, if you wanted to return null, you would need to modify this solution slightly, perhaps use some constant for flagging the case instead of using null.

Using Java 8, you can refactor into a method that returns an Optional<...> value.
Statements like return x; would be replaced by return Optional.of(x) (assuming x cannot be null). The default return statement at the end would be return Optional.empty().
Then you can use return optional.orElseGet(() -> ...)) to compute the value for the case where none of the original return statements would be reached.

Related

java function to return either False or object

I'm working on a function that will be recursively called in a backtracking scenario. Either the function worked and will return the working list, or it fails and return false. In python, I can write this:
def myfunc(input):
# logic and logic
if fails:
return False
return alist
In java, a function can't return a List or False. I think I can skirt around the problem with (? just for argument sake, I know what I'm returning):
public List<?> myfunc(someType input){
// logic and logic
return res
// empty or special result instead of False.
}
But is there a more elegant way to do this? perhaps try catch? I'm quite fresh in java and would want to know the standard in this case. Thanks.
There are several options:
Using java.util.Optional
public Optional<List> myfunc(someType input){
// logic and logic
if (fail) return Optional.empty();
else return Optional.of(res);
}
Return null
public List myfunc(someType input){
// logic and logic
if (fail) return null;
else return res;
}
Throw exception
public List myfunc(someType input){
// logic and logic
if (fail) throw new RuntimeException("What an interesting case!");
else return res;
}
PS. I would recommend Optional or exception.
You can return a null list on failure.
public static ArrayList<String> GetList()
{
return null;
}

How to break out and return an object from a recursion after meeting a certain condition is met

I have a recusrion function where i want to return the object as soon as certain condition is met . The function looks like this .
GroupNavigationItemSRO getCategorySpecificNavItem(List<GroupNavigationItemSRO> items,String url) {
GroupNavigationItemSRO sro = new GroupNavigationItemSRO();
if(items != null && !items.isEmpty()){
for(GroupNavigationItemSRO item : items) {
if(item.getUrl().equals(url)) {
LOG.info("Found Specific Url");
return item;
}
else
getCategorySpecificNavItem(item.getChildren(),url);
}
}
return null;
}
Now the function returns null and i get why its happening despite meeting the criteria .How to avoid that and end the recursion as soon as the url is found.
What you want to do is stop looking when you've found it, but recurse until you do.
The main problem with your existing code is that the recursive call's return value is ignored. Instead, you want to look at that return value and, if it's not null, return it; you're done:
for(GroupNavigationItemSRO item : items) {
if(item.getUrl().equals(url)) {
LOG.info("Found Specific Url");
return item;
}
else {
GroupNavigationItemSRO itemFromChild = getCategorySpecificNavItem(item.getChildren(),url);
if (itemFromChild != null) {
// Found!
return itemFromChild;
}
}
}

get status of an Arraylist in Java

In my code I write a "Project" object that can contains an Arraylist of "Requirement" objects. I want to write a function that can calculate the status of my Project objects :
1) "Status" can only have 3 values : "todo", "in progress" and "done"
2) If the status of ONE requirement (in the arraylist) is "todo", the final status of the project is "todo".
3) If the status of ALL requirements is "in progress", the status of the project will be "in progress". The same thing for the last status (done).
4) If some requirements have "in progress" status while other have "done" status, the final status of the project will be "in progress". But I don't how can I write this case in the function.
I search a clean way to code this. I'm sure it's easy in Java but I'm newbie in Java and I don't feel comfortable with ArrayList.
I tried this :
#Override
public String getStatus(Project project){
Iterator<Requirement> it = project.listRequirement.iterator();
while (it.hasNext()) {
Requirement s = it.next();
if (s.getStatus()=="TODO") return "TODO";
//I don't know how I can write the others lines for the two others status
}
}
Can you help me please to complete my function? Thanks
Your comparison logic in if (s.getStatus()=="TODO") is incorrect as you are using == to compare the Strings. You should be using equals() or equalsIgnoreCase() instead.
You can use a boolean to track the statuses. If none of your conditions gets fulfilled then you can return null from the function and handle it appropriately in your code.
Here is the corrected snippet:
#Override
public String getStatus(Project project) {
/* Create Final Strings */
final String TODO = "TODO";
final String INP = "In Progress";
final String DONE = "Done";
/* Boolean Flag */
boolean flag = false;
/* Comparison Logic */
Iterator<Requirement> it = project.listRequirement.iterator();
while (it.hasNext()) {
Requirement s = it.next();
if (TODO.equalsIgnoreCase(s.getStatus())) {
return TODO;
} else if (INP.equalsIgnoreCase(s.getStatus())) {
flag = true;
}
}
/* Return Done */
if(flag) return INP;
else return DONE;
}
Also, you can use if-else or switch() to do the comparisons.
You can use the List method "contains" to check if a list contains a certain element.
But your logic seems incomplete: What about if the list contains status of both "DONE" and "in progess" (And no "todo")? You never specified what should be returned in that case.
To check if a List only contains status of one type, I would copy the list to a Set (A Collections that doesn't allow duplicates) and then check if that sets size is 1
so maybe something like
if(project.listRequirement.contains("TODO")) {
return "TODO";
} else if(project.listRequirement.contains("INPROGRESS") && new HashSet<String>(project.listRequirement).size()==1) {
return "INPROGRESS";
} else if(project.listRequirement.contains("DONE") && new HashSet<String>(project.listRequirement).size()==1) {
return "DONE";
} else {
// These are the cases your logic doesn't cover yet.....
}
Edit:
#PyThon I forget that. In this case, the status of the progress will be "in progress" (since the entire project is not completly done). But I don't have an idea how to program that...
Okay, so if the list looks like this ("DONE", "DONE", "INPROGRESS") the result is supposed to be "INPROGRESS"?
In that case my edited code from above:
if(project.listRequirement.contains("TODO")) {
// list contains a todo
return "TODO";
} else if(project.listRequirement.contains("DONE") && new HashSet<String>(project.listRequirement).size()==1) {
// list contains no todo, and only "done" as only status
return "DONE";
} else if(project.listRequirement.contains("INPROGRESS")) {
// list contains no todo, but does contain in progress
return "INPROGRESS";
} else {
// this should never happen!
throw new IllegalStateException();
}
If you use Java 8
public static String getStatus(List<Requirement> requirement) {
if (requirement.stream().anyMatch(r -> r.getStatus().equals("TODO"))) {
return "TODO";
} else if (requirement.stream().allMatch(r -> r.getStatus().equals("DONE"))) {
return "DONE";
} else {
return "IN PROGRESS";
}
}
If there is any TODO then it is TODO
If all are DONE, then it is DONE
If there are no TODO and not all are done, then some or all must be IN PROGRESS

Missing a return statement somewhere?

I'm working on a basic Java assignment for school. This snippet involves searching for a specific part number in an ArrayList. When I try to compile, the IDE says I have a missing return statement. However, I can't see where it is. Do I need a return statement following the increment of the index? If so, then the return null becomes unreachable. Thank you guys very much.
public InventoryItem findInventoryItem(int searchPartNumber)
{
int index = 0;
boolean searching = true;
while (index < items.size() && searching){
InventoryItem inventoryItem = items.get(index);
int fetchedPartNumber = inventoryItem.getPartNumber();
if(fetchedPartNumber == (searchPartNumber)){
searching = false;
return inventoryItem;
}
else{
index++;
}
if(searching){
return null;
}
}
}
your code has several problems:
after you compared first item in list and it does not match - you will stop comparing, as searching is true and you will return null
in case of empty list you need to return null too
here is the fixed version:
public InventoryItem findInventoryItem(int searchPartNumber) {
for (InventoryItem inventoryItem : items)
if (inventoryItem.getPartNumber() == searchPartNumber)
return inventoryItem;
return null;
}
The method expected a return value in all cases. This means you have to add a return value in the else-block, too. Or you could add a return value only once at the end of all statements.
you're not handling the case where search will not be true.
That is,
if(searching){
return null;
}
Where is the else part handled here?
No matter what happens in your method, there has to be some value returned (even if it is null).
Right now, if you never get into your while (because that condition isn't fulfilled to begin with -> like when items.size() is 0), your method won't return anything.
In other words: Put a return null; after the closing bracket of your while loop.
Another important note: You do realize that this while will always only look at the first item, right? Because if your first item is not the one you're searching for, your variable searching will still be true, which will then force the method to return null (without looking at any other items)
You are missing a return statement right at the end, after the while loop.
This is needed to handle the case where the while loop guard becomes false, either by items being empty, or searching being set to false.
The compiler has no way of determining whether these will never become false, so you it requires you to return in case they do.
All functions that have a type (aren't void) require that you return something based on the method signature. This means that you must return something in ALL cases. You haven't included the case where searching is not true, and must return something if that is the case.
if(searching){
return null;
} else{
//return something else
}
It is important to note though that in this case the else is implicit, and therefore you don't actually have to provide the else. You could instead just do this:
if(searching){
return null;
}
//return something else
Keep in mind that if searching is true, it will return null and "return something else" will never be called.
Do like this
public InventoryItem findInventoryItem(int searchPartNumber)
{
int index = 0;
//boolean searching = true; comment out this line
InventoryItem inventoryItem = null; //declare null InventoryItem here
while (index < items.size())
{
inventoryItem = items.get(index);
int fetchedPartNumber = inventoryItem.getPartNumber();
if (fetchedPartNumber == (searchPartNumber))
{
//searching = false; comment out this line
break; //do something to get out from while loop
}
else {
inventoryItem = null;
index++;
}
}
return inventoryItem; //if found then it will have item otherwise null
}
First you need to return if items.size equals zero. Second you need to return if you find nothing. Third I can't see any usefulness of the variable searching.
You could change your searching function a bit. The final form would be something like this:
public InventoryItem findInventoryItem(int searchPartNumber) {
int index = 0;
while (index < items.size()){
InventoryItem inventoryItem = items.get(index);
int fetchedPartNumber = inventoryItem.getPartNumber();
if(fetchedPartNumber == searchPartNumber)
return inventoryItem;
else
index++;
}
return null;
}

Java: avoid checking for null in nested classes (Deep Null checking)

Imagine I have a class Family. It contains a List of Person. Each (class) Person contains a (class) Address. Each (class) Address contains a (class) PostalCode. Any "intermediate" class can be null.
So, is there a simple way to get to PostalCode without having to check for null in every step? i.e., is there a way to avoid the following daisy chaining code? I know there's not "native" Java solution, but was hoping if anyone knows of a library or something. (checked Commons & Guava and didn't see anything)
if(family != null) {
if(family.getPeople() != null) {
if(family.people.get(0) != null) {
if(people.get(0).getAddress() != null) {
if(people.get(0).getAddress().getPostalCode() != null) {
//FINALLY MADE IT TO DO SOMETHING!!!
}
}
}
}
}
No, can't change the structure. It's from a service I don't have control over.
No, I can't use Groovy and it's handy "Elvis" operator.
No, I'd prefer not to wait for Java 8 :D
I can't believe I'm the first dev ever to get sick 'n tired of writing code like this, but I haven't been able to find a solution.
You can use for:
product.getLatestVersion().getProductData().getTradeItem().getInformationProviderOfTradeItem().getGln();
optional equivalent:
Optional.ofNullable(product).map(
Product::getLatestVersion
).map(
ProductVersion::getProductData
).map(
ProductData::getTradeItem
).map(
TradeItemType::getInformationProviderOfTradeItem
).map(
PartyInRoleType::getGln
).orElse(null);
Your code behaves the same as
if(family != null &&
family.getPeople() != null &&
family.people.get(0) != null &&
family.people.get(0).getAddress() != null &&
family.people.get(0).getAddress().getPostalCode() != null) {
//My Code
}
Thanks to short circuiting evaluation, this is also safe, since the second condition will not be evaluated if the first is false, the 3rd won't be evaluated if the 2nd is false,.... and you will not get NPE because if it.
If, in case, you are using java8 then you may use;
resolve(() -> people.get(0).getAddress().getPostalCode());
.ifPresent(System.out::println);
:
public static <T> Optional<T> resolve(Supplier<T> resolver) {
try {
T result = resolver.get();
return Optional.ofNullable(result);
}
catch (NullPointerException e) {
return Optional.empty();
}
}
REF: avoid null checks
The closest you can get is to take advantage of the short-cut rules in conditionals:
if(family != null && family.getPeople() != null && family.people.get(0) != null && family.people.get(0).getAddress() != null && family.people.get(0).getAddress().getPostalCode() != null) {
//FINALLY MADE IT TO DO SOMETHING!!!
}
By the way, catching an exception instead of testing the condition in advance is a horrible idea.
I personally prefer something similar to:
nullSafeLogic(() -> family.people.get(0).getAddress().getPostalCode(), x -> doSomethingWithX(x))
public static <T, U> void nullSafeLogic(Supplier<T> supplier, Function<T,U> function) {
try {
function.apply(supplier.get());
} catch (NullPointerException n) {
return null;
}
}
or something like
nullSafeGetter(() -> family.people.get(0).getAddress().getPostalCode())
public static <T> T nullSafeGetter(Supplier<T> supplier) {
try {
return supplier.get();
} catch (NullPointerException n) {
return null;
}
}
Best part is the static methods are reusable with any function :)
You can get rid of all those null checks by utilizing the Java 8 Optional type.
The stream method - map() accepts a lambda expression of type Function and automatically wraps each function result into an Optional. That enables us to pipe multiple map operations in a row. Null checks are automatically handled under the neath.
Optional.of(new Outer())
.map(Outer::getNested)
.map(Nested::getInner)
.map(Inner::getFoo)
.ifPresent(System.out::println);
We also have another option to achieve the same behavior is by utilizing a supplier function to resolve the nested path:
public static <T> Optional<T> resolve(Supplier<T> resolver) {
try {
T result = resolver.get();
return Optional.ofNullable(result);
}
catch (NullPointerException e) {
return Optional.empty();
}
}
How to invoke new method? Look below:
Outer obj = new Outer();
obj.setNested(new Nested());
obj.getNested().setInner(new Inner());
resolve(() -> obj.getNested().getInner().getFoo())
.ifPresent(System.out::println);
Instead of using null, you could use some version of the "null object" design pattern. For example:
public class Family {
private final PersonList people;
public Family(PersonList people) {
this.people = people;
}
public PersonList getPeople() {
if (people == null) {
return PersonList.NULL;
}
return people;
}
public boolean isNull() {
return false;
}
public static Family NULL = new Family(PersonList.NULL) {
#Override
public boolean isNull() {
return true;
}
};
}
import java.util.ArrayList;
public class PersonList extends ArrayList<Person> {
#Override
public Person get(int index) {
Person person = null;
try {
person = super.get(index);
} catch (ArrayIndexOutOfBoundsException e) {
return Person.NULL;
}
if (person == null) {
return Person.NULL;
} else {
return person;
}
}
//... more List methods go here ...
public boolean isNull() {
return false;
}
public static PersonList NULL = new PersonList() {
#Override
public boolean isNull() {
return true;
}
};
}
public class Person {
private Address address;
public Person(Address address) {
this.address = address;
}
public Address getAddress() {
if (address == null) {
return Address.NULL;
}
return address;
}
public boolean isNull() {
return false;
}
public static Person NULL = new Person(Address.NULL) {
#Override
public boolean isNull() {
return true;
}
};
}
etc etc etc
Then your if statement can become:
if (!family.getPeople().get(0).getAddress().getPostalCode.isNull()) {...}
It's suboptimal since:
You're stuck making NULL objects for every class,
It's hard to make these objects generic, so you're stuck making a null-object version of each List, Map, etc that you want to use, and
There are potentially some funny issues with subclassing and which NULL to use.
But if you really hate your == nulls, this is a way out.
Although this post is almost five years old, I might have another solution to the age old question of how to handle NullPointerExceptions.
In a nutshell:
end: {
List<People> people = family.getPeople(); if(people == null || people.isEmpty()) break end;
People person = people.get(0); if(person == null) break end;
Address address = person.getAddress(); if(address == null) break end;
PostalCode postalCode = address.getPostalCode(); if(postalCode == null) break end;
System.out.println("Do stuff");
}
Since there is a lot of legacy code still in use, using Java 8 and Optional isn't always an option.
Whenever there are deeply nested classes involved (JAXB, SOAP, JSON, you name it...) and Law of Demeter isn't applied, you basically have to check everything and see if there are possible NPEs lurking around.
My proposed solution strives for readibility and shouldn't be used if there aren't at least 3 or more nested classes involved (when I say nested, I don't mean Nested classes in the formal context). Since code is read more than it is written, a quick glance to the left part of the code will make its meaning more clear than using deeply nested if-else statements.
If you need the else part, you can use this pattern:
boolean prematureEnd = true;
end: {
List<People> people = family.getPeople(); if(people == null || people.isEmpty()) break end;
People person = people.get(0); if(person == null) break end;
Address address = person.getAddress(); if(address == null) break end;
PostalCode postalCode = address.getPostalCode(); if(postalCode == null) break end;
System.out.println("Do stuff");
prematureEnd = false;
}
if(prematureEnd) {
System.out.println("The else part");
}
Certain IDEs will break this formatting, unless you instruct them not to (see this question).
Your conditionals must be inverted - you tell the code when it should break, not when it should continue.
One more thing - your code is still prone to breakage. You must use if(family.getPeople() != null && !family.getPeople().isEmpty()) as the first line in your code, otherwise an empty list will throw a NPE.
If you can use groovy for mapping it will clean up the syntax and codes looks cleaner. As Groovy co-exist with java you can leverage groovy for doing the mapping.
if(family != null) {
if(family.getPeople() != null) {
if(family.people.get(0) != null) {
if(people.get(0).getAddress() != null) {
if(people.get(0).getAddress().getPostalCode() != null) {
//FINALLY MADE IT TO DO SOMETHING!!!
}
}
}
}
}
instead you can do this
if(family?.people?[0]?.address?.postalCode) {
//do something
}
or if you need to map it to other object
somobject.zip = family?.people?[0]?.address?.postalCode
Not such a cool idea, but how about catching the exception:
try
{
PostalCode pc = people.get(0).getAddress().getPostalCode();
}
catch(NullPointerException ex)
{
System.out.println("Gotcha");
}
If it is rare you could ignore the null checks and rely on NullPointerException. "Rare" due to possible performance problem (depends, usually will fill in stack trace which can be expensive).
Other than that 1) a specific helper method that checks for null to clean up that code or 2) Make generic approach using reflection and a string like:
checkNonNull(family, "people[0].address.postalcode")
Implementation left as an exercise.
I was just looking for the same thing (my context: a bunch of automatically created JAXB classes, and somehow I have these long daisy-chains of .getFoo().getBar().... Invariably, once in a while one of the calls in the middle return null, causing NPE.
Something I started fiddling with a while back is based on reflection. I'm sure we can make this prettier and more efficient (caching the reflection, for one thing, and also defining "magic" methods such as ._all to automatically iterate on all the elements of a collection, if some method in the middle returns a collection). Not pretty, but perhaps somebody could tell us if there is already something better out there:
/**
* Using {#link java.lang.reflect.Method}, apply the given methods (in daisy-chain fashion)
* to the array of Objects x.
*
* <p>For example, imagine that you'd like to express:
*
* <pre><code>
* Fubar[] out = new Fubar[x.length];
* for (int i=0; {#code i<x.length}; i++) {
* out[i] = x[i].getFoo().getBar().getFubar();
* }
* </code></pre>
*
* Unfortunately, the correct code that checks for nulls at every level of the
* daisy-chain becomes a bit convoluted.
*
* <p>So instead, this method does it all (checks included) in one call:
* <pre><code>
* Fubar[] out = apply(new Fubar[0], x, "getFoo", "getBar", "getFubar");
* </code></pre>
*
* <p>The cost, of course, is that it uses Reflection, which is slower than
* direct calls to the methods.
* #param type the type of the expected result
* #param x the array of Objects
* #param methods the methods to apply
* #return
*/
#SuppressWarnings("unchecked")
public static <T> T[] apply(T[] type, Object[] x, String...methods) {
int n = x.length;
try {
for (String methodName : methods) {
Object[] out = new Object[n];
for (int i=0; i<n; i++) {
Object o = x[i];
if (o != null) {
Method method = o.getClass().getMethod(methodName);
Object sub = method.invoke(o);
out[i] = sub;
}
}
x = out;
}
T[] result = (T[])Array.newInstance(type.getClass().getComponentType(), n);
for (int i=0; i<n; i++) {
result[i] = (T)x[i];
}
return result;
} catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
throw new RuntimeException(e);
}
}
and my favorite, the simple try/catch, to avoid nested null checks...
try {
if(order.getFulfillmentGroups().get(0).getAddress().getPostalCode() != null) {
// your code
}
} catch(NullPointerException|IndexOutOfBoundsException e) {}

Categories

Resources