Why does java require a double equals sign (==) when comparing Integers in a if statement?
For example
if(x = 3.141)
System.out.println("x is equal to pi.");
is incorrect, it should be
if(x == 3.141)
System.out.println("x is equal to pi.");
I know that "==" is used to compare integers and "=" is used to set an integer value, but why in a if statement does this remain true?
Is it even allowed to assign a variable a value in an if statement (or initiate a new variable)?
Is there any reason anyone would ever want to assign a variable a new value inside an if statement (if so please provide an example)?
This seems like a question that should already have an answer, but I was unable to find one on here or using google, if this is a duplicate question please tell me and I will remove it immediately.
Wouldn't it be confusing if = sometimes did assignment, and sometimes comparison, depending in which context you used it?
That sounds like a bad idea, and would introduce errors.
Plus, the current syntax is compatible with C and C++, so a lot of people are familiar with it.
Is there any reason anyone would ever want to assine a variable a new value inside of an if statement (if so please provide an example)?
It's quite common in while loops:
int b;
while ((b=in.read()) != -1){
=
is used for assignment.
==
is used for comparison.
Is it even allowed to assign a variable a value in an if statement (or initiate a new variable)?
yes it is allowed.
Note what error message you get for if (x = 3.141); it is a type error (cannot convert from double to boolean).
The assignment's type is the type of its both sides; if the type of the assignment is boolean (if (x = true), or even if (x = a.equals(b))), then it is legal to write.
So since it is legal to assign a value to a boolean in the condition, you'd have to use == for comparison.
Is it even allowed to assine a variable a value in an if statement (or initiate a new variable)?
Yes. A common idiom for doing this is:
String line = null;
while ( (line = in.readLine()) != null ) {
// do work
}
In the loop, line is assigned a value and then compared to null. I can't think of an example with ints; it certainly wouldn't be clear there.
History of programming languages 101:
Fortran uses = for both.
Algol introduced := for assignment and used = for comparison. This was required to resolve a grammar ambiguity.
Pascal followed suit.
PL/1 did not.
I can't speak for B or BCPL but by the time we got C it was = for assignment and == for comparison, again to resolve a grammar ambiguity
C++ followed C
Java followed C++ in many respects including this one.
The grammar ambiguity arises because of allowing assignments in expressions. Contrary to your assertion, if (x = true) is legal in Java if x is of type boolean.
== is the identity comparator, which works for both objects and primitives. It answers the question "are the two things the same thing".
= is the assignment operator. It sets the value of the left side to the right side.
Things can turn buggy when using your example with booleans:
boolean b;
if (b = true) // This compiles, but is a bug, because it sets b, not tests it
While other types won't compile with this syntax, boolean and Boolean do, so that's why the following pattern is advised:
if (b)
you can absolutely assign a variable in an if statement. also, that's just the way it works: = always is assignment, and == is always comparison.
So..
= is assignment, and == is comparison, and it is always like this, no matter where they are used.
And assignment is different with "declaration". An assignment statement has its return value, while a declaration doesn't. So you can't write boolean a = false in the () of if statement, but you can write a = false when a has been declared before.
Not all assignments are legal. For example:
int index;
if (index = str.indexOf("something")) {
...
}
It's not legal, because String.indexOf(String) returns an int, while if requires a boolean.
Also, there is a huge difference between "legal" and "making sense".
int index;
if ((index = str.indexOf("something")) != -1) {
...
}
It is legal, as != operation returns a boolean, and it makes sense, as I do want to check if the str contains a substring "something";
However,
int index;
boolean flag;
if ( flag = ((index = str.indexOf("something")) != -1) ) {
...
}
is also legal, as the statement as last returns a boolean; but it DOESN'T make sense, because the != statement already returns a boolean.
Related
I am facing something strange here. Please help me understand if I am missing something. My if condition was supposed to be:
if(configuredPdf == true)
But by mistake I had written:
if(configuredPdf = true)
And my Eclipse compiler does not ask me to correct it. Then I assume there is no compile time or checked exception. So:
(configuredPdf = true)
Returns a boolean?
Yes, configuredPdf = true assigns true to your variable and returns true. Therefore if (configuredPdf = true) is a valid syntax even though it's usually a bug.
It's safer to use if (configuredPdf) to avoid this kind of typo.
An assignment is an expression which returns the value you assigned. e.g. a = b = true will assign true to a and b.
The reason boolean type was added was to avoid this sort of bug. In C for example you can write
if (a = 1)
and anything non-negative is true.
While you can still make a mistake with boolean types, instead of writing
if (a == true)
if (b == false)
you can write
if (a)
if (!b)
A more common example is
for(String line; ((line = br.readLine()) != null;) {
// process the line.
}
An assignment expression's result is always the value that was assigned, including when assigning to a boolean. This is covered by JLS§15.26:
At run time, the result of the assignment expression is the value of the variable after the assignment has occurred.
So yes, configuredPdf = true assigns true to configuredPdf, and the result of that expression is true.
Similarly, x = y = 5; assigns 5 to y, and the result of y = 5 is 5, which is then assigned to x.
Fundamentally, what you wanted was:
if (configuredPdf)
There's never any need to compare a boolean variable with true or false, just use the if (theVariable) (for comparing with true) or if (!theVariable) (for comparing with false). Getting in that habit will protect you from inadvertent assignment.
The only time actually comparing boolean values is useful is when they're both variables, e.g. if (thisFlag == thatFlag) or if (thisFlag != thatFlag).
To avoid accidental assignment in that situation, either:
Use a linter that checks for this
"double bang" the first flag:
if (!!thisFlag == thatFlag)
...although as you pointed out if you can accidentally type = instead of ==, presumably you can accidentally type ! instead of !! :-)
Use an old C idiom (this is what I use):
if (!thisFlag == !thatFlag)
What is happening is when the compiler comes to the if condition in your code, it assigns 'configuredpdf' to be true. Thus the condition
if(configuredpdf = true)
Becomes true and the loop executes successfully. However, the problem arises when we DON'T want this loop to be true. At that time when, for a given input, the compiler parses the if condition, it forcibly becomes true and executes the code written in if condition executes even if the data entered does not agreeing. That is why you will find that your code has a bug at the if condition.
configuredPdf must be a boolean for if(configuredPdf = true) to compile.
configuredPdf = true will assign true to configuredPdf and thus if will succeed.
I am learning Android and taking the MOOC offered by Maryland University.
In one of the lectures I noticed the following line of code:
String output = (val == answer) ? "42" : "We may never know";
My guess is that this is equivalent to:
if(val == answer){
String output = "42";
}else{
String output = "We may never know";
}
Is my assumption correct?
PS: Is there anywhere besides coursera where I can take certified android classes online?
You are almost correct, it's actually like this:
String output;
if(val == answer){
output = "42";
}else{
output = "We may never know";
}
BR Erik
Your assumption is almost correct. The ternary expression would be more accurately represented as:
String output;
if (val == answer) {
output = "42";
}
else {
output = "We may never know";
}
In your original version, output is only available within the scope of the if/else blocks, since you declare it inside them. Declaring it outside the scope means you'll be able to use the value later. However, as Hariharan pointed out, using == for string comparison is a no-no in Java; you're comparing the raw objects, not the string contents. You'll want to replace your val == answer with val.equals(answer) to get a proper result.
Edit: If val and answer aren't strings, disregard the portion about using .equals(). I (and apparently everyone else who answered this question) made the bad assumption that they were, since everything else was strings. .equals() should be used for strings and any other complex object, == can be safely used for primitives.
Yes, you are correct (almost). It's called ternary operator. Your logic is good but you must take care that the variable is initialized outside of the if-else statement.
String output;
if (val == answer) {
output = "42";
} else {
output = "We may never know";
}
If the variable would be defined inside if and else blocks you would not be able to use it after the } sign because it would fall out of the scope.
Yes, you are totally right. It's so called ternary operator. take a look here and here
And a small note: it's weird to declare the same variable twice inside conditional blocks. Declare it somewhere outside .
Currently I'm using:
int a=10;
if(a=20)
printf("TRUE");
else
printf("false");
Which prints, in C, the value TRUE.
But in case of java:
int a=10;
if(a=20)
System.out.println("TRUE");
else
System.out.println("FALSE");
I'll get a compile time error about an incompatible type.
The reason for that is that in C there is no specific type boolean - instead any non-0 integer evaluates to a boolean "true". Thus in your C code:
if(a=20)
a is assigned the value 20, which is non-0 - and the condition is evaluated as true
In java, there's a fundamental type boolean and the value of the conditional inside if must be of this type.
a=20
in Java assigns 20 to a and returns the final result of evaluation as integer value 20, however type boolean is expected - hence you're getting a compile-time error about the incompatible types.
If you want to do a comparison of a with 20, however, you need to use == operator both in C and Java:
if(a == 20)
This will compile in both C and Java and print FALSE in both languages.
You need to replace = with ==.
= is an assignment operator
int a=10;
if(a==20){
System.out.println("TRUE");}
else{
System.out.println("FALSE");}
This should work fine.
Edit:
In C, the returned integer value of the assignment (in this case 20) is a positive int, which evaluates to true.
In java, a boolean is expected.
(See the more thorough answer provided by Aleks G)
A single = is an assignment. If you want to test for equality, you use the double == in both C and Java.
It should be evident that you're doing the wrong thing, even in the C version, since you set a to 10 and then, on "comparing" it to 20, you get a true value. I'm not aware of any mathematical systems where 10 and 20 are considered equal :-)
What happens in your C case is that the assignment actually "returns" a value as well.
The statement:
if (a = 20) ...
is equivalent to:
a = 20;
if (a) ...
so it first sets a to 20, then uses that as the if condition. Since 0 is false and anything else is true, the body of the if is executed.
A good compiler (like gcc) will actually warn you of what you're doing so that you don't get caught out by these little things. Some people also use the trick of putting constants first:
if (20 == a) ...
so that, if you mistakenly use assignment, it's a syntax error. But I find that sort of code ugly, especially since I mostly use those good compilers mentioned above :-)
The reason you get an error in Java is because it's much more strict on what you can do with assignments. By that, I mean there is no automatic conversion from int to boolean as with C. So this code refuses to compile, producing an error:
class Test {
static public void main(String[] args) {
int a = 10;
if (a = 20)
System.out.println ("true");
}
}
But you can still get burnt with something like this:
class Test {
static public void main(String[] args) {
boolean a = false;
if (a = true)
System.out.println ("true");
}
}
Because that assignment is of a boolean value inside the if, it doesn't cause a compilation error due to the wrong type. However, since it prints true, it's still not what you wanted.
Bottom line, go back an re-read that first paragraph. = is assignment, == is equality checking.
Use the == to test the condition instead of =. That way, you are assigning 20 to a and not testing for a condition.
if (a==20) ... or
System.out.println(a==20);
value of a=20 is 20. You should use == operator.
for comparison you should use ==
if(a==20) instead of a=20, which is assignment
I have an array in containing numbers that represent cable sizes (1, 1.5, 2.5, etc), stored as strings.
In my program, the array is loaded into a spinner, which is working fine.
However, when the item is selected and stored in a variable, I want to check what string was selected, and set another numerical variable to 2.5 so I can do a calculation later in the program.
I tried the following:
if (conductorSize = "1" ) {conCsa = 1;}
else if (conductorSize = "1.5") {conCsa = 1.5;}
conductorSize being the variable holding the selected string, and conCsa being the variable
set to a numerical variable for calculation.
The compiler says that I cannot convert a string to boolean. What's happening?
If you are doing string comparisons, use .equals()
Example taken from here:
String s = "something", t = "maybe something else";
if (s == t) // Legal, but usually WRONG.
if (s.equals(t)) // RIGHT <<<<<<<<<<<<< Use this.
if (s > t) // ILLEGAL
if (s.compareTo(t) > 0) // CORRECT>
As Ed S. points out you are using the assignment operator. However since you are comparing a String you need to use the equals method.
if ("1".equals(conductorSize)) {conCsa = 1;}
else if ("1.5".equals(conductorSize)) {conCsa = 1.5;}
Alternatively, you could just create a new float from your String:
float conCsa;
try {
conCsa = Float.parseFloat(conductorSize);
}catch(NumberFormatException e){
conCsa = 0.0f; //set to a default value
}
It looks like what you're trying to do might better be expressed in this way:
conCsa = Double.parseDouble(conductorSize);
In general you need to use the .equals() method.
If performance is extremely important and you are comparing against string literals, take a look at String.intern(). It'll allow you to do super-fast == comparisons and avoid a full character-by-character scan as in .equals().
Performance would have to be really, really important though, to justify such a non-standard approach.
When you have cable sizes which are constants, you need to use Enums , which will help you in reducing no of if condition comparisons.
I was trying to write a simple method:
boolean validate(MyObject o)
{
// propertyA && propertyB are not primitive types.
return o.getPropertyA() == null && o.getPropertyB() == null;
}
And got a strange error on the == null part:
Syntax error on token ==. Invalid
assignment operator.
Maybe my Java is rusty after a season in PLSQL. So I tried a simpler example:
Integer i = 4;
i == null;
// compile error: Syntax error on token ==. Invalid assignment operator.
Integer i2 = 4;
if (i == null); //No problem
How can this be?
I'm using jdk160_05.
To clarify: I'm not trying to assign anything, just do an && operation between two boolean values. I don't want to do this:
if (o.propertyA() == null && o.propertyB() == null) { return true; }
else { return false; }
== is not an assignment operator, it's a boolean equality operator, see:
http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.21.2
If you want to set i to null use the simple assignment operator =:
i = null;
http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.26.1
If you want to check that i is null then you need to use the == operator
if (i == null)
I don't think you are confusing assignment and equality comparison. I think your compiler is just giving you a confusing error message. This program:
Integer i = 4;
i ==null;
should give an error something like this:
Program.java:8: not a statement
i ==null;
Your first program should compile correctly. Perhaps there is some invisible unicode character in the text that is confusing the compiler. Try deleting the entire function and typing it in again.
I think I see your problem. I'm sorry the other answers don't address it.
So, Java has this idea that is shared by some other languages that just because something is a valid expression doesn't mean that that thing, by itself, is a valid statement.
For example, this code will complain similarly:
Integer i = 4;
i+3; // this line gives a compilation error
And yet obviously I can use i+3 (go unboxing!) elsewhere to mean "7":
System.out.println(i+3); // this is fine
It gets a bit confusing because unlike some languages that have this expression/statement distinction, java allows you to use any method call - whether it returns a value or not - as a statement. However, most java operators do not - by themselves - form a valid statement.
Likewise, this fails to compile:
Integer i = 4;
i; // this line gives a compilation error
For the full gory details, see http://java.sun.com/docs/books/jls/second_edition/html/statements.doc.html#32588
In PL/SQL, assigning a value to a variable is done with the := operator. Comparing two values is done with =.
In Java, assigning a value to a variable is done with the = operator. Comparing two values is done with ==, or a .equals() method in some cases.
You can do things like this:
x = i==null;
This will test if i is null and if so, the value true will be assigned to x (assuming that x is a boolean).