3

As far as I know, new keyword is used to instantiate classes. And I think we need to call the class constructor and pass its arguments after this keyword. Right?

Okay, Here is a code snippet:

public class JavaApp{

    public static void main(String[] args) {
        String st1 = "Test";
        String st2 = new String("Test");

        byte[] b1 = {'a', 'b'};
        byte[] b2 = new byte[]{'a', 'b'};
        byte[] b3 = new byte[]('a','b'); //Error

        byte b4 = 3;
        byte b5 = new byte{3}; //Error
        byte b6 = new byte(3); //Error

    }

}

My questions:

  1. What's the difference between st1 and st2?
  2. Why we must pass the arguments of constructor in {} instead of (), in the b2 declaration line?
  3. Why I receive error for b5 and b6?
EbraHim
  • 2,279
  • 2
  • 16
  • 28
  • 2
    Just wanted to add that you are very right to be confused. All the lines do more or less the same thing and you are confused because of the special cases. One of the thing Scala tried is to reduce such special casing. E.g. an Array is instantiated as `Array[Byte](1,2,3)`, just like `List[Byte](1,2,3)`. Although arguably Scala introduced more variance in syntax in other places... – Enno Shioji Apr 23 '16 at 06:57

9 Answers9

4

st1: This stores a reference to the object representing "Test" in variable st1.

st2: Here a new object of java.lang.String is created but it is unnecessary: it shares the value of the constructor argument and copies the hash value. (Not useful.)

b1, b2: That's the way the syntax is defined for array initializers. Probably a good reason if you study the syntax in depth.

A simple type has no object, hence no reason or possibility for new, which instantiates objects from classes (not classes, strictly speaking).

laune
  • 31,114
  • 3
  • 29
  • 42
4
  1. st1 and st2 are two different object; first one reside inside String-Pool and second one as normal java object locates at Heap memory.

  2. {} is not calling constructor, its just a syntax to initialize array.

  3. byte is not a class; its a primitive type so there is no constructor for byte.

rev_dihazum
  • 818
  • 1
  • 9
  • 19
3

Your first answer can be found in the JavaDoc of of constructor String(String)

/**
 * Initializes a newly created {@code String} object so that it represents
 * the same sequence of characters as the argument; in other words, the
 * newly created string is a copy of the argument string. Unless an
 * explicit copy of {@code original} is needed, use of this constructor is
 * unnecessary since Strings are immutable.
 *
 * @param  original
 *         A {@code String}
 */

2nd issue, these are arrays of primitives, your are not invoking a "constructor" in the same way as you would be say new Horse("Alan"). The brace notation is just an initializer which takes a list of values which Java uses to populate the array. new byte[]() concept simply does not exist in the Java language in the way you might think it does.

byte[] b2 = new byte[]{'a', 'b'};
byte[] b3 = new byte[]('a','b'); //Error

3rd issue, byte is not an object, it is a primitive, it has no constructor to call.

byte b5 = new byte{3}; //Error
byte b6 = new byte(3); //Error

However you can use the Byte object wrapper, essentially an Object version of the byte primitive, this does have a constructor.

byte b7 = new Byte((byte)3);
Adam
  • 35,919
  • 9
  • 100
  • 137
  • Re "not calling constructor": There's no difference if the array element is a regular class. An array *is* an object, always, so a constructor is called behind the scenes. -1 – laune Apr 23 '16 at 06:50
  • @laune, correct primitive arrays are objects. I mean to say not calling a constructor at the language level, i.e. new byte[]{'a', 'b'} is not passing the arguments 'a' and 'b' into a constructor. – Adam Apr 23 '16 at 06:57
  • @laune there are certain scenario that the object is created but the constructor is not called e.g. **.clone()**. Can you please provide a reference that states that an array constructor is called. Basically I tried to find one that supports your statement but no luck. – Enzokie Apr 23 '16 at 07:14
  • @neferpitou Java is not a pure OO language, objects can be constructed without constructors being called, not all things that look like objects are pure, some are implemented at the JVM level – Adam Apr 23 '16 at 07:17
  • @Adam thats what I am saying. – Enzokie Apr 23 '16 at 07:18
  • @neverpitou So how does any clone implementation create the copies object? - I wrote "behind the scenes". If the language provides some syntactic sugar that does the same thing as the (*fictional pseudo-code!*) `new Array( byte.class, 3 )` this is just a shortcut. In the end, it is still an object, and any code that creates an object can be called "constructor", even if there's no Java source code for it, just a JVM instruction. – laune Apr 23 '16 at 07:48
2

At st1 you create a String object that represents the string "Test", at st2 you pass his String object into the String constructor. The String constructor can take many kinds of arguments, if you pass on a String into this it just makes a copy. However it also can do things like convert a char array into a String for example.

b3 gives an error because thats simply just not the right syntax, for defining the values of an array at creation the correct syntax is brackets like in b2.

For b5 I dont really get what you're trying to do, that syntax doesn't really make sense to me.

