Why does jshell show this number? - java

I am learning java and this logic makes me feel confused.
Isn't here i=20(+1)+20(+1)?
Why 41 instead of 42?
jshell> int i = 20
i ==> 20
jshell> i=i++ + i++
i ==> 41
See this code run at Ideone.com.

Effectively, the expression i=i++ + i++; is equal to i=i++ + i;. Why? The latter i++ result value is never used and is not propagated. The result of the postfix addition i++ is used as long as the value i is added later in the expression and the result takes the effect. However, after the latter i++ the result value of i is not used.
If you want to achieve the result of 42, you need to perform the postfix assignment (i++) after the whole result is assigned back to the i variable:
int i = 20;
i = i++ + i;
i++;
System.out.println(i);

Related

What does the semicolon actually do?

I was looking at a typical for loop:
class ForDemo {
public static void main(String[] args){
for(int i=1; i<11; i++){
System.out.println("Count is: " + i);
}
}
}
I am happy with the semicolons after int i=1: it is a statement which declares the new variable i. If i++ is also a statement, why doesn't it have a semicolon after?
Another example. I opened the Jshell and put the following:
jshell> int a=1;
a ==> 1
jshell> a++
$2 ==> 1
jshell> a
a ==> 2
jshell> int b=1;
b ==> 1
jshell> b++;
$5 ==> 1
jshell> b
b ==> 2
In other words the command ++ works, independently from whether there is a semicolon or not. I expected not to work without it.
Last example (adapted from a presentation about the difference between = and ==):
jshell> boolean x = false;
x ==> false
jshell> if (x = true) System.out.println("Sorry! This is wrong ...");
Sorry! This is wrong ...
jshell> boolean x = false;
x ==> false
jshell> if (x = true;) System.out.println("Sorry! This is wrong ...");
| Error:
| ')' expected
| if (x = true;) System.out.println("Sorry! This is wrong ...");
| ^
I get the point about the difference between = and ==. My question is why it works in the first half (if (x = true) without ;), and not with a ; (if (x = true;)).
Apologies for the several examples, but I think the question is relatively straightforward: if there are instances where an expression (without ;) works as a command statement (with ;), what is the function of semicolons?
The semicolon does nothing, it is there because a for loop is (amongst others) defined as
BasicForStatement:
for ( ForInitopt ; Expressionopt ; ForUpdateopt ) Statement
according to https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html
There are by definition two semicolons between the three parts.
The semiccolon is a separator of stack calls. The inside of if() wants a boolean, not a stack call.
Only inside the {} are statements expected.
The inside of for() expects three stack calls: One defining the loop variable, one defining the breaking clause and one defining what happens after each loop.
Example:
The construct for(;;); is a valid java construct. But you should never use it as the only thing it would do is loop over nothing forever: You don't define a variable, a breaking condition or something that gets executed after each call. During the loop you also just do nothing.

Java: Difference between +--i and +++i

