Why can the immutable class Integer have its value reset? - java

I was reading earlier that wrapper classes are all immutable. Immutable means that the value cannot be changed. Below I tried this simple example that can just be pasted in to any main method. first I create a Integer that wraps the value five. Immutable means that they cannot be changed so why can I set I to 89. I think that it is because it changes where (I) points to but I am not certain why this is the case.
In my next little example i create an Integer of x which will throw an error if I try and change it. The x seems to be immutable in this specific case but not in the case of the (i) variable.
It seems that I can change the value of (i) whenever I want to so in reality Integer without the final keyword is not immutable???? If i can be set to 89 then to me this seems that the variable can be changed.
I have read other post on this and I still am not certain why i can be changed to another variable. Also in writing code what is the best way to declare primitive types. Why not use the wrapper classes all of the time to create variables.
int y = 5;
Integer i = new Integer(y);
i = 89;
final Integer x = Integer.valueOf(5);
System.out.println("Integer:(i) " + i.intValue());
System.out.println("Integer:(i) " + i.byteValue());
System.out.println("Integer:(x) " + x.intValue());;
System.out.println("Integer:(x) " + x.byteValue());;
i = i - 5;
Using all wrapper classes to declare variables: (Would this be better than declaring these variable with the primitive variable types)
Integer a = new integer(MyNewValue);
Integer b = new integer(MyNewValue);
Integer c = new integer(MyNewValue);
Integer d = new integer(MyNewValue);
Float fa = new integer(MyNewValue);

You are conflating two things: changing the value of an "object" itself and changing the object a reference points to. Saying i = 89 just points the variable i to a new object; it doesn't change the Integer object which originally was pointed to by i.
Pre-pending variable declarations with final just ensures that reassigned is prohibited, it is in no way a declaration of the mutability/immutability of the object it points to. Maybe off-topic, but I personally think the article Java is Pass-by-Value, Dammit! is a good read.

When you call i = 89;, your not changing the value of the Integer object stored in memory. Instead, you're assigning a brand new int with value 89 to i. So the immutable rule isn't being broken.
Remember that i is simply a reference that points to the Integer, not the actual Integer itself.

Yes, it does look like the integer is changing, but all that is happening on line 3 is its being converted to i = new Integer(89) by the compiler. If you wanted to see, you could do
Integer i1 = i;
i = 83;
println(i); \\ prints out the original value 5
println(i1); \\ prints out a new value, 83
When you declare something as final, you cannot change the definition of the variable, though you can still mutate anything inside it. JavaRanch has a very nice analogy to help
You should not use wrapper objects when you can avoid it because they are a small amount less efficient to than primitives and take up a few extra bytes.

Related

Understanding a ArrayList of references [duplicate]

