I'm a groovy newbie so bear with me here. I love groovy's power to write less and often cleaner code but I'm trying to figure out if there's a better or more readable way of condensing these multiple if statements. It's a fairly straightforward code snippet but there's got to be a better way of doing this. I'm a newbie so any code snippets are greatly appreciated.
if (!textOverlay) {
textType = ""
if(url != null){
Page getPage = resource.getResourceResolver().getResource(url).adaptTo(Page.class)
if (getPage != null) {
showLink = showLink + ".html"
if (fragment.length() > 0) {
url += "#"+fragment;
}
}
}
} else {
//do something else
}
Thanks in advance for the help!
This doesn't help with nesting, but there are a few places where you could take advantage of Groovy to make the code a bit more compact. I've added some explanatory comments
if (!textOverlay) {
textType = ""
// null is considered false, so no need to explicitly check for null
if (url) {
// getResourceResolver() replaced by resourceResolver
// Page and Page.class are the same thing
Page getPage = resource.resourceResolver.getResource(url).adaptTo(Page)
// Groovy truth
if (getPage) {
// use String concatenation operator (also works in Java)
showLink += ".html"
// non-empty strings evaluate to true
if (fragment) {
// GString instead of string concatenation
url += "#$fragment"
}
}
}
} else {
//do something else
}
Related
Please advise how to reduce cognitive complexity on the below code
ids.add((row.getCell(11) != null) ? row.getCell(11).getStringCellValue() : "");
Add a method to hide the details, for example:
private String getCellValueOrDefault(Cell cell) {
if (cell == null) {
return "";
}
return cell.getStringValue();
}
Then use the method:
ids.add(getCellValueOrDefault(row.getCell(11));
You can use Optional:
ids.add(Optional
.ofNullable(row.getCell(11))
.map(cell -> cell.getStringCellValue())
.orElse("")
)
That way you don't need an extra method. If this is something that is needed at many places it is better to create a specific method for at as Andrew S remarked.
Normally I make a comparison in every activity(Android) but I have a problem and I couldn't find the solution. I tried everything I could but result is still the same.
In if statement null value seems to be not null.
What am I doing wrong?
Here is the code :
System.out.println(item.getSub()); // output is null
if (item.getSub()!=null) {
r.putExtra("engsub", item.getSub()); // Normally it shouldn't, but it goes in here
startActivityForResult(r, position);
}
else {
//Do something
}
And I tried this :
String def = item.getSub()+"";
System.out.println(def); // output is not null
if (!def.equals("")) {
r.putExtra("engsub", item.getSub()); // Normally it shouldn't, but it goes in here
startActivityForResult(r, position);
}
else {
//Do something
}
Added :
JSONArray jsonResponse = new JSONArray(result);
asd = new String[5][jsonResponse.length()];
rowItems = new ArrayList<RowItem2>();
for (int i = 0; i < jsonResponse.length(); i++) {
JSONObject js = jsonResponse.getJSONObject(i);
// ....codes
asd[4][i] = js.getString("engsub");;
item = new RowItem2(asd[0][i], asd[1][i], asd[2[i],
asd[3][i],asd[4][i]);
rowItems.add(item);
}
RowItem2 class
private String engsub;
public RowItem2(String title, String desc,String desc2,String desc3,String engsub) {
this.engsub = engsub;
//......
}
//.......
public String getSub() {
return engsub;
}
public void setSub(String engsub) {
this.engsub = engsub;
}
I think JSON string result contains the word "NULL" in it.
Look at the docs about JSONObject on Android Developer site.
Here is the line that solves your problem:
When the requested type is a String, other non-null values will be
coerced using valueOf(Object). Although null cannot be coerced, the
sentinel value NULL is coerced to the string "null".
Below some ideas when trying to track down an issue like this:
Confirm your assumptions
You sound confused, so set your mind at ease. There is nothing wrong with Java / Android. Confirm this with a change that will work correctly every time.
This change challenges your assumption: you assume that item.getSub() is returning null.
String nullString = null;
System.out.println(nullString);
if (nullString != null) {
r.putExtra("engsub", item.getSub()); // Normally it shouldn't, but it goes in here
startActivityForResult(r, position);
}
else {
//Do something
}
This will NOT pass the if test, unless there is something wrong with your IDE.
Confirm your IDE is working
You may still think you are getting null. In some cases it could look like this.
Sometimes Eclipse will not put the correct code onto your emulator / device. There could be an issue with the build.
So do a project Clean. Then build again and test.
This will confirm that you are running the correct code.
Confirm what you are seeing
Sometimes when output looks like a "" string, it can be " " or " ".
Try logging your output surrounded by [ and ].
System.out.println("[" + item.getSub() + "]");
Look deeper into the code
This is why I asked to see the item.getSub() code, and the extra you have shown.
If the above tests don't help, look to see how that value is set / returned.
Looking into JSONObject.getString() javadoc, it shows that it cannot return a null value:
In your case, log out the JSON string, and log out the values in RowItem2 constructor.
That should show you the "NULL" I refer to at the top of this answer.
You could try:
if (item.getSub() instanceof String) {
r.putExtra("engsub", item.getSub()); // Normally it shouldn't, but it goes in here
startActivityForResult(r, position);
}
else {
//Do something
}
This way you're sure that the item.getSub() is a string.
Try this,
if(!"".equals(your string)
{
// do something
}
I wonder if it would be possible to 'avoid' null checks in Java, take an example from this code:
#Override
public List<AccountBean> search(AccountConstraint... c) {
if (c.length == 0) {
throw new IllegalArgumentException("dao.AccountDAO.search: c.length == 0");
}
try {
List<AccountBean> beans = new ArrayList<>();
for (AccountConstraint ac : c) {
Builder builder = new QueryBuilder.Builder("SELECT * FROM accounts");
if (ac.getAccountId() != null) {
builder.clause("accountId >= " + ac.getAccountId().getMin() + " AND accountId <= " + ac.getAccountId().getMax());
}
if (ac.getUsername() != null) {
builder.clause("username = \"" + ac.getUsername() + "\"");
}
if (ac.getPassword() != null) {
builder.clause("password = \"" + ac.getPassword() + "\"");
}
if (ac.getEmail() != null) {
builder.clause("email = \"" + ac.getEmail() + "\"");
}
PreparedStatement ps = connection.prepareStatement(builder.build().getQuery());
ResultSet rs = ps.executeQuery();
while (rs.next()) {
beans.add(new AccountBean(rs));
}
}
return beans;
} catch (SQLException ex) {
throw new RuntimeException(ex);
}
}
It has to check 4 times for the != null because else the code would fail.
Is it possible to turn the if (object != null) statements into one-liners that only execute if there is no NullPointerException? When there is an exception, the line should just be ignored.
I am not talking about a general language feature here, I am talking about a feature that would only be turned in when you explicitely decide to do so.
For example: NullCheck(builder.clause("username = \"" + ac.getUsername() + "\"")); would be a snippet of the suggested code.
Is something like that possible in Java?
Also if it is not possible, might it be possible in Java 8 to use methods (voids) directly in methods?
So then code like this could actually work?
public static NullCheck(Void void) {
try {
void.execute();
}
catch (NullPointerException e) {
//ignore
}
}
I know I could put the method inside it's own class that extends an interface that has method execute() and then pass that class around, but that would defeat the purpose of getting rid of the null checks or anything that would be even more complicated.
Regards.
WARNING: The way I used PreparedStatement here is prone to SQL Injection. Do not reuse this code.
You can avoid these checks by assuming that these methods do not return null values.
How can you assume this? By having the specification for the AccountConstraint say so. The code in AccountConstraint is then responsible for ensuring the values are not null, rather than your search method being responsible for handling null values. You might have to change the design of AccountConstraint to do this.
And what happens if your assumption is wrong? That is, if AccountConstraint is buggy. An exception will be thrown, which you were not expecting. But that is what can happen when you have a bug: an unexpected exception is thrown. Debugging the code will be easy, because the stacktrace will show you which method of AccountConstraint is returning an invalid null value.
Yes and No.
There are two approaches to tackle the null problem:
Special Operators like the Safe Navigation Operator in Groovy. If x.y throws a NullPointerException x?.yreturns just null. Since Java does not allow creation of new operators, you can't do this in Java. Operators like this where considered for JDK8 but where dropped. If you want have something like this, switch to Groovy or one of the many other languages having this feature.
Special Class many languages have a special interface for representing a value that might be null. In Scala it is called Option. Option has two implementations: None + Some. None replaces null. Whenever you want to do something with the value, you don't use it directly, but you call map on the Option with a function as an argument. If it is actually a None, nothing happens, you just get back None. If it is a Some, the function gets executed on the value and you get an Option with the result. That way you can work with Options all the time, without worrying about nulls.
Actually it is in now way special, so you can create such a class yourself with Java. The problem is only, that Java doesn't have functions, so you have to use anonymous classes. This makes the whole thing really cumbersome and only a theoretical option.
JDK8 has a Option class. As far as I know it is missing the map method which makes the whole thing a bad joke in my opinion. But since the most important tool (anonymous functions) are there will be a proper Option implementation provided by one of the usual suspects (Google, Apache ...)
As it stands, you could probably write a method like
public void clauseIfNotNull(Builder builder, String format, Object o) {
if (o != null) {
builder.clause(String.format(format, o));
}
}
and then that'd look like clauseIfNotNull(builder, "username = \"%s\"", ac.getUsername());
Other than that, there's not much you can do with Java 7.
Make a minimal adaptor object on the Builder
class NotNullClauseAdapter
{
private final Builder builder;
public NotNullClauseAdapter(Builder builder) {
this.builder = builder;
}
public void clause(String format, Object o) {
if (o != null) {
builder.clause(String.format(format, o));
}
}
}
Use this in your code:
for (AccountConstraint ac : c) {
Builder builder = new QueryBuilder.Builder("SELECT * FROM accounts");
NotNullClauseAdapter adapter = new NotNullClauseAdapter(builder);
if (ac.getAccountId() != null) {
builder.clause("accountId >= " + ac.getAccountId().getMin() + " AND accountId <= " + ac.getAccountId().getMax());
}
adapter.clause("username = \"%s\"", ac.getUserName());
adapter.clause("password = \"%s\"", ac.getPassword));
adapter.clause("email = \"%s\"", ac.getEmail());
PreparedStatement ps = connection.prepareStatement(builder.build().getQuery());
ResultSet rs = ps.executeQuery();
while (rs.next()) {
beans.add(new AccountBean(rs));
}
}
You can expand by adding further clause-methods to the adapter to handle specific objects like ranges in order to convert things like the accountId as well, e.g.
public void clauseMinMax(String format, Range r) {
if (r != null) {
builder.clause(String.format(format, r.getMin(), r.getMax()));
}
}
The accountId row then becomes (if getAccountId() returns a Range object):
adapter.clauseMinMax("accountId >= %d AND accountId <= %d", ac.getAccountId());
Use JSR305 and use the appropriate #Nonnull annotations and you don't have to do null checks, the annotations do them for you.
The use of #Nonnull and #CheckReturnValue annotations from JSR305 help to express the needs for null and return value checks. It is a good practice that the developer describes the expected behavior of the implementation for the later use and the static code analysis.
I'm trying to make a group of if statements, in which each if will print given some argument is true, but an else that will only print if none of the ifs were returned. I don't think an else if would work in this case.
I have some code (the colors are just as examples):
boolean any=false;
if(redStage==2)
{ any=true; System.out.print(redComplete); }
if(blueStage==2)
{ any=true; System.out.print(blueComplete); }
if(greenStage==2)
{ any=true; System.out.print(greenComplete); }
if(any==false)
System.out.print(noneComplete);
Is there anything I can do to eliminate the need for a separate boolean to check whether any of the if's arguments were true?
Edit:
(I just noticed what may be confusing. The code im using isn't actually using return. Instead, it is printing out the results, which means more than one thing can be returned.)
Since you need to processes the stages independently from one another, and more than one can be complete at the same time, your code is as good as it can be.
What follows is my answer to your original question:
You don't need the boolean. Your code is equivalent to:
if (redStage == 2) { return redComplete; }
if (blueStage == 2) { return blueComplete; }
if (greenStage == 2) { return greenComplete; }
return noneComplete;
This makes use of the fact that each if body contains an unconditional return. If this wasn't the case, you could phrase the construct like so:
if (redStage == 2) {
// redComplete
} else if (blueStage == 2) {
// blueComplete
} else if (greenStage == 2) {
// greenComplete
} else {
// noneComplete
}
I learned this piece of code in University, while learning C++.. and I later used the same thing in C#... but now I want to use it in Java... I have looked all over Internet for similar thing, but i dun even no how to phrase it so i get the correct results.
So umm please let me know how to do this is in JAVA and also let me know what is this way called??? I know What it does.. but i have no idea how it does it.. so mind explaining it as well...
C++ is the same thing as below except one DIFFERENCE look Below
C# if (Customers[i].delExecute(delIn) == true)
C++ if (Customers[i]->delExecute(delIn) == true)
Java ?? if (????????????????????????????????)
So here I go ill try my best to explain.
C#
Class called Customer with custId etc etc
List<Customer> Customers = new List<Customers>
public void delCust(int delIn)
{
for (int i = 0; i < Customers.Count(); i++)
{
if (Customers[i].delExecute(delIn) == true)
{
Customers.Remove(Customers[i]);
break;
}
}
}
bool delExecute(int delInput) {
if (custId == delInput) {
return true;
}
return false;
}
OK right so the above code works
now I want the same thing with JAVA... anyone got any ideas how?
if (Customers.get(i).delExecute(delIn))
BTW, there is no need to say == true explicitly
In Java, Vector is an out-dated class which you should probably avoid using. Instead, you should use an ArrayList. Either way, though, both are Lists, and thus implement get for random-access.
You can implement what you're attempting as follows...
if (customers.get(i).delExecute(delIn))
Note that == true is redundant, as it is effectively an identity (true == true is true, false == true is false). You should also avoid capitalized field names in Java.
Now, there is also a preferred way to do what you are attempting using an Iterator.
private List<Customer> customers = new ArrayList<Customers>();
public void delCust(int delIn) {
final Iterator<Customer> cursor = customers.iterator();
while (cursor.hasNext()) {
if (cursor.next().delExecute(delIn)) {
cursor.remove();
break;
}
}
}
... coupled with:
boolean delExecute(int delInput) {
return custId == delInput;
}