Last day while programming, I mistakenly wrote something like this-
int i = 2;
int j = 3;
int a = i+++j;
And it did not shoot any error and I got-
a = 5
After detecting this coding error I was curious. So, I started playing with it. When I changed it a little-
int a = i+ ++j;
I got-
a = 6
With this-
int a = i+ + +j;
and this-
int a = i++ +j;
I again got-
a = 5
Similar situation was experienced here.
But here comes the weird part. There is no difference between a = i+--j & a = i+ --j. Both gives-
a = 4
Why is that? I completely understand what exactly is happening here. The thing I do not understand is- 'WHY?'. + and - are both operators, then why there is a difference?
For clarity, I wish to share another odd experience. This code works perfectly-
int i=0;
System.out.println("value: "+--i);
And outputs-
value: -1
But this-
System.out.println("value: "+++i);
Gives following error-
error: unexpected type
As #Bunti pointed out, your answer is in the Operator Precedence.
When you do,
int a = i+++j;
It's evaluated as int a = (i++) + j since Postfix has the highest precedence.
Now you know why you get a = 5 there. Print i along with a and you will see it's incremented.
Similarly, when you do System.out.println("value: "+++i);, it's evaluated to System.out.println(("value: "++) + i);
But postfix operations are not applicable to String. Hence the syntax error.
But when you do, System.out.println("value: "+--i);, this is evaluated to System.out.println("value: "+ (--i));. Hence it works just fine.
Operator precedence is only half of the answer, since the first thing to clarify is what the operators in your code are.
Basically i+++j could be interpreted as i ++ + j, as i + ++ j or as i + + + j.
However according to the lexical rules of Java (https://docs.oracle.com/javase/specs/jls/se7/html/jls-3.html#jls-3.2) the interpretation is the same as if the expression was written as i ++ + j.
According to the operator precedence this is evaluated is (i++) + j, so that in int a = i++ + j; a is 5 (and i is 3!).
For i+--j the tokens are i + -- j (since the is no operator +-), which is according to operator precedence i + (--j), so that in int a = i + --j; a is 4 (and j is now 2).
Now comes the fun part:
What is int a = i + + + j;? This is the same as int a = i + (+(+j)); (+j being the unary plus operation on j), so this gives again 5 (but i is still 2 and j is still 3, which is different from the case i++ + j!)
And what is int a = i + - - j;? This is the same as int a = i + (-(-j)); (-j being the unary minus operation on j) which also gives 5 (and also does not modify i or j).
What is int a = i++++j;? This is not a valid Java expression (it will not compile), since this is equivalent to (i++) ++ j and since i++ cannot be converted to a variable this is illegal (https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.14.2) and then there is this dangling j too.
Adding more + without adding spaces does not make it legal, while i++ + ++j is perfectly legal...
Similarly, "SomeString"+++i is illegal, since this is read as ("SomeString"++)+i and you can't increment a String literal (and also not a String variable).
"SomeString"+--i is valid, since this is read as "SomeString"+(--i), which appends the result of --i to "SomeString".
Many of them have written answers for this. I would like to put it in different words.
i++ is post fix.
In post fix operation, value is incremented after the value is extracted.
Thus in case of i+++j, we have original value of i when expression is evaluated, and i is incremented after the evaluation is completed.
In case of ++j since its prefix value is incremented before evaluation.
This i+++j is equal to (i++)+j and i+ ++j is equivalent to i + (++j).
Hope this adds this helps adding to your understanding.
Hope this answers the behavior of arithmetic operation-
int i = 2;
int j = 3;
int a = i+++j;
a=5 as there is no space between the + symbol. Even if you put any more + symbols in between, the answer will remain the same. To explain its working, it is similar to any basic calculator we use, if i input a number and type + for any number of times, the second input when received will still give the sum of the 2 input-ed numbers. This is because the compiler is initializing the addition operation between the 2 numbers.
int a = i+ ++j;
Here in this case, you are adding the i to the incremented value of j. So it is like u are looking for an operation of 2+ ++3, which is 2+4 and hence the answer 6. the ++ operator is defined as an increment in the JRE.
int a = i+ + +j;
Here it behaves same as the 1st case as +j or i+ are not increment operators defined by JRE.
int a = i+--j;
In this interesting case, we are using 2 diff arithmetic operators i.e. + and --. As -- is defined, the decrement of j value happens and the change value of j is added to i.
int a = i+ --j;
As in above, since + and - are diff operations. the space between them or not doesn't matter.
int i=0;
System.out.println("value: "+--i);
In this case, we are printing a string and using +--i; so JRE treats it as printing out Value: decrement of i. As known in print statement, + is used to make system print multiple value at a time.
System.out.println("value: "+++i);
coming to this, the + in print function is defined to provide a way to print several variable that are separated by a + symbol and hence the conjunction of +++ is not defined for print function and hence gives an error.
May be the i+++j just is i+j, but the i+ ++j is i + ++j, there ++j change's , 'j=4'. So i[2] + j[4] = 6.
Java May not recognize three +++.

Strings and Loops Practice Test

I'm slightly confused on this test question. I made a chart of the values of i , j, and the string. I got "nbearig", but my runtime is printing out numbers. I'm not sure where I went wrong. ++i , --j means that they were incre/decremented before the code after the for loop right?
public class AlGore {
public static void main(String[] args) {
String mystery = "mnerigpaba";
String solved = "";
int len = mystery.length();
for (int i = 0, j = len - 1; i < len/2; ++i, --j) {
solved += mystery.charAt(i) + mystery.charAt(j);
}
System.out.println(solved);
}
}
I'm not sure where I went wrong. ++i , --j means that they were incre/decremented before the code after the for loop right?
1) They were preincremented / predecremented respectively.
2) It happened after each execution of the loop body.
my compiler is printing out numbers.
No it isn't. The compiler is compiling your code!!! The JVM is printing numbers ... when you run the code.
To understand the reason why, take a careful look at this:
solved += mystery.charAt(i) + mystery.charAt(j);
This is equivalent to
solved = solved + ( mystery.charAt(i) + mystery.charAt(j) );
Now the expression in brackets performs a numeric addition of a character to a character. According to the rules of Java expressions, that gives an int value. So the entire expression becomes:
solved = String.concat(
solved,
Integer.toString(mystery.charAt(i) + mystery.charAt(j));
I thought that the charAt(i) function will return a string?
No. It returns a char ... just like the method name "charAt" implies. String and char are fundamentally different types.
Comment: That is a good exam question, it tests how well you understand loops, and how well you understand Java expression semantics.
You are performing integer math (because char is an integral type),
// solved += mystery.charAt(i) + mystery.charAt(j);
solved += Character.toString(mystery.charAt(i))
+ Character.toString(mystery.charAt(j));
That way you are performing String concatenation.
mystery.charAt(i) + mystery.charAt(j); will add the numeric values of those two characters. You can force string concatenation by adding "" + before:
solved += "" + mystery.charAt(i) + mystery.charAt(j);

Java String += Shorthand explanation needed

While I was creating a program to compress a string I ran into this strange problem, I will paste the code snippets with their outputs, I would like someone to clearly explain why this is happening.
The first code snippet: here if same letter appears consecutively, then the successive occurrences of the letter is replaced by the total count of same letters. Ex: aaabbb should be written as a3b3.
public static String compress(String str){
String compressed = "";
char prev = str.charAt(0);
int count = 1;
for (int i = 1; i < str.length(); i++) {
char curr = str.charAt(i);
if (curr == prev) { // in case curr is equal to prev
count++;
} else { // in case curr is not equal to prev
//compressed=compressed+prev+count;
compressed+=prev+count; // Shorthand used here
count=1;
prev=curr;
}
}
compressed=compressed+prev+count; // Shorthand not used
System.out.println(compressed);
return compressed;
}
the output for this above code when inputted with aabbccaabbccaabbccaabb is 99100101991001019910010199b2, observe the last two elements of the output, this is because outside the loop, shorthand is not used. If I write the expression as compressed = compressed +prev+count inside the loop, I'll get the intended output.
I thought this output is because the operation is messing with the address of the String. But the next code confused me again.
String prev= "abc";
String curr = "def";
String result="";
result+=prev+curr;
System.out.println(result);
I think this is because the right hand operation is performing an ASCII addition, I cannot come to a conclusion, can anyone clarify.
I am sleep deprived and hence I am not able to come to a conclusion, hence asking someone to clarify my trivial doubt.
It has nothing to do with the reference. When you did prev+count ascii value of the character in prev is added with the integer count. In this case :
ascii of "a" is 97, and it occurred twice... so 97 +2 = 99 ..
ascii of "b" is 98, and it occurred twice... so 98 +2 = 100 ..
ascii of "c" is 99, and it occurred twice... so 99 +2 = 101 ..
that's why the output is 99100101991001019910010199100
try this : compressed+=(""+prev)+count; // Shorthand used here
In this case, or in compressed+=""+prev+count case, since the operation happens from left to right, the + operator is applied on a string ("") and char(prev) and behaves like append and also returns a string. The resulting string is then appened with another int (prev)
A better way is using a StringBuilder
Take a look at this subject and at JLS 15.18.1 section :
You see this behavior as a result of the combination of operator
precedence and string conversion.
JLS 15.18.1 states:
If only one operand expression is of type String, then string conversion (ยง5.1.11) is performed on the other operand to produce a
string at run time.
Therefore the right hand operands in your first expression are
implicitly converted to string: string = string + ((char)65) + 5;
For the second expression however string += ((char)65) + 5; the +=
compound assignment operator has to be considered along with +.
Since += is weaker than +, the + operator is evaluated first.
There we have a char and an int which results in a binary numeric
promotion to int. Only then += is evaluated, but at this time
the result of the expression involving the + operator has already been evaluated.
Whenever you add a char to an int in java first it converts the character into its equivalent ASCII value and then adds it to the integer
eg suppose the following scenario ,
char c = 'a'; // ASCII value of 'a' is 97
int i = c + 5 ; // result will be 97 + 5 = 102
I think this answers your first half question
Now the Second part ,
Whenever you use the shorthand operator in Java the expression at right hand side is evaluated first.
Hence , for expresion
result += prev + curr it is evaluated as
result = result + (prev + curr);
Therefore ,
result+=prev+curr; // Here first it appends "abc" with "def" and then the resultant "abcdef" is appended to as result .
you can convert your charater value "prev" to string and than append count to it.
compressed += Character.toString(prev) + count;

Java .split weird outcome

I'm trying to split up a string, but it doesn't seem to give the correct output
this is the string being passed around
1#0:250:250:
I first do this
String[] dataArray = data.split("#");
this gives me
1
0:250:250:
I then do this
for( int i = 0; i < totalPlayers; i++)
{
String[] pos = dataArray[i++].split(":");
if( Integer.parseInt( pos[0] ) == ID )
{
//do nothing
}
else
{
assets[i].setPosition( Integer.parseInt( pos[1] ), Integer.parseInt( pos[2] ) );
}
}
I get an error saying ArrayIndexOutOfBoundsException, if i print out pos[0] i get 1, if i print out pos[1] i get ArrayIndexOutOfBoundsException,
Why isn't my string being split up into
0
250
250
?
Cheers
Canvas
You have an error in your code that is causing it to split 1 instead of 0:250:250: . Recall that the postfix increment operator (e.g. i++) increments the variable after it is used in the expression. So the first line in the loop is really saying String[] pos = dataArray[i].split(":"); i = i + 1; .
The simple fix would be to change i++ to ++i, which would essentially make the line run as i = i + 1; String[] pos = dataArray[i].split(":"); . However, this exact bug is why using ++ operators inside complex statements can be confusing and is often discouraged. Moreover, incrementing your loop variable outside of your for statement can lead to additional confusion.
Since the idea you really want to express is 'loop through the array by pairs', I would recommend writing something like
for (int i = 0; i < totalPlayers; i += 2) {
String[] pos = dataArray[i + 1].split(":");
// (the same as above)
}
For the first time, i will be 0. That essentially means dataArray[0], which is 1. Hence, when you do this:-
String[] pos = dataArray[i++].split(":");
Your pos has only 1 element in the array (i.e.) pos[0] which is 1. Therefore, if you try to access pos[1] or pos[2], you'll get the ArrayIndexOutOfBoundsException.
pos is created twice, once with only 1 as an element. the second time it will have 0, 250, 250.
I believe this problem is due to the fact that the split function takes a regular expression (regex).
Because the colon is a special character in regex, you must escape it with a backslash.
In Java, you must escape a backslash with another backslash.
So, try splitting on "\\:" instead of just ":"

Categories