I find the defs circular, the subjects are defined by their verbs but the verbs are undefined! So how do you define them?
The Circular Definitions
initialization: to initialize a variable. It can be done at the time of
declaration.
assignment: to assign value to a variable. It can be done anywhere, only once with the final-identifier.
declaration: to declare value to a variable.
[update, trying to understand the topic with lambda calc]
D(x type) = (λx.x is declared with type)
A(y D(x type)) = (λy.y is assigned to D(x type))
%Then after some beta reductions we get initialization.
D(x type) me human // "me" declared with type "human"
A(y (D(x type) me human)) asking // "asking" assigned to the last declaration
%if the last two statemets are valid, an initialization exists. Right?
assignment: throwing away the old value of a variable and replacing it with a new one
initialization: it's a special kind of assignment: the first. Before initialization objects have null value and primitive types have default values such as 0 or false. Can be done in conjunction with declaration.
declaration: a declaration states the type of a variable, along with its name. A variable can be declared only once. It is used by the compiler to help programmers avoid mistakes such as assigning string values to integer variables. Before reading or assigning a variable, that variable must have been declared.
String declaration;
String initialization = "initialization";
declaration = "initialization"; //late initialization - will initialize the variable.
// Without this, for example, in java, you will get a compile-time error if you try
// to use this variable.
declaration = "assignment"; // Normal assignment.
// Can be done any number of times for a non-final variable
Declaration is not to declare "value" to a variable; it's to declare the type of the variable.
Assignment is simply the storing of a value to a variable.
Initialization is the assignment of a value to a variable at the time of declaration.
These definitions also applies to fields.
int i; // simple declaration
i = 42 // simple assignment
int[] arr = { 1, 2, 3 };
// declaration with initialization, allows special shorthand syntax for arrays
arr = { 4, 5, 6 }; // doesn't compile, special initializer syntax invalid here
arr = new int[] { 4, 5, 6 }; // simple assignment, compiles fine
However, it should be mentioned that "initialization" also has a more relaxed definition of "the first assignment to a variable", regardless of where it happens.
int i; // local variable declaration
if (something) i = 42;
System.out.println(i);
// compile time error: The local variable i may not have been initialized
This, however, compiles:
int i; // the following also compiles if i were declared final
if (something) i = 42;
else i = 666;
System.out.println(i);
Here i can be "initialized" from two possible locations, by simple assignments. Because of that, if i was an array, you can't use the special array initializer shorthand syntax with this construct.
So basically "initialization" has two possible definitions, depending on context:
In its narrowest form, it's when an assignment is comboed with declaration.
It allows, among other things, special array shorthand initializer syntax
More generally, it's when an assignment is first made to a variable.
It allows, among other things, assignments to a final variable at multiple places.
The compiler would do its best to ensure that exactly one of those assignments can happen, thus "initializing" the final variable
There's also JVM-context class and instance initialization, OOP-context object initialization, etc.
Here is a short explanation with some examples.
Declaration:
Declaration is when you declare a variable with a name, and a variable can be declared only once.
Example: int x;, String myName;, Boolean myCondition;
Initialization:
Initialization is when we put a value in a variable, this happens while we declare a variable.
Example: int x = 7;, String myName = "Emi";, Boolean myCondition = false;
Assignment:
Assignment is when we already declared or initialized a variable, and we are changing the value. You can change value of the variable as many time you want or you need.
Example:
int x = 7;
x = 12; .......We just changed the value.
String myName = "Emi";
myName = "John" .......We just changed the value.
Boolean myCondition = false;
myCondition = true; .......We just changed the value.
Note: In memory will be saved the last value that we put.
declaration: whenever you define a new variable with its type
assignment: whenever you change the value of a variable by giving it a new value
initialization: an assignment that is done together with the declaration, or in any case the first assignment that is done with a variable, usually it's a constructor call for an object or a plain assignment for a variable
I come from a C/C++ background, but the ideas should be the same.
Declaration - When a variable is declared, it is telling the compiler to set aside a piece of memory and associate a name (and a variable type) with it. In C/C++ it could look like this:
int x;
The compiler sees this and sets aside an address location for x and knows what methods it should use to perform operations on x (different variable types will use different access operations). This way, when the compiler runs into the line
x = 3 + 5;
It knows to put the integer value 8 (not the floating point value 8) into the memory location also known as 'x'.
Assignment - This is when you stuff a value into the previously declared variable. Assignment is associated with the 'equals sign'. In the previous example, the variable 'x' was assigned the value 8.
Initialization - This is when a variable is preset with a value. There is no guarantee that a variable will every be set to some default value during variable declaration (unless you explicitly make it so). It can be argued that initialization is the first assignment of a variable, but this isn't entirely true, as I will explain shortly. A typical initialization is a blend of the variable declaration with an assignment as follows:
int x = 6;
The distinction between initialization and assignment becomes more important when dealing with constants, such as this...
const int c = 15;
When dealing with constants, you only get to assign their value at the time of declaration/initialization. Otherwise, they can't be touched. This is because constants are often located in program memory vs data memory, and their actual assignment is occurring at compile time vs run time.
Step 1: Declaration : int a;
Step 2: Initialization : a = 5;
Step 3: Assignment: a = b; (ex: int b = 10 ; now a becomes 10)
Declaration
When we first create a variable of any Data Type is call Declaration. Example:
int obj;
String str;
Initialization
When (Declaration is completed) or variable is created the assigned any value to this variable is call Initialization. Example
int obj = 10;
String str = "Azam Khan";
Assignment
Reassign value to that variable that is already initialized is call Assignment. Example
int obj = 15;
obj = 20; // it print **20** value.
String str = "simple"
str = "Azam Khan" // it's result or print **Azam Khan** value...
Simple program
class ABC{
public static void main(String args[]){
int obj; // this is **Declaration:**
int testValue= 12; // After the **Declaration**,
testValue is **Initialize**.
testValue = 25;
System.out.println(textValue);
}
}
the output result is 25.
it saves the value of 25.