For b6 it's not possible to create a byte using a constructor since constructors are related to objects and byte is a primitive type and not an object. If you'd type Byte instead you could do that since a Byte is the object wrapped version of a byte. (Same holds for other primitive data types, double & Double, boolean & Boolean, char & Character etc.)

2

You are actually asking several questions in one, which is fine. I will try to answer them all.

  1. The two are different because one declares a new String object on the heap, and one just points to a string literal. See this for more info: Why new keyword not needed for String

  2. B2 is an array of primitive types. Arrays are initialized at creation with {}.

  3. You probably receive an error because byte cannot store an integer, for one thing.

Community
  • 1
  • 1
nhouser9
  • 6,730
  • 3
  • 21
  • 42
2
  1. st1 You are using a String literal object which sits on the heap (if it doesn't exist already it will be created).

  2. st2 You could potentially be creating two objects here, first by writing "Test" you are using a literal (which may create a new object) and then explicitly creating a new String object from it. You are unlikely to ever need to use the String constructor.

  3. b1 You are creating a new byte array here, containing byte primitives. But essentially using syntactic sugar means you don't need to explicitly write new byte[] as this can be determined by the left hand side of the expression.

  4. b2 Exactly the same as b1 only in the full form.

  5. b3 Here you are using the () parenthesis as though you are calling a constructor. This is not how array allocations works. The {} braces are used to populate the array and there is no constructor for simple arrays. So, you are actually saying "My byte array contains 'a' and 'b'" when placed between {} braces.

  6. b4 This is fine, you are telling the compiler you want this byte b4 to represent the value 3.

  7. b5 This is incorrect because you are using the array initialization syntax and trying to 'construct' a primitive. b5 is not an array therefore you cannot use the {} braces to initialize it.

  8. b6 Here you are trying to call a constructor on a primitive. Primitives do not have constructors and so you do not ever need to new them, nor pass arguments to any constructor. You can simply assign values to them.

Jumwah
  • 517
  • 5
  • 19
2

At high level both are String object, but main difference comes from the point that new() operator always creates a new String object. Also when you create String using literal they are interned. This will be much more clear when you compare two String objects created using String literal and new operator, as shown in below example :

String a = "Java";     
String b = "Java";    
System.out.println(a == b);  // True    

Here two different objects are created and they have different references:

String c = new String("Java");    
String d = new String("Java");      
System.out.println(c == d);  // False    

Similarly when you compare a String literal with an String object created using new() operator using == operator, it will return false, as shown below :

String e = "JDK";        
String f =  new String("JDK");        
System.out.println(e == f);  // False        

Difference between String literal and String object

enter image description here
If my application is going to use some fixed number of string values , i will use string literals for better performance. But if my application will need different string at different times i will use 'new' operator to create them.

KP_JavaDev
  • 222
  • 2
  • 4
  • 11
2

Let us clear few things about primitives and non-primitives in java which is needed to understand the answer.

  • String is a class and it is not a primitive data type(only byte, short, int, long, double, boolean, float and char are primitives).

  • Memory is alloted in stack for primitive types and in heap for non-primitive types.

  • String is a special type. We can create string in the heap(where it behaves as a non-primitive) as well as stack (where it behaves as a primitive).

  • new(which calls constructor and creates object in heap) keyword is needed only for non-primitive types(like string in heap) but not needed for primitive types(like 'int').

Answer to 1st question:

String st2 = new String("Test");

in the above line you are creating string objects in heap. Since it is non-primitive you always need new to create objects for string in the heap.

Then you may think,"Then how did I create string object without new keyword in this line?"

 String st1 = "Test";

Here you are not creating string object in the heap. You are creating a string literal in the stack which behaves as a primitive type. Answer to 3rd question:

byte is a primitive data type, so you should not use new to create a byte or you will face a error.

byte b=new byte(4); //error

you are thinking, "Then why it didn't throw an error in this line?"

byte[] b2 = new byte[]{'a', 'b'};

It didn't throw an error, because you are not creating a byte object with new here. You are creating an array which is just like a reference object which refer to other objects in the heap.

Array is a non-primitive so you have to use new.

Answer to 2nd question:

2.Why we must pass the arguments of constructor in {} instead of (), in the b2 declaration line?

Here, you are not passing arguments to constructor. You are initialising an array with some values.

Array initialisation should use {} but not (). Hence the error

 byte[] b3 = new byte[]('a','b'); //Error
0

new keyword is used for creating objects of a particular class. There is operator overloading with '=' operator. As when we are writing String st1="Test"; It is performing the same things as done with String st2=new String("Test");. There is no as such any difference in both the statements other than operator overloading. In case of b1 and b2. An array of objects is created so we need to use {} for passing multiple values. For calling constructor we always use () parentheses not curly braces. That's why there is an error in b5. In case of b6 and b5 you have gotten error because byte is primitive data type whose wrapper class is Byte that's why you dont call constructor with an argument for primitive datatypes.

Shubham Agrawal
  • 298
  • 4
  • 10
  • 1
    There is no operator overloading here. There is just the compilation of string literals as object references. – user207421 Apr 23 '16 at 06:58