How object creation or constructors called implicitly in Java - java

I'm little confused about static methods and object creation in java.
As we know we can access static members in static method as here.
public static void main(String[] args){
// only static method from outside ( without any object )
}
But my stupid question is that why java allow this?
`public static void main(String[] args){
Object o = new Object(); // is constructor implicitly static?
// I'm sure no but why java allow this to call here?
}
I know the above statement is similar to declare local variable in static method.
public static void main(String[] args){
int a = 3;
}
But I'm little confused about constructor.

In bytecode, your main() method looks like this (result of the javap -c Main.class command):
public static void main(java.lang.String[]);
Code:
0: new #3 // class java/lang/Object
3: dup
4: invokespecial #8 // Method java/lang/Object."<init>":()V
7: astore_1
8: return
As you can see, at location 0, the new instruction is performed. Then, at location 4, the constructor is invoked on the newly created object.
This is also specified in the Java Virtual Machine Specification:
4.10.2.4. Instance Initialization Methods and Newly Created Objects
Creating a new class instance is a multistep process. The statement:
...
new myClass(i, j, k);
...
can be implemented by the following:
...
new #1 // Allocate uninitialized space for myClass
dup // Duplicate object on the operand stack
iload_1 // Push i
iload_2 // Push j
iload_3 // Push k
invokespecial #5 // Invoke myClass.<init>
...

Constructors are not static. They are called on the instance, you just created. In byte code what happens.
An new object is created, but it is not inilialised.
The constructor is called on that object. In the constructor this is the object being initialised.

Related

How I am able to access the enum value just by reference, where reference itself is null? [duplicate]

The following simple code snippet is working fine and is accessing a static field with a null object.
final class TestNull
{
public static int field=100;
public TestNull temp()
{
return(null);
}
}
public class Main
{
public static void main(String[] args)
{
System.out.println(new TestNull().temp().field);
}
}
In the above code, the statement System.out.println(new TestNull().temp().field); in which the static field field is being associated with a NULL objectnew TestNull().temp(), still it is returning a correct value of it which is 100 instead of throwing a null pointer exception in Java! Why?
As opposed to regular member variables, static variables belong to the class and not to the instances of the class. The reason it works is thus simply because you don't need an instance in order to access a static field.
In fact I'd say it would me more surprising if accessing a static field could ever throw a NullPointerException.
If you're curious, here's the bytecode looks for your program:
// Create TestNull object
3: new #3; //class TestNull
6: dup
7: invokespecial #4; //Method TestNull."<init>":()V
// Invoke the temp method
10: invokevirtual #5; //Method TestNull.temp:()LTestNull;
// Discard the result of the call to temp.
13: pop
// Load the content of the static field.
14: getstatic #6; //Field TestNull.field:I
This is described in the Java Language Specification, Section 15.11.1: Field Access Using a Primary. They even provide an example:
The following example demonstrates that a null reference may be used to access a class (static) variable without causing an exception:
class Test {
static String mountain = "Chocorua";
static Test favorite(){
System.out.print("Mount ");
return null;
}
public static void main(String[] args) {
System.out.println(favorite().mountain);
}
}
It compiles, executes, and prints:
Mount Chocorua
Static variables are shared among every object of a class. So while the actual object reference you are returning is null (In C++: TestNull* temp = null;), you have an object of type TestNull which Java can use to find static values of that class.
Remember in Java objects are really pointers. Pointers have a type. From that type Java can discern certain information, even if its pointing to null.
Static fields are associated with the class not an instance of that class. Therefore you don't need an instance of an object to access the static field.
You could also access the field by calling TestNull.field

Understanding dynamic polymorphsim byte code

I am a novice to Java byte code and would like to understand the following byte code of Dispatch.class relative to Dispatch.java source code below :
Compiled from "Dispatch.java"
class Dispatch {
Dispatch();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public static void main(java.lang.String[]);
Code:
0: new #2 // class B
3: dup
4: invokespecial #3 // Method B."<init>":()V
7: astore_1
8: aload_1
9: invokevirtual #4 // Method A.run:()V
12: return
}
//=====================Dispatch.java==============================
class Dispatch{
public static void main(String args[]){
A var = new B();
var.run(); // prints : This is B
}
}
//======================A.java===========================
public class A {
public void run(){
System.out.println("This is A");
}
}
//======================B.java===========================
public class B extends A {
public void run(){
System.out.println("This is B");
}
}
After doing some reading on the internet I had a first grasp of how JVM stack and opcodes work. I still however do not get what these command lines are good for :
3: dup //what are we duplicating here exactly?
4: invokespecial #3 //what does the #3 in operand stand for?
invokevirtual VS invokespecial //what difference there is between these opcodes?
It really sounds like you need to read the docs some more, but to answer your updated questions,
dup duplicates the top value on the operand stack. In this case, it would be the uninitialized B object that was pushed by the previous new instruction.
The #3 means that invokespecial is operating on the 3rd slot in the classfile's constant pool. This is where the method to be invoked is specified. You can see the constant pool by passing -c -verbose to javap.
invokevirtual is used for ordinary (non interface) virtual method calls. (Ignoring default interface methods for the moment) invokespecial is used for a variety of special cases - private method calls, constructor invocations, and superclass method calls.

How do static methods run?

How do static methods actually run in Java? We usually invoke them using the class name, and do not create any object for them, but these are objects which actually can "run", not methods!
For static methods, a special keyword is available and added as part of the byte-code. It is called invokestatic.
From Oracle docs :
invokestatic
Operation
Invoke a class (static) method
Description :
The unsigned indexbyte1 and indexbyte2 are used to construct an index
into the run-time constant pool of the current class (§2.6), where the
value of the index is (indexbyte1 << 8) | indexbyte2. The run-time
constant pool item at that index must be a symbolic reference to a
method (§5.1), which gives the name and descriptor (§4.3.3) of the
method as well as a symbolic reference to the class in which the
method is to be found. The named method is resolved (§5.4.3.3). The
resolved method must not be an instance initialization method (§2.9)
or the class or interface initialization method (§2.9). It must be
static, and therefore cannot be abstract.
On successful resolution of the method, the class that declared the
resolved method is initialized (§5.5) if that class has not already
been initialized.
The operand stack must contain nargs argument values, where the
number, type, and order of the values must be consistent with the
descriptor of the resolved method.
Sample code :
public class Example {
static void myStaticMethod() {
System.out.println("Hello");
}
public static void main(String[] args) {
myStaticMethod();
}
}
Byte code :
public static void main(java.lang.String[]);
descriptor: ([Ljava/lang/String;)V
flags: ACC_PUBLIC, ACC_STATIC
Code:
stack=0, locals=1, args_size=1
0: invokestatic #31 // Method myStaticMethod:()V
3: return
LineNumberTable:
line 8: 0
line 9: 3
LocalVariableTable:
Start Length Slot Name Signature
0 4 0 args [Ljava/lang/String;
Runtime constant pool of class :
...
#31 = Methodref #1.#32 // Example.myStaticMethod:()V
...
In case of static method Java loads the method when the class is loaded and shares the method with all the objects also and that's why an object is not necessary.
It's not always necessary to have an object in order to run a method.
And no, it's not the object that runs. It's the method that does the operation and objects or classes hold them as a property.

When to declare objects?

I have been working on some of my AP cs projects and came to the wonder the difference between doing this:
public class CalculateTaxes {
private Scanner in;
public CalculateTaxes(){
in = new Scanner(System.in);
}
}
and this:
public class CalculateTaxes {
private Scanner in = new Scanner(System.in);
public CalculateTaxes(){
}
}
I've seen many examples were they declare an object in one line and instantiate it somewhere else in the code. Why not just declare and instantiate an object in the same line?
Lets test how these classes will be compiled.
public class Test1 {
private Scanner in;
public Test1() {
in = new Scanner(System.in);
}
}
and
public class Test2 {
private Scanner in = new Scanner(System.in);
public Test2() {
}
}
If we use javap -c Test1 we will see
Compiled from "Test1.java"
public class Test1 {
public Test1();
Code:
0: aload_0
1: invokespecial #10 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #12 // class java/util/Scanner
8: dup
9: getstatic #14 // Field java/lang/System.in:Ljava/io/InputStream;
12: invokespecial #19 // Method java/util/Scanner."<init>":(Ljava/io/InputStream;)V
15: putfield #22 // Field in:Ljava/util/Scanner;
18: return
}
and if we use it on Test2 we will get
Compiled from "Test2.java"
public class Test2 {
public Test2();
Code:
0: aload_0
1: invokespecial #10 // Method java/lang/Object."<init>":()V
4: aload_0
5: new #12 // class java/util/Scanner
8: dup
9: getstatic #14 // Field java/lang/System.in:Ljava/io/InputStream;
12: invokespecial #19 // Method java/util/Scanner."<init>":(Ljava/io/InputStream;)V
15: putfield #22 // Field in:Ljava/util/Scanner;
18: return
}
So as you can see the initialization of in field in Test2 class was automatically moved by compiler at start of constructor.
In fact this code will be moved at start of each constructor of that class (right after super() call if any) so only difference is that if you have few constructors you can initialize in field in one place outside constructors instead of doing it in every one of them.
But if lets say you want to initialize field depending on some argument passed in constructor then you have to do it in constructors block.
If you intend to assign an object a value in one scope but need it to be visible in another it can be useful to split up the declaration and the assignment.
Pseudocode:
{
// Outer loop
SomeObject a;
if (condition_one == condition_two)
a = new SomeObject(4);
else
a = new SomeObject(12);
a.doStuff();
}
If a had been declared only inside of the if statements, it wouldn't be visible outside of that loop.
{
if (a == b)
SomeObject a = new SomeObject(5);
a.doStuff(); // ERROR
}
There's not much difference in this case. In some cases, you use different parameters depending on what parameters are sent in the constructor.
Ultimately, in a professional programming environment, your goal is not what is best "right now", but what will help you understand what's going on in 6 months when you need to reread your code and understand WHY you were doing something. HOW you implemented it will help document the intent.

Accessing a static field with a NULL object in Java

The following simple code snippet is working fine and is accessing a static field with a null object.
final class TestNull
{
public static int field=100;
public TestNull temp()
{
return(null);
}
}
public class Main
{
public static void main(String[] args)
{
System.out.println(new TestNull().temp().field);
}
}
In the above code, the statement System.out.println(new TestNull().temp().field); in which the static field field is being associated with a NULL objectnew TestNull().temp(), still it is returning a correct value of it which is 100 instead of throwing a null pointer exception in Java! Why?
As opposed to regular member variables, static variables belong to the class and not to the instances of the class. The reason it works is thus simply because you don't need an instance in order to access a static field.
In fact I'd say it would me more surprising if accessing a static field could ever throw a NullPointerException.
If you're curious, here's the bytecode looks for your program:
// Create TestNull object
3: new #3; //class TestNull
6: dup
7: invokespecial #4; //Method TestNull."<init>":()V
// Invoke the temp method
10: invokevirtual #5; //Method TestNull.temp:()LTestNull;
// Discard the result of the call to temp.
13: pop
// Load the content of the static field.
14: getstatic #6; //Field TestNull.field:I
This is described in the Java Language Specification, Section 15.11.1: Field Access Using a Primary. They even provide an example:
The following example demonstrates that a null reference may be used to access a class (static) variable without causing an exception:
class Test {
static String mountain = "Chocorua";
static Test favorite(){
System.out.print("Mount ");
return null;
}
public static void main(String[] args) {
System.out.println(favorite().mountain);
}
}
It compiles, executes, and prints:
Mount Chocorua
Static variables are shared among every object of a class. So while the actual object reference you are returning is null (In C++: TestNull* temp = null;), you have an object of type TestNull which Java can use to find static values of that class.
Remember in Java objects are really pointers. Pointers have a type. From that type Java can discern certain information, even if its pointing to null.
Static fields are associated with the class not an instance of that class. Therefore you don't need an instance of an object to access the static field.
You could also access the field by calling TestNull.field

Categories