How to make the variables of an Object final? [duplicate]

This question already has answers here:
what is the sense of final ArrayList?
(13 answers)
Closed 5 years ago.
I have a question about final variables in java and I have written a short code to demonstrate the issue. The Language Specification of java8 states that:
Once a final variable has been assigned, it always contains the same
value. If a final variable holds a reference to an object, then the
state of the object may be changed by operations on the object, but
the variable will always refer to the same object. Language
Specification
To investigate further I have tried out three things in a small example code. The first thing I tried out was to create an object of the type Integer and assign non final reference to it. Then I assigned a final reference to it as well. In the second experiment I did the same with primitive int. Both experiments lead to the same result of me not being allowed by the compiler to increment the final reference, but being allowed to increment the non final reference and in the Output only the non final variable got incremented.
In my third experiment I used a List and assigned, again, a non final and a final reference to the List. Here I was allowed to use the final and the non final reference to call add() and in both references the size was updated.
My test-code:
public void testFunction () {
Integer nonFinalInteger = 4;
final Integer finalInteger = nonFinalInteger;
nonFinalInteger++;
//Compiler shows error
//finalInteger++;
System.out.println("nonFinal Integer: " + nonFinalInteger);
System.out.println("final Integer: " + finalInteger + "\n");
int nonFinalInt = 4;
final int finalInt = nonFinalInt;
nonFinalInt++;
//Compiler shows error
//finalInt++;
System.out.println("nonFinal primitive int: " + nonFinalInt);
System.out.println("final primitive int: " + finalInt + "\n");
List<String> nonFinalVar = new ArrayList<String>();
final List<String> finalVar = nonFinalVar;
finalVar.add("Hello");
//Compiler does not show error
nonFinalVar.add("World");
System.out.println("nonFinal List Size: " + nonFinalVar.size());
System.out.println("final List Size: " + finalVar.size() + "\n");
}
Output:
nonFinal Integer: 5
final Integer: 4
nonFinal primitive int: 5
final primitive int: 4
nonFinal List Size: 2
final List Size: 2
My question is now: Is there a way to protect the state of the object without having to change the code of its class? Lets say we stay in the context that there is a List, where you should not be allowed to add or delete elements. Is it possible to mark the List in a way, so that the compiler would show an error (or at least some kind of warning)?
Edit:
It seems I have caused some confusion with using arrays in the example. My question should refer to any kind of objects, hence I did not put in List in the question or the tags. What I meant was not to tell the compiler that updating the reference is forbidden, I just wanted to know if there was a way of implicitly telling the compiler to reject the calling of functions that may change the state of the object.
Currently the idea with the wrapper class seems to be the most appealing one, even though it still lacks one thing for me: It would not stop me or other people to change the state of the object completely. Final variables always have this "do not touch" trait I am looking here for.
This is a confusing matter. I will try to explain it:
When you declare a variable as final, the result is that his value can be assigned in two different forms:
Assigned the value in the same line that you define the final variable.
If the final variable B is a property of a class A, then the B's value can be assigned in the constructor of the A class.
But the important thing is, when I'm saying assigned a value I refer to the assignment in the form:
final ArrayList<Integet> myArray = new ArrayList<Integer>(Arrays.asList(1,2,3));
Now the variable myArray is always pointing to that arraylist and can't be assigned in the same form again:
myArray = new ArrayList<Integer>(Arrays.asList(4,5,6)); will throw an error.
But that being said, you can still make operations in that variable. For example, like you see, you could add values doing: myArray.add(4);.
In a few words: when you mark a variable C as final you are doing just that, saying that C can't be assigned to another object, but that target object can change his state at any time.

