I am currently learning Java, and I'm trying to understand the logic behind math in Java. On old tests in this course, there have been problems like the ones below. I am then supposed to write out what this code is going to display. My problem is that I don't understand two of the numbers in both codes.
In the first test class, the integer Tal prints out as 15. Ok, I can follow the logic there.
It goes like this:
c.setNbrOf(4+1) = 5
int tal = c.getNbrOf()+10 = 15
BUT
When I apply the same logic to the second test class I get the wrong answer.
My logic goes:
c.setNbrOf(4+1) = 5
c2.setNbrOf(5) +1 = 6
Since Customer c = c2, this means c also has the value of 6 (?)
So, int tal = 6 + 5 which is 11.
It's not though. When I run it, it's 12.
Why does the ++tal in the method andra affect its value globally? I thought it was only local.
I hope I haven't been to unclear.
The customer class is needed to run the test class.
public class Customer {
private String name;
private int nbrOf;
public String getName() {
return this.name;
}
public void setName(String name) {
this.name=name;
}
public int getNbrOf() {
return this.nbrOf;
}
public void setNbrOf (int nbrOf) {
this.nbrOf=nbrOf;
}
}
The first test class.
public class Test {
public static void main(String[] args) {
Customer c = new Customer();
c.setName("Kund1");
c.setNbrOf(4+1);
int tal = c.getNbrOf()+10;
System.out.println("Namn: "+c.getName()+" ålder: "+c.getNbrOf());
foo(c, tal+3);
System.out.println("Namn: "+c.getName()+" ålder: "+c.getNbrOf());
System.out.println("Tal: "+tal);
}
public static void foo(Customer p, int x) {
p.setName("Kund2");
p.setNbrOf(x);
x ++;
}
}
The second.
public class Test {
public static void main(String[] args) {
Customer c = new Customer();
c.setName("K1");
Customer c2 = c;
c.setNbrOf(4+1);
c2.setNbrOf(c.getNbrOf()+1);
int tal = c.getNbrOf()+5;
System.out.println("Namn: "+c.getName()+" ålder: "+c2.getNbrOf());
andra(c, ++tal);
System.out.println("Namn: "+c.getName()+" ålder: "+c.getNbrOf()+",
"Tal: "+tal);
}
public static void andra(Customer p, int tal) {
p.setName("K2");
tal=9;
p.setNbrOf(tal);
}
}
When you write ++tal, it means tal = tal + 1; then return the new value of tal as a result. Hence, when you pass ++tal to a function, you have run two commands.
Also, you should be aware that setting value of tal inside andra function, is local and not changed the value of tal outside the function. Hence, the final value of tal after calling andra(c, ++tal) would be 12.
[EDIT] Fixed the incorrect part about pass by value and clone()
You are asking two questions so let's attach each one separately.
A) What is the value of c and c2 at specific points in the code.
To answer this you need to realize that just saying 'c = c2' doesn't tell the full story. You first create two instances of the Customer object and store the references to them in c and c2 respectively. When you assign c = c2 you are making both variable store the reference to the same (single) instance of Customer; the other will get garbage collected. Now, it is possible to change the state of the remaining object through method calls to either c OR c2 because they both refer to the same instance.
This means that
c.setNbrOf(4+1); // AAA
c2.setNbrOf(c.getNbrOf()+1); // BBB
changes the value of the same nbrOf member variable twice, it just looks like they are separate because you have made c an alias of c2 (or vice versa depending on how you want to look at it). After line AAA c.nbrOf does equal 5; to calculate what happens in line BBB you need to break the line up into its parts. Calling c2.setNbrOf() with an argument that is actually an expression of the sum of two things, the result of a call to c.getNbrOf() and the numeric literal '1'. The call to c.getNbrOf() returns 5 and the expression adds 1 to it before passing the result, 6, to the call of c2.setNbrOf(). Since c and c2 are aliases of each other you will get a result of '6' when you call getNbrOf using either c or c2 simply because they both point to the same instance.
B) Why does the ++tal in the method andra affect it's value globally?
Well, it doesn't affect the value globally, it only looks that way because again, you have run into an expression used as an argument to a method.
andra(c, ++tal); // CCC
The call to andra() does not pass '++tal' into the method, it evaluates the expression first, which actually increments tal by 1 in the local scope and then evaluates the value of tal to determine the value to be sent to the method call. This means that, yes, tal was 11 before the line CCC but during the evaluation of the arguments the variable's value was changed to 12 before the call is made. So why does the code print '12' when you can clearly see that
public static void andra(Customer p, int tal) {
p.setName("K2");
tal=9; // DDD
p.setNbrOf(tal);
}
line DDD should result in the value of p.nbrOf being 9? Well, yes, the value of p.nbrOf does get changed to '9' in the line following DDD, just as p.name gets changed to "K2". This leads to your question of why the code prints '12' instead of '9'. This is because of another thing you have to consider and that is scope. The method andra() actually creates a new storage location named 'tal' that is not the same location as the variable with the same name in main(), that is andra() is hiding the name 'tal' so that when it changes the value of 'tal' to 9 it is only changing the local variable and not the variable with the same name in the calling code.
I have to say that this sample code is doing several things to trip you up, which also means it's doing its job to help you understand the different ways the language handles its symbol table that can be confusing. The sample code isn't making it any better by using tal as a local variable in the test code AND as a parameter name in the methods, that is a poor practice but was used here to make the exercise more difficult.
Try this code to see what is actually happening.
// actually Test3 would be a better name, but I'll leave that to you
public class Test {
public static void main(String[] args) {
Customer c = new Customer();
c.setName("K1");
Customer c2 = c;
c.setNbrOf(4+1);
c2.setNbrOf(c.getNbrOf()+1);
int tal = c.getNbrOf()+5;
int tal2 = ++tal;
System.out.println("Namn: "+c.getName()+" ålder: "+c2.getNbrOf()+" reference to c:"+ c);
andra(c, tal2);
System.out.println("Namn: "+c.getName()+" ålder: "+c.getNbrOf()+",
Tal: "+tal);
}
public static void andra(Customer p, int tal3) {
p.setName("K2");
tal3=9;
System.out.println("BEFORE - reference to p: "+p+" tal: "+tal3+" p.nbrOf:"+p.getNbrOf());
p.setNbrOf(tal3);
System.out.println("AFTER - reference to p: "+p+" tal: "+tal3+" p.nbrOf:"+p.getNbrOf());
}
}
This should show several things, the reference to p should be a different value than the reference held in c, using unique variable and parameter names should make it clearer about which variables are being evaluated or changed, and moving the ++tal expression to outside the method call should show how the variable is not being changed from within andra().
c = c2 - this line means that from now you want c to point to the same space in memory that holds c2. From now all changes in c or c2 will affect in the same change in the value of the other one (two different refferences point to the same object)
andra(c, ++tal);
is:
tal = tal + 1; //12
andra(c, tal);
andra(c, ++tal); is the same as:
tal = tal + 1;
andra(c, tal);
While andra(c, tal++); is similar to:
andra(c, tal);
tal = tal + 1;
The pre-increment and post-increment operators increment the value prior to (pre) or after (post) evaluating the expression. This is not a "local" vs "global" scope. It affects the scope of the variable that is within scope.
Also, in your andra method, you are explicitly setting tal = 9 so it ignores the passed argument.
since we actually only have one object here, we could ignore OO here and write it in plain math:
if c2 = c, then there is only one object, therefore only one NbrOf
c.setNbrOf(4+1);
NbrOf = 4 + 1 = 5
c2.setNbrOf(c.getNbrOf()+1);
NbrOf = NbrOf + 1 = 5 + 1 = 6
int tal = c.getNbrOf()+5;
int tal = NbrOf + 5 = 6 + 5 = 11;
andra(c, ++tal);
this increases tal by 1 and assigns that value to tal, its equivalent to
tal = tal + 1;
andra(c, tal);
however, the tal inside of andra(c, tal); is an copied value (all primitives are passed by copy, not by reference. So assigning tal=9 wont affect the outside tal! Rename it inside andra(c, tal); to make it easier to understand.
conclusion, tal = 12
Related
I know this is probably very stupid, but a lot of places claim that the Integer class in Java is immutable, yet the following code:
Integer a=3;
Integer b=3;
a+=b;
System.out.println(a);
Executes without any trouble giving the (expected) result 6. So effectively the value of a has changed. Doesn't that mean Integer is mutable?
Secondary question and a little offtopic: "Immutable classes do not need copy constructors". Anyone care to explain why?
Immutable does not mean that a can never equal another value. For example, String is immutable too, but I can still do this:
String str = "hello";
// str equals "hello"
str = str + "world";
// now str equals "helloworld"
str was not changed, rather str is now a completely newly instantiated object, just as your Integer is. So the value of a did not mutate, but it was replaced with a completely new object, i.e. new Integer(6).
a is a "reference" to some Integer(3), your shorthand a+=b really means do this:
a = new Integer(3 + 3)
So no, Integers are not mutable, but the variables that point to them are*.
*It's possible to have immutable variables, these are denoted by the keyword final, which means that the reference may not change.
final Integer a = 3;
final Integer b = 3;
a += b; // compile error, the variable `a` is immutable, too.
You can determine that the object has changed using System.identityHashCode() (A better way is to use plain == however its not as obvious that the reference rather than the value has changed)
Integer a = 3;
System.out.println("before a +=3; a="+a+" id="+Integer.toHexString(System.identityHashCode(a)));
a += 3;
System.out.println("after a +=3; a="+a+" id="+Integer.toHexString(System.identityHashCode(a)));
prints
before a +=3; a=3 id=70f9f9d8
after a +=3; a=6 id=2b820dda
You can see the underlying "id" of the object a refers to has changed.
To the initial question asked,
Integer a=3;
Integer b=3;
a+=b;
System.out.println(a);
Integer is immutable, so what has happened above is 'a' has changed to a new reference of value 6. The initial value 3 is left with no reference in the memory (it has not been changed), so it can be garbage collected.
If this happens to a String, it will keep in the pool (in PermGen space) for longer period than the Integers as it expects to have references.
Yes Integer is immutable.
A is a reference which points to an object. When you run a += 3, that reassigns A to reference a new Integer object, with a different value.
You never modified the original object, rather you pointed the reference to a different object.
Read about the difference between objects and references here.
Immutable does not mean that you cannot change value for a variable. It just means that any new assignment creates a new object ( assigns it a new memory location) and then the value gets assigned to it.
To understand this for yourself, perform Integer assignment in a loop ( with integer declared outside the loop ) and look at the live objects in memory.
The reason why copy constructor is not needed for immutable objects is simple common sense. Since each assignment creates a new object, the language technically creates a copy already, so you do not have to create another copy.
This is how I understand immutable
int a=3;
int b=a;
b=b+5;
System.out.println(a); //this returns 3
System.out.println(b); //this returns 8
If int could mutate, "a" would print 8 but it does not because it is immutable, thats why it is 3. Your example is just a new assignment.
"Immutable classes do not need copy constructors". Anyone care to explain why?
The reason is that there is rarely any need to copy (or even any point in copying) an instance of a immutable class. The copy of the object should be "the same as" the original, and if it is the same, there should be no need to create it.
There are some underlying assumptions though:
It assumes that your application does not place any meaning on the object identity of instances of the class.
It assumes that the class has overloaded equals and hashCode so that a copy of an instance would be "the same as" the original ... according to these methods.
Either or both of those assumptions could be false, and that might warrant the addition of a copy constructor.
I can make clear that Integer (and other of its creed like Float, Short etc) are immutable by simple sample code:
Sample Code
public class Test{
public static void main(String... args){
Integer i = 100;
StringBuilder sb = new StringBuilder("Hi");
Test c = new Test();
c.doInteger(i);
c.doStringBuilder(sb);
System.out.println(sb.append(i)); //Expected result if Integer is mutable is Hi there 1000
}
private void doInteger(Integer i){
i=1000;
}
private void doStringBuilder(StringBuilder sb){
sb.append(" there");
}
}
Actual Result
The result comes to he Hi There 100 instead of expected result (in case of both sb and i being mutable objects) Hi There 1000
This shows the object created by i in main is not modified, whereas the sb is modified.
So StringBuilder demonstrated mutable behavior but not Integer.
So Integer is Immutable. Hence Proved
Another code without only Integer:
public class Test{
public static void main(String... args){
Integer i = 100;
Test c = new Test();
c.doInteger(i);
System.out.println(i); //Expected result is 1000 in case Integer is mutable
}
private void doInteger(Integer i){
i=1000;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
String s1="Hi";
String s2=s1;
s1="Bye";
System.out.println(s2); //Hi (if String was mutable output would be: Bye)
System.out.println(s1); //Bye
Integer i=1000;
Integer i2=i;
i=5000;
System.out.println(i2); // 1000
System.out.println(i); // 5000
int j=1000;
int j2=j;
j=5000;
System.out.println(j2); // 1000
System.out.println(j); // 5000
char c='a';
char b=c;
c='d';
System.out.println(c); // d
System.out.println(b); // a
}
Output is :
Hi
Bye
1000
5000
1000
5000
d
a
So char is mutable , String Integer and int are immutable.
Copy and run this code,I hope this will answer all your doubts
private static void wrapperClassDemo() {
//checking wrapper class immutability using valueOf method
//We can create wrapper class by using either "new" keyword or using a static method "valueOf()"
//The below Example clarifies the immutability concept of wrapper class in detail
//For better understanding just ciopy the below code to the editor and run
Integer num1 =Integer.valueOf(34); // i'm passing the 34 as the parameter to the valueOf method
System.out.println("value assigned to num1 is : "+num1);
System.out.println("Printing the hashcode assigned to store the \" num1 \"value in memory: "+System.identityHashCode(num1));
Integer num2 =Integer.valueOf(34);
System.out.println("value assigned to num2 is : "+num2);
System.out.println("Printing the hashcode assigned to store the \" num2 \"value in memory: "+System.identityHashCode(num2));
/*Now u can notice both the hashcode value of num1 and num2 are same. that is because once you created the num1 with the value 34 an object is
* created in the heap memory. And now You are passing the value same as num1 to the num2 .Now JVM Checks the same value is present in the heap Mmeomry
* If present the reference variable(in this example it is num2) will be pointed to the same address where the object num1 is stored so u get the same hashcode */
num2++; // You can use num2 = 35 as both are same;
System.out.println("\nvalue assigned to num2 is : "+num2);
System.out.println("Printing the hashcode of \" num1 \": "+System.identityHashCode(num1) + "\nPrinting the hashcode of \" num2 \": "+System.identityHashCode(num2));
System.out.println("As now you can notice the hashcode has changed for num2 ,That is because now a new object is created for num2 and it is referencing the new object");
//Again i'm incrementing num2
System.out.println("\nBefore incremeting the hashcode of \" num2 \" is: "+System.identityHashCode(num2));
num2++; // You can use num2 = 36 as both are same;
System.out.println("After incremeting the hashcode of \" num2 \" is: "+System.identityHashCode(num2));
//now the hashcode value of num2 is changed ,again new object is created for the updated value and num2 is referencing new object ,and old object will be garbage collected
System.out.println("\n Thus the CONCLUSION is Wrapper objects are immutable ,They only create new object and refernce the new object ,They won't modify the present object ");
System.out.println("This is applicable for Strings also");
Something to hold in mind is that there is now a cache for Integer values. It sometimes saves developers from the mistake of using == instead of .equals() when changing from int to Integer. Not always though. When you instantiate a new Integer, there will be a new instance created. So Integers are not only immutable, but also semi static.
Integer a = 3;
Integer b = 3;
Integer c = new Integer(3);
b = b + 1;
b = b - 1;
System.out.println("a-id: " + System.identityHashCode(a));
System.out.println("b-id: " + System.identityHashCode(b));
System.out.println("c-id: " + System.identityHashCode(c));
System.out.println("a == b: " + (a == b));
System.out.println("a == c: " + (a == c));
System.out.println("a eq c: " + (a.equals(c)));
Gives the printout:
a-id: 666988784
b-id: 666988784
c-id: 1414644648
a == b: true
a == c: false
a eq c: true
Is this code safe in Java?
public class HelloWorld {
public static void main (String args[]) {
HelloWorld h = new HelloWorld();
int y = h.getNumber(5);
int z = h.getNumber (6);
if (y == 10)
System.out.println("true");
}
public int getNumber(int x) {
int number = 5;
number = number + x;
return number;
}
}
My co-worker says that int number will be placed on the stack and when getNumber returns it will be popped off and could potentially be overwritten.
Is the same code potentially unsafe in C?
The HelloWorld class has no fields, and is therefore immutable. You can call your getNumber(x) function as many times as you'd like, from any thread, using the same object, and it will always give the same result for the same argument.
Maybe your co-worker is recalling horror stories in C where you can have something like static int number, which "belongs" to the method and which would get overwritten. Or maybe she's thinking about "return by reference"; even if it were, you'd be referencing a brand-new object every time because number is newly instantiated for every method call.
Your coworker is correct, sort of, but they apparently misunderstand what is going on.
public int getNumber(int x) {
int number = 5;
number = number + x;
return number;
}
Yes the value of 5 + 5 or 5 + 6 will be placed on the stack, but there is no danger of them being overwritten, they will properly be placed into y or z.
I suspect the confusion is from C (this type code works fine in C as well), but for pointers instead of primitives. Returning a result of malloc from a function in C can be "challenging" if you don't do it right.
I am a little bit confused about the following piece of code:
public class Test{
int x = giveH();
int h = 29;
public int giveH(){
return h;
}
public static void main(String args[])
{
Test t = new Test();
System.out.print(t.x + " ");
System.out.print(t.h);
}
}
The output here is 0 29, but I thought that this has to be a compiler error, because the variable h should have not been initialized when it comes to the method giveH(). So, does the compilation go through the lines from top to bottom? Why is this working? Why is the value of x 0 and not 29?
The default value of int is 0 (see here). Because you initialize x before h, giveH will return the default value for a int (eg 0).
If you switch the order like this
int h = 29;
int x = giveH();
the output will be
29 29
Compilation in Java doesn't need the method to be declared before it is used. The Java tutorial goes into a bit more detail on initialization.
Here's a way to think about it: the compiler will make a note to look for a method called giveH somewhere in scope, and it will only error if it leaves the scope and doesn't find it. Once it gets to the giveH declaration then the note is resolved and everyone is happy.
Also, the variable initialization for instance variables in Java is moved to the beginning of the constructor. You can think of the lines above being split into two parts, with the declaration for x and h above, and the assignment inside the constructor.
The order of declaration does matter in this case. When the variable x is initialized, h has the default value of 0, so giveH() will return that default value. After that, the variable h is given the value 29.
You can also look at the Java Language Specification sections on Field Initialization and Forward References During Field Initialization.
#Maloubobola has provided the correct answer, but since you don't seem to fully understand yet, let me try to elaborate.
When Test is created, it runs the variable initialization (x = giveH(), h= 29) once. Your misunderstanding may be that variable x is always determined by giveH(), whereas it only determines it's value when x is initialized.
That's why the order of the statements is crucial here; x is initialized before h, and therefore h is 0 when giveH() is called at x's initialization.
It's bad practice to use a method in the field initializer. You can fix this by making h final. Then it will be initialized when the class is loaded.
import java.util.ArrayList;
public class Test {
int x = giveH();
final int h=29;
final public int giveH(){
return h;
}
public static void main(String args[]) {
Test t = new Test();
System.out.print(t.x + " ");
System.out.print(t.h);
}
}
If we do not initialize the value for non static variables like x in this program JVM will provide default value zero for class level non static variables.
Once declared, all the array elements store their default values.
Elements in an array that store objects default to null.
Elements of an array that store primitive data types store:
0 for integer types (byte, short, int,long);
0.0 for decimal types (float and double);
false for boolean;
\u0000 for char data.
Actauls values will come only when we give initialize them
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Is Java “pass-by-reference”?
I am trying to understand the difference between the 2 Java programs written below:
public class Swapping {
public static void main(String[] args) {
IntWrap i = new IntWrap(10);
IntWrap j = new IntWrap(20);
swap(i, j);
System.out.println("i " + i.i + ", j " + j.i);
}
public static void swap(IntWrap i , IntWrap j){
int x = i.i;
i.i = j.i;
j.i = x;
System.out.println("i " + i.i + ", j " + j.i);
}
}
public class IntWrap {
int i;
public IntWrap(int i){
this.i = i;
}
}
Output :
i 20, j 10
i 20, j 10
And second one:
public class Swapping {
public static void main(String[] args) {
Integer i = new Integer(10);
Integer j = new Integer(20);
swap(i, j);
System.out.println("i " + i + ", j " + j);
}
public static void swap(Integer i , Integer j){
Integer temp = new Integer(i);
i = j;
j = temp;
System.out.println("i " + i + ", j " + j);
}
}
Output :
i 20, j 10
i 10, j 20
I am not able to understand that I even though I am passing the Integer object, it should get swapped in the original program. What difference did it created if I wrote the wrapper class on the top of it as I am again passing the object only.
All method parameters, including object references, are passed by value in Java. You can assign any value to the method parameter - the original value in the calling code will not be modified. However you can modify the passed object itself and the changes will persist when the method returns.
There are old Holder classes in J2SE API, specially designed to support calls to methods with "returnable parameters" (IntHolder or StringHolder, for instance). They are mostly used with generated code from IDL language as IDL requires support for in, out and inout parameters. These holders are very uncommon in other code.
You can also simulate passing by reference by using arrays:
String [] a = new String[1]; String [] b = new String[1];
void swap(String [] a, String [] b) {
String t = a[0]; a[0] = b[0]; b[0] = t;
}
Java uses call-by-value to pass all arguments.When you pass the object to a function, the object reference(address of object) gets passed by value.In the second program swap, you are assigning i=j and j=temp.
So i=address of 20
j=address of 10(new object)
But after return from swap, in the main program i is still pointing to 10 and j is pointing to 20.Thats why you are getting 10 and 20 back in main program.
But in first program, you are passing the address of your objects to swap function and in the swap function you are modifying the content of object pointed by these addresses.That is why, it is getting reflected in main method.
Ups. Integer objects are immutable in Java. You can not change their internal values neither from other method, neither at all. Only create new Integer object.
(If you don't know about pointers and references I suggest you go over them a bit, then the world will make more sense - Intro to Pointers)
Putting it down to the most simplest explanation, there are 2 ways java passed everything back and forth:
Pass-by=Value: Used for immutable objects (String, Integer, Double, etc.). These values cannot change with one exception, if you recreate the object.
String x = "World"; <- String x = new String("World");
x = "Hello"; <- x = new String("Hello");
x = x + " World"; <- x = new String("Hello" + " World");
printOutString(x); <- printOutString("Hello World");
Held at one memory location. Any alteration creates a new object with no relation to the previous and look at a separate memory location.
Pass-by-reference: Used for non-immutable objects (Classes, int, double, etc.). These values can be changed and still keep their old place in memory.
int i = 1;
i = 2; <- value at <reference-to-memory-as-value> = 2;
i = i + 1; <- value at <reference-to-memory-as-value> + 1;
printOutInteger(i); <- printOutInteger(value at <reference-to-memory-as-value>);
Any change to this object is done to the memory location. Therefore the location never changes (unless you create a new object).
The same is happening in your programs. The objects that say one thing in the method, then revert to the previous values. You are, in a way, Operator Overloading. You assign new values to the objections (Integer in this case) that you are sending, BUT you have passed the values which means Integer i within the method, because Integer is immutable, is looking at a different memory location to the Integer i in the main method. Therefore, when the method exits, the objects you passed are disposed of and Integer i and j now look at their original memory locations.
When you passed the classes with the int objects, as they are NOT immutable the memory locations were passed (by value) and the values at those locations were worked with. That is why the changes here were shown in the original objects.
I hope this helps
In Java Language Spex 15.7:
Code is usually clearer when each expression contains at most one side
effect, as its outermost operation
What does it mean?
It means that each expression should do one task at a time.
Consider the following two declarations:
int a = 10;
int b = 20;
Now the task is to add these two ints and increment b by 1. There are two way to do it.
int c = a + b++;
and
int c = a + b;
b++;
JLS prefers and recommends the latter one.
What this means is that:
int x = someFunction(a, b);
is clearer when someFunction(a, b) doesn't have any side-effect i.e. it doesn't change anything. Rather the only change in the above is the assignment to x.
Another example would be use of prefix/postfix incrementers.
int x = a + b;
is clearer than
int x = (a++) + (++b);
since only x is assigned to. In the second example a and b are changed in the same statement.
By limiting the side effects, you can more easily reason about the functioning of the code, and/or re-order statement invocations, including parallelising them e.g. in the below, if the methods don't have side-effects, then you can invoke the methods a(), b() and c() representing the arguments in any order, and/or in parallel.
int res = f(a(), b(), c());
Side-effect of an expression is mostly an assignment to variable during evaluation of the expression.
Notice the code:
int x = 5, y = 7;
while ((z = x-- + --y) > 0 ) {
console.out("What is 'z' now? " + z);
console.out("How many times will this be printed?");
}
Evaluation of the condition has 3 side-effects:
decrementing x
decrementing y
assignment to z
Looks twisted, isn't it?