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};
Related
In SCJP book i get a point by Kathy Sierra that their is no final object in java. There are only final reference variable in java.
But i think objects of string class are final. As once initialized their state can not change.
Now question is that the objects of string class are final or not.
If they are not than how the objects of string class are immutable.
Thanks
But i think objects of string class are final. As once initialized their state can not change.
No, they're not final in the Java sense. They're immutable, but final relates purely to variables/data members, not objects.
Here's an example:
final String a = "foo";
String b = "bar";
b = "updated bar"; // Compiles and works, `b` (the variable) can be changed
a = "updated foo"; // Won't compile, you're not allowed to change the `a` variable
final is about whether a "variable"'s value can be changed, not about whether the state of an object can be changed.
Here's an example with a final variable referring to a mutable object:
final Map a = new HashMap();
a.add("foo", "bar"); // Works; we're not changing `a`, we're changing the state
// of the object `a` refers to
And just to take objects out of it entirely:
final int a = 5;
a = 6; // Won't compile, because we aren't allowed to change `a`
First you have to read this:
http://en.wikipedia.org/wiki/Final_(Java)
Because in Java final keyword can be used in several different context.
String class is immutable, it means that after creation state of this object cannot be changed and is also declared as final which means it can't be subclassed.
You would have to post the chapter (please don't, by the way) to fully give the context, but I can distinguish the two concepts further for you.
final is a keyword in java that applies, in your case, to a reference variable. That means that once the object is instantiated, that variable cannot be assigned to a different object, i.e., if you do:
final String[] stringArray = new String[8];
you can never do anything again like this:
stringArray = new String[2];//stringArray is final and cannot be reassigned
This doesn't indicate however that if the contents of stringArray are not able to be changed. You can do:
stringArray[3] = "Hey!";
And it will compile just fine. This shows you that just the reference cannot be reassigned to anything else; we're only talking the reference here.
When they say String is immutable, they are talking about the String constant pool. In the string constant pool there is a collection of strings that have been created in memory that are stored for reuse. If you say, for example:
String tempString1 = "yo";
String tempString2 = "yo";
You only created 1 string object in the string constant pool (a special part of memory where strings go) and assigned it to two different reference variables. If you do:
tempString2 = "hey";
String tempString3 = "yo";
you have only created 1 new object again, "hey", in the string constant pool. tempString1 only changed what it was pointing to, and tempString3 is reusing "yo" that has already been created.
If you do this because you're nuts about Java:
tempString1 = tempString2 + tempString3;
String tempString4 = tempString2 + tempString3;
String tempString5 = tempString2 + tempString3;
You have only created 1 more string "heyyo". "yo" "hey" and "heyyo" are the only strings in the String constant pool.
Any operation you do will not change "hey" and "yo" in the string constant pool, even though you may change output to appear like those strings have changed.
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.
I know the concept of String pool in PermGen area of heap. So when we do something like
String firstString = "Stack";
String secondString = "Stack";
both references firstString and secondString point to the same object in the pool. But I tried the same for a variable of type int.
int firstInt = 5;
int secondInt = 5;
if(firstInt == secondInt) {
System.out.println("Both point to same allocated memory");
} else {
System.out.println("Both point to different allocated memory");
}
and the result is Both point to same object and when i tried
Integer firstInteger = new Integer(2);
Integer secondInteger = new Integer(2);
if(firstInteger == secondInteger) {
System.out.println("Both point to same object");
} else {
System.out.println("Both point to different object");
}
output is Both point to different object
I tried the same for char and the result is similar. So my question do we have pools for all primitive types like int, char? And when we actually create objects with same content using new () as in the second case mentioned above is the object cloned and stored in same pool area or is it outside the pool?
There is so much misconception in your post, it is hard even to start explaining. Get some decent book. For now, some facts that might help you:
String is not a primitive type,
there are no pools of primitive types, because there cannot be a reference to a primitive type (the answer saying that they are only kept on the stack is plain wrong!)
if you use new, you bypass pools anyway; so executing new String("ala") will always create a new String object; you cannot change the semantics of new;
if you want to use available pools, use factory methods on objects (like Integer.valueOf), they will - to some extent - pool instances (it is not viable or beneficial to pool all possible values of Integers, Floats etc.).
Primitives are not objects. They can be stored directly in the generated code.
In your second code block, you're testing equality of value, not that two objects are the same.
int firstInt = 5;
int secondInt = 5;
if(firstInt == secondInt)
{
System.out.println("Both point to same object");
// NO - neither point to an object -- their alues are the same.
}
You can share the same Integer object among multiple references by explicitly using Integer.valueOf(int), which may return the same object for multiple calls.
If you try
if (Integer.valueOf(2) ==Integer.valueOf(2))
you will get true.
With the Integer firstInt = new Integer(2) you create a new local variable that is != to another local variable created with Integer secondInt = new Integer(2). Same goes for String type.
The reason behind this is that == checks equality of the variables. Variables could be different (== results in false) even though they point to two objects that are "the same". The same in this context means obj1.equals(obj2) returns true.
If you want object representation of primitve types and also StringS to be stored in PermGen then do not use new keyword, i.e. Integer firstInt = 2;, String firstString= "whatevs"; beacause the keyword new creates an object on the heap.
Sometimes, to answer advanced questions it is enough to look through source code. For instance, here is the code of Integer#valueOf(int i) method:
public static Integer valueOf(int i) {
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
return new Integer(i);
}
Values IntegerCache#low and IntegerCache#high could be changed via vm options:
The size of the cache may be controlled by the -XX:AutoBoxCacheMax=<size> option.
I believe this is a very valid question that needs to be answered. For any future readers, the way the == operation works for Object types and primitive types are different.
Primitive types(int, char, double, long....) are evaluated by their values.
Whereas Primitive Wrappers (Integer, Double, String ....) are actually objects and not just values.
So when we use Integer class as
Integer number = new Integer(10)
A new Object is created in the memory which is not the case for primitive data types.
The == evaluation checks the memory, as well as the value for the Object types and for primitive types, checks the value only.
I am not able to figure out that if
String ab = "hello"; //straight initialization
String ab_1 = new String ("hello_1"); //initializing using new
both work, but
StringBuffer bfr = new StringBuffer("hi"); //works only with new
works only if created with new.
Why it is that String can be instantiated directly but StringBuffer needs new operator. Can someone explain me the main reason please.
All objects need to be instantiated with new. Only primitives can be instantiated from a literal (int i = 0;).
The only exceptions are:
strings, which allow a special initialisation construct:
String s = "abc"; //can be instantiated from a literal, like primitives
null instantiation: Object o = null;
It is defined in the Java Language Specification #3.10:
A literal is the source code representation of a value of a primitive type, the String type, or the null type.
Note: arrays also have a dedicated initialisation patterm , but that's not a literal:
int[][] a = { { 00, 01 }, { 10, 11 } };
Using String s1 = "hello"; and String s2 = new String("hello"); have a subtle difference.
public static void main(String[] arg ) {
String s1 = "Java";
String s2 = "Java";
String s3 = new String("Java");
System.out.println(s1==s2); //true
System.out.println(s1==s3); //false
StringBuilder sb = new StringBuilder(25); //initial capacikacity
sb = new StringBuilder(10);
sb.append(s1).append(" uses immutable strings.");
sb.setCharAt(20, 'S');
System.out.println(sb);
}
In the above code, "Java" is known as a String literal. In order to save memory, both times this appears in the code, it is the same String literal, so s1 and s2 actually refer to the same object in memory. While s1.equals(s3) would be true, they do not reference the same object in memory as shown above.
In practice, we always use .equals to compare Strings and they are immutable, so we cannot change the data s1 refers to (at least not easily). But if we were able to change the data referenced by s1, then s2 would change along with it.
StringBuilder does let you modify the underlying data: we often use it to append one String to another as illustrated above. We can be glad that StringBuilder sb2 = "what?" is illegal because in the case of StringBuilders, having two of them reference the same data (meaning sb1==sb2) is more likely to lead to problems where a change in sb1 causes an unexpected change in sb2.
String ab = "hello"; //straight initialization
String ac = "hello"; // create one more reference ac
String is a special case when you use the new keyword, a new String object will be created. Note that objects are always on the heap - the string pool is not a separate memory area that is separate from the heap.The string pool is like a cache.
It is like this because Strings are something heavily used by java and creating String objects using new key word is expensive also that's why java has introduced StringPool concept.
If you declare one variable ac with same value , java will not create new object(String) it will simply refer to the same object(hello) which is already there in pool.
String ab_1 = new String ("hello_1"); //initializing using new
It will simple create object in memory and ab_1 will refer to that object.
Strings are quite a special case in Java (this is not really a good thing in my opinion, but that doesn't matter).
Strings, unlike other objects, can be instantiated directly like they were constants.
When you do this, the String constant is added to the String constant pool, and handled like it was a primitive. Let me give an example.
String a = "abc";
String b = "abc";
When you instantiate a as a "primitive" string, it gets added to the pool, when you instantiate b, the same object is returned from the pool, so if you do this:
a == b;
You'll get... true, since it's actually the same object. If you instantiate both with new, you'll get false, since you're comparing the references of two different Objects (new forces the creation of a distinct object).
Strings are handle specially by java compiler. When you type a string literal such as "hello", the compiler creates a new String object for you internally.
No such thing is performed for StringBuffers (although Java uses StringBuffers internally for another purpose - for implementing string concatenation).
See Difference between string object and string literal for more details.
Other pointers:
String, StringBuffer, and StringBuilder
+ operator for String in Java
There is also one more difference based on 'where' strings are 'stored' - memory or string constant pool.
To make Java more memory efficient, the JVM sets aside a special area
of memory called the "String constant pool." When the compiler
encounters a String literal, it checks the pool to see if an identical
String already exists. If a match is found, the reference to the new
literal is directed to the existing String, and no new String literal
object is created. (The existing String simply has an additional
reference.)
String s = "abc"; // creates one String object and one reference variable
In this simple case, "abc" will go in the pool and s will refer to it.
String s = new String("abc"); // creates two objects, and one reference variable
In this case, because we used the new keyword, Java will create a new String object
in normal (nonpool) memory, and s will refer to it. In addition, the literal "abc" will
be placed in the pool.
String is a mutable class and has in-build constructors which can create String object from the string literal.
There is no exception in case of String also (like creating it like primitive .e.g int i =0). String also executes constructor to initialize following (just difference is its abstract and not directly visible) :
String str = "ABC";
Becuase here "ABC" also represent one String object which can not be used directly by programmer but it resides in the String pool. And when this statement will be executed JVM will internally call the private constructor to create object using the "ABC" object which resides in the pool.
Basically, since Strings are used so much, Java offers a shorthand solution to instantiating a String.
Instead of always using this,
String str = new String ("hello");
Java makes it able to do this:
String str = "hello";
I was doing one of these online Java tests and I was asked this question:
Q: Indicate correct assignment:
Long l = 1;
Double d = 1;
Integer i = 1;
String s = 1;
Object o = "1";
System.out.println(o);
o = 1;
System.out.println(o);
Please try it yourself before you go any further.
Well I can tell you I got it wrong, I investigated it and found:
//Long l = 1; //cannot widen and then box
Long ll = 1L;//no need to widen, just box
//Double d = 1;//cannot widen and then box
Double dd = 1d;//no need to widen, just box
Integer i = 1;//no need to widen, just box
//String s = 1;//cannot do implicit casting here
Object o = "1";//this compiles and is just plain weird
System.out.println(o);//output is 1
o = 1;//this also compiles and is also weird
System.out.println(o);//output is 1
Can someone tell why:
Object o = 1; and Object o = "1";
compile and output 1 in both cases, this is puzzling me.
Many thanks
"1" is an instance of String class, and String is a subclass of Object class in Java (as any other class). 1 is boxed into an Integer, which is also derived from Object.
Because "1" is an instance of a String, and since 1.5 1 is auto-boxable to an Integer; both types are subtypes of Object. Before autoboxing was introduced, Object o = 1; would not compile.
To get the most out of this learning experience, you should be aware of Object's getClass() method. By adding System.out.println(o.getClass().getName()), you can also print the name of the class that the object referred to by o belongs to. In your case, they are java.lang.String (for (Object) "1") and java.lang.Integer (for (Object) 1).
Just for completion, I should mention that you can now also do Object o = false;.
Well, the first case "1" is a String literal, so a subclass of object, hence assignable to it. As a string, it output of 1 is relatively simple.
In the second case, auto-boxing is occurring. Integer is a subclass of object, hence assignable to it. Similarly, the output of 1 then makes perfect sense.
This is because o is of type Object. Every object, in java, extends the class Object. So... when you say Object o = 1, it converts 1 to from int to Integer, which is an Object. Similarly, "1" is a String which is an Object. In both cases, calling System.out.println on an Object invokes the Objects toString method. In both cases, it will print 1.
You can put Object o = anything; where anything is any object because all classes derive from the Object class. It works with primitives because of autoboxing feature which came in java 1.5.