I'm following this tutorial for creating reminder in android. In the source code that it provides it used the value of "1" for a boolean method.
Here is the code snippet I'm talking about:
public static boolean showRemainingTime(){
return "1".equals(sp.getString(TIME_OPTION, "0"));
}
Why "1" is used in this example given that in java the value of boolean is either true or false?
Sorry for my lame question!
The showRemainingTime method is not returning the String "1". It returns true if the String returned by sp.getString(TIME_OPTION, "0") is equal to the String "1", and false otherwise.
String literals are full-fledged String objects. This may make more sense to you:
String str = "1";
return str.equals(sp.getString(TIME_OPTION, "0"));
It might also make more sense if it were written this way:
return sp.getString(TIME_OPTION, "0").equals("1");
The problem with this version is that if getString(...) returned null, calling equals(...) would throw a NullPointerException. That may not be possible in this particular case, but calling methods on string literals is a good habit to get into.
Related
I am trying to find the most concise (and meaningful) way of using Java Optional, to read the first value off a Optional<String> and return the String if exists, or return "NOT_FOUND". Here is the code I am working with:
public static String getValue(Optional<String> input) {
return input.ifPresent(val -> val.get()).orElse("NOT_FOUND")
}
The methods of Optional apparently have very specific purposes but the API has left me confused.
Update (4/13/2018):
The code in my question is incorrect, because if I regarded val as the value inside the Optional, then val.get() does not make any sense. Thanks for pointing that out, #rgettman.
Also, I added another part to my question in the accepted answer's comments, i.e. I needed a way to manipulate the String value, if present, before returning. The orElse("NOT_FOUND") is still applicable, if the Optional does not contain a value. So what is an acceptable use of the Optional API to achieve the following?
public static String getValue(Optional<String> input) {
return input.isPresent() ? input.get().substring(0,7).toUpperCase() : "NOT_FOUND";
}
#Aominè's answer and follow up comments addressed both parts of this question.
All you have to do is change your return statement to:
return input.orElse("NOT_FOUND");
This will return the object in the Optional if present else returns "NOT_FOUND".
That said, I'd avoid using Optional's as parameters. see here.
If you need to manipulate the string value, if it is present before returning it, use map method:
public static String getValue(Optional<String> input) {
return input.map(s -> s.substring(0,7).toUpperCase()).orElse("NOT_FOUND");
}
If input is empty the method returns default value - "NOT_FOUND", otherwise capitalized part of the string is returned.
getValue(Optional.ofNullable(null));
$6 ==> "NOT_FOUND"
getValue(Optional.of("some long string"));
$7 ==> "SOME LO"
Converting the value to String in java; There are multiple ways of doing it.
Just wanted to know what's the difference between each other in the following ways.
strValue.toString()
strValue+""
""+strValue
It depends on java version. Java 7 would act a bit smarter using StringBuilder + append().
Generally, you do not want unnecessary allocations. Use first one.
strValue.toString()
will return itself, because the toString() implementation of String (I'm guessing strValue is indeed of type String) returns this.
strValue+""
""+strValue
Will result in the same value (strValue) but won't invoke the toString() method
All Strings contain the same value, try it out:
String strValue = "Hello world"; // not null
String a = strValue.toString();
String b = strValue+"";
String c = ""+strValue;
Measuring its length give all the result 11, because adding an empty String to another one equals the original String itself:
System.out.println(a.length());
...
Try the equality between these Strings:
System.out.println(a.equals(b));
System.out.println(b.equals(c));
System.out.println(c.equals(a));
They are all true, because these Strings have the same value to be compared. All it in the case the strValue is not null.
One major difference is how null is handled.
If strValue is null, strValue.toString() will throw a NullPointerException, while the other two options will return the String "null".
Other differences may be observed if strValue is of a boxed numeric type, and you try to concatenate other numeric variables to it.
For example :
If
Integer a = 5;
Integer strValue = 6;
Then
a+strValue+""
would return
"11"
while
a+""+strValue
or
""+a+strValue
would return
"56"
Sorry if my question is silly or not it doesnot matter. But i just want to know what will happen in these two conditions.
public class Test {
public static void main(String[] args)
{
String str="test";
if(str.equals("test")){
System.out.println("After");
}
if("test".equals(str)){
System.out.println("Before");
}
}
}
Both are giving same results only. But i know there is some reasons.I dont know about that. What is difference between these two conditions?
There are no difference between them at all. Many programmers use the 2nd way just to make sure that they don't get a NullPointerException. That's all.
String str = null;
if(str.equals("test")) { // NullPointerException
System.out.println("After");
}
if("test".equals(str)) { // No Exception will be thrown. Will return false
System.out.println("Before");
}
Second one does not throw NullPointerException. But again it is considered as bad code because it might happen that str is null and you do not detect that bug at this point instead you detect it somewhere else
Given a choice prefer 1 since it helps you to find bugs in the program at early stage.
Else add check for null if str is null then you will be able to make out are strings really not equal or is second string does not present
if(str == null){
//Add a log that it is null otherwise it will create confusion that
// program is running correctly and still equals fails
}
if("test".equals(str)){
System.out.println("Before");
}
For first case
if(str.equals("test")){//Generate NullPointerException if str is null
System.out.println("After");
}
Actually both are same. There is no difference between this two. http://www.javaworld.com/community/node/1006 Equal method compares content of two string object. So in your first case it compares str variable with "test" and in second it compares "test" to str variable.
They do pretty much the same.
The only difference is that the first example uses the equal() method of the string object "str" with the "test"-string as parameter while the second example uses the equal() method of the string "text" with "str" as parameter.
The second variant can't throw a NullPointerException since its obviously not null.
The first if-statement test, whether str equals "test". The second if-statement test, whether "test" equals str. So the difference between these two if-statements is, that in the first you send a message to the str object with the argument "test". then the str object compares, whether it equals to the argument and return true or false. The second if-statement send a message to "test". "test" is also a string object. So now "test" compares, whether it equals to str and return true or false.
when you try first fixing static string you can avoid nullpointer exception in many situations.
This is my source code. I'trying to implement a simple program that asks a question to a user and expects the answer to be "yes" or "no" and terminates only if the user answer to the question "yes" or "no". The book I have suggested me not to use == comparison and to use the equals method instead, so that the program can understand if the user typed "y e s" instead of "yes". But in this way the result is the same and the method seems to compare the user's answer if it is exactly "yes" or "no". It doesn't accept for example an aswer of "n o". Is that logical for that method? Is it supposed to work that way? How can I change the program to accept answers like "Yes" "ye s" "No" "NO" etc.? I would appreciate your help:)
import acm.program.*;
public class YesNoExample extends ConsoleProgram{
public void run(){
while(true){
String answer = readLine("Would you like instructions? ");
if(askYesNoQuestion(answer)){
break;
}
println("Please answer yes or no.");
}
}
private boolean askYesNoQuestion(String str){
if(str.equals("yes")||str.equals("no")){
return true;
}else{
return false;
}
}
}
If you use == you'll be comparing the references (memory pointers) of two String objects. If you use equals, a custom made method in the String class will be run that does some "intelligent" comparison, in this case, check that the characters are all the same, and the whole thing has the same length.
If you'd like to support mixed case letters, you could use "someString".equalsIgnoreCase("SoMeString") (which will return true). This is done (said roughly) by making both strings lowercase (so the case doesn't matter) and comparing them using equals.
Edit: The other posters made me realize that, in addition to capitalization, you also want to look for String equality where spaces don't matter. If that's the case, a similar trick to turning everything to lowercase applies, where you first remove all the spaces, as #LouisWasserman says in his answer
If you need to fuzzily identify yes/no, first you need exact rules as to what matches. Based on your examples, I can suggest this:
private boolean askYesNoQuestion(String str) {
str = str.replace(" ", "").toUpperCase();
return str.equals("YES") || str.equals("NO");
}
If interested in top performance and not at all in intelligibility, use this:
private static final Pattern p =
Pattern.compile("y\\s*e\\s*s|n\\s*o", Pattern.CASE_INSENSITIVE);
private boolean askYesNoQuestion(String str) {
return p != null && p.matcher(str.trim()).matches();
}
Semantics of == vs .equals()
First off you misunderstand the semantics.
== tests for object identity. A == B says is A a reference to the exact same object as B.
.equals() applies custom logic to test if the objects are equal in some logical manner, without being the exact same object. For this to be implemented correct, both objects should have the same .hashCode() value as well.
Idiomatic Java Solution
Since the String object is final which means it can't be inherited from. You can't override the .equals() on the String object.
What you need to do is preprocess the input into something that can be directly compared to the target value with .equalsIgnoreCase().
One way to do this is use, answer.replaceAll("\\s","") to remove all the whitespace then you can compare it to your target String literal with .equalsIgnoreCase().
A better method to replace askYesNoQuestion() would be:
private boolean isAnswerYesOrNo(final String answer)
{
final String input = answer.replaceAll("\\s","");
return "yes".equalsIgnoreCase(input) || "no".equalsIgnoreCase(input);
}
Comparing a literal to the input parameter will insulate you from NullPointerExceptions if the input parameter happens to be null "yes".equalsIgnoreCase()can never throw aNullPointerException`. This is idiomatic Java.
Get a better book
That book isn't very useful if it really says what you are claiming it says. Also it is teaching you to write lots of code to handle bad input when that is a complete anti-pattern and a well designed program would exit with a verbose explanation of the exact problem was what can be done to fix the input.
With the explanation of == and .equals well described above, here's a two examples of a one liner that does the comparison you want.
if ( Pattern.matches("\\s*[yY]\\s*[eE]\\s*[sS]\\s*", input) ) {
// do something
}
if ( input.replaceAll("\\s", "").equalsIgnoreCase("yes") ) {
// do something
}
This question already has answers here:
How do I compare strings in Java?
(23 answers)
Closed 9 years ago.
I am making an archive for my family. There are no syntax errors, however whenever I type in "Maaz", it evaluates realName == "Maaz" to false and goes to the else statement.
import java.util.Scanner;
public class MainFamily {
public static void main (String [] args) {
System.out.println("Enter you're name here");
Scanner name = new Scanner(System.in);//Scanner variable = name
String realName;
realName = name.nextLine();//String variable = user input
System.out.println("Name: "+ realName);
if (realName == "Maaz") {
System.out.println("Name: Maaz");
} else {
System.out.println("This person is not in the database");
}
}
}
TL;DR
You wrote (this doesn't work):
realName == "Maaz"
You meant this:
realname.equals("Maaz")
or this:
realname.equalsIgnoreCase("Maaz")
Explanation
In Java (and many other Object-Oriented programming languages), an object is not the same as a data-type. Data-types are recognized by the runtime as a data-type.
Examples of data-types include: int, float, short.
There are no methods or properties associated with a data-type. For example, this would throw an error, because data-types aren't objects:
int x = 5;
int y = 5;
if (x.equals(y)) {
System.out.println("Equal");
}
A reference is basically a chunk of memory that explicitly tells the runtime environment what that data-block is. The runtime doesn't know how to interpret this; it assumes that the programmer does.
For example, if we used Integer instead of int in the previous example, this would work:
Integer x = new Integer(5);
Integer y = new Integer(5);
if (x.equals(y)) {
System.out.println("Equal");
}
Whereas this would not give the expected result (the if condition would evaluate to false):
Integer x = new Integer(5);
Integer y = new Integer(5);
if (x == y) {
System.out.println("Equal");
}
This is because the two Integer objects have the same value, but they are not the same object. The double equals basically checks to see if the two Objects are the same reference (which has its uses).
In your code, you are comparing an Object with a String literal (also an object), which is not the same as comparing the values of both.
Let's look at another example:
String s = "Some string";
if (s == "Some string") {
System.out.println("Equal");
}
In this instance, the if block will probably evaluate to true. Why is this?
The compiler is optimized to use as little extra memory as is reasonable, although what that means depends on the implementation (and possibly runtime environment).
The String literal, "Some string", in the first line will probably be recognized as equivalent to the String literal in the second line, and will use the same place in memory for each. In simple terms, it will create a String object and plug it into both instances of "Some string". This cannot be relied upon, so using String.equals is always a better method of checking equivalence if you're only concerned with the values.
do this instead
if (realName.equals("Maaz"))
equals() should be used on all non-primitive objects, such as String in this case
'==' should only be used when doing primitive comparisons, such as int and long
use
if(realName.equals("Maaz"))
use == with primitive data type like int boolean .... etc
but if you want to compare object in java you should use the equals method
You have to compare objects with realName.equals ("Maaze"), not with ==.
It is best practice to compare Strings using str.equals(str2) and not str == str2. As you observed, the second form doesn't work a lot of the time. By contrast, the first form always works.
The only cases where the == approach will always work are when the strings are being compared are:
string literals or references to string literals, or
strings that have been "interned" by application-level code calling str = str.intern();.
(And no, strings are not interned by default.)
Since it is generally tricky to write programs that guarantee these preconditions for all strings, it is best practice to use equals unless there is a performance-related imperative to intern your strings and use ==.
Before that you decide that interning is a good idea, you need to compare the benefits of interning with the costs. Those costs include the cost of looking up the string in the string pool's hash table and the space and GC overheads of maintaining the string pool. These are non-trivial compared with the typical costs of just using a regular string and comparing using equals.
You can also use
realname.equalsIgnoreCase("Maaz")
This way you can accept Maaz, maaz, maaZ, mAaZ, etc.
== tests shallow equality. It checks if two objects reference the same location in memory.
Intriguing. Although, as others have stated, the correct way is to use the .equals(...) method, I always thought strings were pooled (irrespective of their creation). It seems this is only true of string literals.
final String str1 = new String("Maaz");
final String str2 = new String("Maaz");
System.out.println(str1 == str2); // Prints false
final String str3 = "Laaz";
final String str4 = "Laaz";
System.out.println(str3 == str4); // Prints true
Since you are working on strings, you should use equals to equalsIngnorecase method of String class. "==" will only compare if the both objects points to same memory location, in your case, both object are different and will not be equal as they dont point to same location. On the other hand, equals method of String class perform a comparison on the basis of the value which objects contains. Hence, if you will use equals method, your if condition will be satisfied.
== compares object references or primitive types (int, char, float ...)
equals(), you can override this method to compare how both objects are equal.
for String class, its method equal() will compare the content inside if they are the same or not.
If your examples, both strings do not have the same object references, so they return false, == are not comparing the characters on both Strings.
It seems nobody yet pointed out that the best practice for comparing an object with a constant in Java is calling the equals method of the constant, not the variable object:
if ("Maaz".equals (realName)) {}
This way you don't need to additionally check if the variable realName is null.
if(realName.compareTo("Maaz") == 0) {
// I dont think theres a better way do to do this.
}