Mark
Mark

Reputation: 29

In Java, from where can a constructor be invoked?

Is this statement true or false?

"The only way a constructor can be invoked is from within another constructor."

I thought a constructor could be invoked from within a method (and other places) if the call to the constructor is preceded with the keyword 'new'.

How about this statement? True or false?

"The only way a constructor can be invoked is from within another constructor (using a call to super() or this()), or from within static or instance methods, static or instance initializer blocks, or even constructors, if the call to the constructor is preceded by the keyword 'new'." Trying to invoke a constructor like you would invoke a method (using only its name) is not allowed."

Is this more accurate? "Where the call to the constructor is not preceded by the keyword 'new', the only way a constructor can be invoked is from within another constructor using this() or super() as the first statement."

Upvotes: 0

Views: 5403

Answers (7)

Stephen C
Stephen C

Reputation: 718718

Rather than focusing on what the author of the original questions means by "invoke"1, here are the different ways that a constructor will be called.

  • By using the new operator with the class name and parameters that match the constructor signature:

        Foon f = new Foon(1, 2);
    

    It is also possible to do the same thing using reflection and the Constructor object equivalent to a new expression, or by using the relevant JNI or JNA callbacks in native code equivalent to a new expression. However, in all cases, the constructor invocation is conceptually happening at same point in the object creation. Hence I will treat them as identical.

  • By explicitly chaining to the constructor from another constructor in the same class using this(...).

  • By explicitly chaining to the constructor from a direct subclass constructor using super(...), or by implicitly chaining to a no-args constructor via an implied super() in a direct subclass constructor (declared or implied).

    The implicit cases are merely "syntactic sugar" for the explicit super chaining cases.


There are a few other places where new is invoked behind the scenes by Java from regular Java code. A couple that spring to mind are string concatenation, auto-boxing, and the JVM throwing certain exceptions; e.g.

    null.toString()   // implicitly creates a NullPointerException obj.

1 - ... which is unknowable unless we understand the context, including how the OP's lecturer (or text book) is using the word "invoke".

Upvotes: 2

biziclop
biziclop

Reputation: 49724

If you mean, directly invoking another constructor of the same object using the this(...) or super(...) construct (called explicit constructor invocation), the answer is yes.

It is probable that this is what the question meant but you have to be really precise in the wording and this question isn't.

Because if by "invoke" you mean, "causing a constructor to run", then you can "invoke" a constructor with the new keyword, which first allocates and creates the object, and then a constructor is run. In this, rather looser sense the answer is no.

But, importantly, new does a lot more than just calling the constructor. So in the most literal sense, calling new is not the same as invoking a constructor. Just like making tea involves pouring hot water but is not the same as simply pouring hot water.

Whether you want to make that distinction or not is up to you, or in this case the author of the question, you need to ask them.

Upvotes: 0

Let's just go straight to the JLS, §8.8:

Constructors are invoked by class instance creation expressions (§15.9), by the conversions and concatenations caused by the string concatenation operator + (§15.18.1), and by explicit constructor invocations from other constructors (§8.8.7). [...]

Constructors are never invoked by method invocation expressions (§15.12).

Therefore, the first statement you quoted is technically false, as the JLS defines using new as invoking the constructor.

Note that your paragraph-length statement is a combination of true and false information; you can't invoke a constructor from static or instance methods except via creating a new object.

Upvotes: 2

Clashsoft
Clashsoft

Reputation: 11882

This statement is false.

'Invoking a constructor' can mean three different things:

  1. You can invoke a constructor by creating a new object with the new operator:

    String s = new String("abc");
    

    In which case you will first allocate an object and then invoke the constructor:

    NEW java/lang/String // allocate String instance
    LDC "abc"            // push the String constant on the stack
    INVOKESPECIAL "java/lang/String"."<init>" : "(Ljava/lang/String;)V" // invoke constructor
    
  2. The second way is to invoke another constructor from the same class:

    class Super
    {
        Super(int i) { }
    }
    class Test extends Super {
        Test() { this(1); }
        // Bytecode:
           INVOKESPECIAL "Test"."<init>" : "(I)V"
        // ---------
    
  3. The third way to invoke a constructor is to invoke one from the super class:

        Test(int i) { super(i); }
        // Bytecode:
           INVOKESPECIAL "Super"."<init>" : "(I)V"
        // ---------
    }
    

Either way, the generated bytecode will contain an INVOKESPECIAL instruction. This means you are literally invoking the constructor in three cases, so if you define 'invoke' by that instruction, there is more than one way to invoke a constructor.

Upvotes: 0

You can use the constructor when you use the class as an object in other class.

MyClass mc = new MyClass();

Upvotes: 0

Tahar Bakir
Tahar Bakir

Reputation: 716

The famous illusive constructor. It's there when it's there, and even when it's not there it's still there.

The constructor is called at object creation.

So yeah the constructor can, or more precisely will be called if you create a object using new , na matter where you use it.

That quote of yours seems to be incomplete

"The only way the constructor of the superclass of the current class can be invoked is from within the current class constructor."

Upvotes: 0

Mohammed Aouf Zouag
Mohammed Aouf Zouag

Reputation: 17132

It's true. You can't write code that actually calls a constructor as follows:

class Vehicle {
    Vehicle() { } // Constructor
    void doSomething() {
        Vehicle(); // Illegal
    }
}

Upvotes: 0

Related Questions