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