Change the value of instance without changing the other instance

For those who had read my first question, I think I found where the problem is. The problem is in the mutate method and especially in this instruction:
Chromosom ch=new Chromosom(); // Chromosom is a class who use hash table
Chromosom k= new Chromosom(); // Class chromosom extends hashmap <integer,parc>
k.initialise();
for(int i=0;i<l.size();i++) ch.put(i,k.get(i)); // in this instruction i think
And this is the constructor of Chromosom:
public Chromosom(){ // construct a blank chromosom
super();
this.identifiant = 0;
NbEquipeExterne = 0;
NbEquipeInterne = 0;
CoutMinimal = 0;
CoutMensuel = 0;
}
When I change the values of ch, the values of k change too?
How can I pass the k's values to ch by copy and not by reference?
First of all Java is always pass-by-value. or rather pass-by-copy-of-the-variable-value not pass by reference. You might be changing objects of Chromosom with k in the constructor.
No danger, both ch and k are separate objects.
Furthermore you can do
ch.putAll(k);
which is a nice short-cut to remember.
Caveat
If the values of the maps are stateful objects (having mutable fields to contain some changing info), then changing that field would change the field of the simgle value object in both tables.
BitSet bits = k.get(i);
bits.set(3);
// Now ch.get(i) being the same object, also has bit 3 set.
If a class has a static field, then that field is once per class, a single instance. So you could have in say Chromosome:
static String copyright;
Chromosome.copyright = "All rights reserved"; // Clearest style
k.copyright = "All rights given to the community";
ch.copyright = "MIT license";
And you would have dealt with the same single variable, with vaklue "MIT license".
About Java
A nice design decision was made in java:
If you pass a variable to a function/method, the object/value will be passed. It may never happen that the variable itself gets an other object/value. (Not the address of the variable is passed.) Java has pass-by-value, no pass-by-reference.

Java object initialization - When is it necessary?

I'm curious about java initialization:
When is it necessary to initialize objects like this:
String init = new String("");
and which objects - like Strings - don't have to be initialized like above?
String init = "";
From your comment on your question:
Then my question is which objects need the "new Object()" initialization?
You're asking about construction, not initialization.
All objects need to be constructed by someone. The strings created by string literals are constructed by the JVM. You basically never want to use new String("text content here").
There are several other objects constructed by the JVM, such as the Class object for each class you load. But other than String, for objects you want to interact with, you usually either have to explicitly construct them (via new) or receive them from a method that constructs them. String is a bit special because it's the only object type in Java (I think) with a literal notation. (All of the other literals, like 42 or false, are primitives.)
Basically there's a subtle difference between the 2 ways of initialization you mentioned:
When you use:
String str = new String("");
a new String object is created on the heap and str points to it.
But in the latter case:
String str = "";
If there is already a string with this value ("") on the string pool, then the reference is initialized to point to it and no new object is created. If it is not found in the string pool, then a new string is created in the string pool and str is initialized to point to it.
For strings, you almost always want to use the second form. It does less work for what -- in most circumstances -- is the same result.
The same advice goes for numeric classes, such as Integer, Double, etc.
In all other cases you don't normally have the choice, and have to use the first form.
In Java, all objects must be initialized. The second case init = "" is also an initialization, except that the compiler lets you avoid the explicit call: object creation is still there. Starting with Java 5, the compiler also "knows" about wrappers for Java primitives, letting you use primitive constants in expressions that require a wrapper class (this is called autoboxing).
All local variables must be initialized explicitly, while member fields can be initialized implicitly to null or the default value of the primitive.
Most classes require explicit construction (the new), however a few classes does not, these are the autoboxing classes (String, Integer, Double, and a few more, as well as arrays of these (using the comma seperated list initiliazation)) and these are the only ones!
What happens at the compiler level is really just that the compiler translates the implicit construction to an explicit one (e.g. One using new)
All objects need to be initialized before they can be used. You can try declaring:
int myPrimitiveInt;
Integer myObjectInt;
But myPrimitiveInt cannot be used until you give it a value, and myObjectInt is implicitly initialized as null. For either of these to be used (except to get a null from the object), they need to be given a value, whether you use a constructor or not.
myPrimitiveInt = 5;
myObjectInt = new Integer(5);
myObjectInt = 5;
String s1 = "1";
String s2 = new String("2");
int i1 = 1;
int i2 = new Integer(2);
long l1 = 1l;
long l2 = new Long(2l);
float f1 = 1f;
float f2 = new Float(2f);
double d1 = 1d;
double d2 = new Double(2d);
char c1 = '1';
char c2 = new Character('2');
byte b1 = 1;
byte b2 = new Byte((byte) 2);
int[] a1 = {1};
int[] a2 = new int[] {2};
All Objects have to be initialized with new but some, like these for example:
String myString= "";
Integer myInteger= 2;
Float myFloat= 2f;
Double myDouble= 2d;
Byte myByte = 2;
and every kind of array, which can be initialized like `T[] array = {//list some Ts};

Java: define terms initialization, declaration and assignment

I find the defs circular, the subjects are defined by their verbs but the verbs are undefined! So how do you define them?
The Circular Definitions
initialization: to initialize a variable. It can be done at the time of
declaration.
assignment: to assign value to a variable. It can be done anywhere, only once with the final-identifier.
declaration: to declare value to a variable.
[update, trying to understand the topic with lambda calc]
D(x type) = (λx.x is declared with type)
A(y D(x type)) = (λy.y is assigned to D(x type))
%Then after some beta reductions we get initialization.
D(x type) me human // "me" declared with type "human"
A(y (D(x type) me human)) asking // "asking" assigned to the last declaration
%if the last two statemets are valid, an initialization exists. Right?
assignment: throwing away the old value of a variable and replacing it with a new one
initialization: it's a special kind of assignment: the first. Before initialization objects have null value and primitive types have default values such as 0 or false. Can be done in conjunction with declaration.
declaration: a declaration states the type of a variable, along with its name. A variable can be declared only once. It is used by the compiler to help programmers avoid mistakes such as assigning string values to integer variables. Before reading or assigning a variable, that variable must have been declared.
String declaration;
String initialization = "initialization";
declaration = "initialization"; //late initialization - will initialize the variable.
// Without this, for example, in java, you will get a compile-time error if you try
// to use this variable.
declaration = "assignment"; // Normal assignment.
// Can be done any number of times for a non-final variable
Declaration is not to declare "value" to a variable; it's to declare the type of the variable.
Assignment is simply the storing of a value to a variable.
Initialization is the assignment of a value to a variable at the time of declaration.
These definitions also applies to fields.
int i; // simple declaration
i = 42 // simple assignment
int[] arr = { 1, 2, 3 };
// declaration with initialization, allows special shorthand syntax for arrays
arr = { 4, 5, 6 }; // doesn't compile, special initializer syntax invalid here
arr = new int[] { 4, 5, 6 }; // simple assignment, compiles fine
However, it should be mentioned that "initialization" also has a more relaxed definition of "the first assignment to a variable", regardless of where it happens.
int i; // local variable declaration
if (something) i = 42;
System.out.println(i);
// compile time error: The local variable i may not have been initialized
This, however, compiles:
int i; // the following also compiles if i were declared final
if (something) i = 42;
else i = 666;
System.out.println(i);
Here i can be "initialized" from two possible locations, by simple assignments. Because of that, if i was an array, you can't use the special array initializer shorthand syntax with this construct.
So basically "initialization" has two possible definitions, depending on context:
In its narrowest form, it's when an assignment is comboed with declaration.
It allows, among other things, special array shorthand initializer syntax
More generally, it's when an assignment is first made to a variable.
It allows, among other things, assignments to a final variable at multiple places.
The compiler would do its best to ensure that exactly one of those assignments can happen, thus "initializing" the final variable
There's also JVM-context class and instance initialization, OOP-context object initialization, etc.
Here is a short explanation with some examples.
Declaration:
Declaration is when you declare a variable with a name, and a variable can be declared only once.
Example: int x;, String myName;, Boolean myCondition;
Initialization:
Initialization is when we put a value in a variable, this happens while we declare a variable.
Example: int x = 7;, String myName = "Emi";, Boolean myCondition = false;
Assignment:
Assignment is when we already declared or initialized a variable, and we are changing the value. You can change value of the variable as many time you want or you need.
Example:
int x = 7;
x = 12; .......We just changed the value.
String myName = "Emi";
myName = "John" .......We just changed the value.
Boolean myCondition = false;
myCondition = true; .......We just changed the value.
Note: In memory will be saved the last value that we put.
declaration: whenever you define a new variable with its type
assignment: whenever you change the value of a variable by giving it a new value
initialization: an assignment that is done together with the declaration, or in any case the first assignment that is done with a variable, usually it's a constructor call for an object or a plain assignment for a variable
I come from a C/C++ background, but the ideas should be the same.
Declaration - When a variable is declared, it is telling the compiler to set aside a piece of memory and associate a name (and a variable type) with it. In C/C++ it could look like this:
int x;
The compiler sees this and sets aside an address location for x and knows what methods it should use to perform operations on x (different variable types will use different access operations). This way, when the compiler runs into the line
x = 3 + 5;
It knows to put the integer value 8 (not the floating point value 8) into the memory location also known as 'x'.
Assignment - This is when you stuff a value into the previously declared variable. Assignment is associated with the 'equals sign'. In the previous example, the variable 'x' was assigned the value 8.
Initialization - This is when a variable is preset with a value. There is no guarantee that a variable will every be set to some default value during variable declaration (unless you explicitly make it so). It can be argued that initialization is the first assignment of a variable, but this isn't entirely true, as I will explain shortly. A typical initialization is a blend of the variable declaration with an assignment as follows:
int x = 6;
The distinction between initialization and assignment becomes more important when dealing with constants, such as this...
const int c = 15;
When dealing with constants, you only get to assign their value at the time of declaration/initialization. Otherwise, they can't be touched. This is because constants are often located in program memory vs data memory, and their actual assignment is occurring at compile time vs run time.
Step 1: Declaration : int a;
Step 2: Initialization : a = 5;
Step 3: Assignment: a = b; (ex: int b = 10 ; now a becomes 10)
Declaration
When we first create a variable of any Data Type is call Declaration. Example:
int obj;
String str;
Initialization
When (Declaration is completed) or variable is created the assigned any value to this variable is call Initialization. Example
int obj = 10;
String str = "Azam Khan";
Assignment
Reassign value to that variable that is already initialized is call Assignment. Example
int obj = 15;
obj = 20; // it print **20** value.
String str = "simple"
str = "Azam Khan" // it's result or print **Azam Khan** value...
Simple program
class ABC{
public static void main(String args[]){
int obj; // this is **Declaration:**
int testValue= 12; // After the **Declaration**,
testValue is **Initialize**.
testValue = 25;
System.out.println(textValue);
}
}
the output result is 25.
it saves the value of 25.

Categories

Resources