Any way to _not_ call superclass constructor in Java? - java

If I have a class:
class A {
public A() { }
}
and another
class B extends A {
public B() { }
}
is there any way to get B.B() not to call A.A()?

There is absolutely no way to do this in Java; it would break the language specification.
JLS 12 Execution / 12.5 Creation of New Class Instances
Just before a reference to the newly created object is returned as the result, the indicated constructor is processed to initialize the new object using the following procedure:
Assign the arguments for the constructor [...]
If this constructor begins with an explicit constructor invocation of another constructor in the same class (using this), then [...]
This constructor does not begin with an explicit constructor invocation of another constructor in the same class (using this). If this constructor is for a class other than Object, then this constructor will begin with an explicit or implicit invocation of a superclass constructor (using super).
Execute the instance initializers and instance variable initializers for this class [...]
Execute the rest of the body of this constructor [...]

The closest you can achieve to the desired behaviour is to delegate initialisation normally performed in the constructor to a template method, which you then override in your subclass implementation. For example:
public class A {
protected Writer writer;
public A() {
init();
}
protected void init() {
writer = new FileWriter(new File("foo.txt"));
}
}
public class B extends A {
protected void init() {
writer = new PaperbackWriter();
}
}
However, as other people have noted this can typically indicate a problem with your design and I typically prefer the composition approach in this scenario; for example in the above code you could define the constructor to accept a Writer implementation as a parameter.

Java deserialisation doesn't call the constructor, but it seems that it is based on some internal JVM tricks.
However, there is a framework that allows you to do that in a portable manner: Objenesis (http://www.theserverside.com/discussions/thread/44297.html)
I've seen this recently in Spring, when using CGLIB proxies, Spring creates two class instances, but the constructor is called only once: https://stackoverflow.com/a/11583641/2557118
This behavior is added in Spring 4:
CGLIB-based proxy classes no longer require a default constructor.
Support is provided via the objenesis library which is repackaged
inline and distributed as part of the Spring Framework. With this
strategy, no constructor at all is being invoked for proxy instances
anymore.

The possibility is that you can call the super class constructor of your choice. That is possible by calling the super class constructor explicitly as :
super(para_1, para_2,........);
class BaseA {
BaseA(){
System.out.println("This is BaseA");
}
BaseA(int a){
System.out.println("This is BaseA a");
}
}
class A extends BaseA {
A(){
super(5);
System.out.println("This is A");
}
public static void main(String[] args) {
A obj=new A();
}
}
Output will be:
This is BaseA a
This is A

No and if you could, your derived object wouldn't really be the object it's deriving from now would it? The is-a principle would be violated. So if you really need it, then polymorphism isn't what you're after.

Every superclass needs to be constructed and there is no other way then calling a constructor.

I think the only way to do it is messing up with the byte-code.
I'm not sure if the Classloader or the JVM checks if super() is being called, but, as Bozho wrote, you probably would end with inconsistent objects when doing so.

Nope - you cannot do it and why would you want to do it anyway? That would mess up your object model.
Anyways - i believe if you still want to do it and then you would have to manipulate the generated byte code.... there are a couple of libraries available that make it easy to instrument the byte code.
Strongly suggest against doing it...

Every object in java is a subclass of Object (object with a capital 'O'). when you create an object of a subclass the super class constructor is invoked. Even if your class is not inhereting anyother class, implicitly it is inheriting Object, so the Object constructor has to be called. So super() is invoked for this purpose.

Assuming you mean
class B extends A {
public B() { }
}
then sure you can
class B extends A {
public B() {
this(abort());
}
private B(Void dummy) {
/* super(); */
}
private static Void abort() {
throw null;
}
}
Not very useful. The interface [not Java keyword] to class A says that you need to run its constructor in order to construct it, not unreasonably. The exception is that serialisable classes are constructed without calling the constructors of the serialisable classes.

As pointed out by another poster, B doesn't extend A, so it won't call A's constructor anyways.
There is no way to do this in Java.
You can probably accomplish equivalently what you want to do as follows:
a) in each class of your hierarchy, include a constructor with a unique signature that calls the superclass's constructor with its arguments. For example, declare a class "Noop" and a constructor that takes that as an argument:
public class NoOp {
}
public class class1 {
class1() {
System.out.println("class1() called");
}
class1(String x, String y) {
System.out.println("class1(String, String) called");
}
class1(NoOp x) {
System.out.println("class1(NoOp) called");
}
}
public class class2 extends class1 {
class2() {
System.out.println("class2() called");
}
class2(String x, String y) {
System.out.println("class2(String, String) called");
}
class2(NoOp x) {
super(x);
System.out.println("class2(NoOp) called");
}
}
public class class3 extends class2 {
class3() {
System.out.println("class3() called");
}
class3(String x, String y) {
super(new NoOp());
System.out.println("class3(String, String) called");
}
class3(NoOp x) {
super(x);
System.out.println("class3(NoOp) called");
}
public static void main(String args[]) {
class3 x = new class3("hello", "world");
}
}
If you run this you will get the output
class1(NoOp) called
class2(NoOp) called
class3(String, String) called
So, effectively you have created a class3 constructor that only calls constructors that don't do anything.

I had a similar requirement where I needed my child class NOT to go through the super class' constructor, and I wanted the rest of the benefits of the super class. Since super class is also mine, here's what I did.
class SuperClass {
protected SuperClass() {
init();
}
// Added for classes (like ChildClassNew) who do not want the init to be invoked.
protected SuperClass(boolean doInit) {
if (doInit)
init();
}
//
}
class ChildClass1 extends SuperClass {
ChildClass1() {
// This calls default constructor of super class even without calling super() explicitly.
// ...
}
// ....
}
class ChildClass2 extends SuperClass {
ChildClass2() {
// This calls default constructor of super class even without calling super() explicitly.
// ...
}
// ....
}
class ChildClassNew extends SuperClass {
ChildClassNew() {
/*
* This is where I didn't want the super class' constructor to
* be invoked, because I didn't want the SuperClass' init() to be invoked.
* So I added overloaded the SuperClass' constructor where it diesn;t call init().
* And call the overloaded SuperClass' constructor from this new ChildClassNew.
*/
super(false);
//
// ...
}
// ....
}

Related

Difference between a protected and package-private (no modifier) constructor?

Possible Duplicate
The top answer given there states that the protected constructor can be called using super() but cannot be instantiated using new? Why so? And if that is the reason then what is the difference between package-private(no modifier) and protected constructor?
The following code is not getting me any difference.
package pack1;
public class Rr {
protected Rr() {
System.out.println("Rello");
}
}
package pack2;
class Tt extends pack1.Rr {
Tt() {
super(); //works
pack1.Rr r = new pack1.Rr(); //error
}
}
class Uu {
public static void main(String args[]) {
Tt t = new Tt();
}
}
A protected method can be accessed via its sub-class objects.
Note, "sub-class" here is very important, which means "via a sub-class way", not "anywhere within a sub-class".
Let's look at an example.
Following are 2 classes:
package one;
public class A {
protected A() {} // protected constructor
public A(int i) {} // public constructor
protected void foo() {} // protected method
}
package two;
import one.A;
public class B extends A {
public void bar() {
this.foo(); // correct
A a = new A(0); // call A's public constructor to construct an A instance.
a.foo(); // compiler error: the method foo from the type A is not visible.
}
}
The first invocation is permitted, but the second not, why?
Like I said, the first one is accessing via "a sub-class way", in which this is A's sub-class instance; however the second just "within a sub-class" (here B is no meaning to A, it's just an ordinary class, so it can not access A's protected method).
Another example is Object.clone. This is a protected method of root class Object. You might likely say it can be accessed from any object created from any class, but the answer is capital "NO": only those codes which are using "sub-classes way" can access it.
The following illustrates this:
this.clone(); // ok
Object o = new Object();
o.clone(); // compiler error: the method clone from the type Object is not visible.
A "default constructor" is a constructor that Java generates if you don't provide one yourself; it's always has the same access as the class itself and has no arguments. Ie when you define
class YourClass {}
the system makes it
class YourClass {
YourClass() {} // default constructor
}
If you create a any other constructor - even a public one with no arguments - it is not a default constructor. The second code piece above would prevent the system from generating one, because you already declared it.
The same is true if you create a protected constructor. Compare:
public class Class1 {}
public class Class2 {
protected Class2() {}
}
you can instantiate Class1, but not Class2:
// invokes autogenerated default constructor
Class1 c1 = new Class1();
// compile error: default constructor is not generated because you declared a protected one
Class2 c2 = new Class2();
As #Turing85 states in a comment, the protected modifier only means that the declared constructor can only be invoked within the proper access scope - from subclasses or classes in the same package.
For completeness' sake: you can call both super() and the constructor explicitly from a subclass:
class Class3 extends Class2() {
public Class3() {
// call to protected constructor of Class2
super();
// explicit call to constructor by creating new instance
Class2 o = new Class2();
}
}
EDIT: I just tried it out, and the last sample is only valid if the two classes are in the same package. I don't know and would like to know.
protected gives access to subclasses, in addition to the classes in the same package.
When you call the constructor directly, e.g. new A() you can think of it as calling a static method. There is no instance of the class yet, thus inheritance rules cannot apply. Therefore, static access rules apply: if the constructor is protected, then it must be in the same package in order to be accessible.
Once you are inside a constructor code and you call super(), then you already have an instance, so if you are in a subclass and call the protected constructor it will work.

Calling of Constructors in a Java

In the book Java: The complete reference
// Demonstrate when constructors are called.
// Create a super class.
class A {
A() {
System.out.println("Inside A's constructor.");
}
}
// Create a subclass by extending class A.
class B extends A {
B() {
System.out.println("Inside B's constructor.");
}
}
// Create another subclass by extending B.
class C extends B {
C() {
System.out.println("Inside C's constructor.");
}
}
class CallingCons {
public static void main(String args[]) {
C c = new C();
}
}
Output:
Inside A’s constructor
Inside B’s constructor
Inside C’s constructor
It is demonstrating how the constructor of a subclass is called. But why are constructors of the super class called in the absence of a super() constructor.
Why did the Java Language designers consider it necessary to do so?
As others have pointed out, if you don't start your constructor with a super(...) call, the compiler will put in a call to super() for you.
As to the why, you have to start with remembering what a constructor is for in the first place: initializing the object. What does that mean, specifically? In practice, it means assigning values to the object's fields, and establishing invariants.
Without a call to super(), the B and A classes wouldn't have a chance to do that for whatever fields they contain. And you can't even have the C() constructor do it for them, if those fields are private, since private fields aren't accessible outside your class (not even your super class's fields are accessible). Even if you could, it wouldn't be a good idea; it would also break encapsulation. For instance, imagine having to change your code if a super class -- possibly a complex one whose internals you're not an expert in -- suddenly decided to change its implementation details.
To illustrate this, consider a very simple set of classes:
public class Super {
private final String name;
Super() {
name = "default";
}
public String name() {
return name.toUpperCase();
}
}
public class Sub extends Super {
public Sub() {
// don't do anything
}
}
When you instantiate Sub, it will start out by calling Super's constructor. If it didn't, the name field would be null (the default value for reference types). But the name() method doesn't check for null; it assumes that the reference is non-null, because the constructor establishes that invariant. So, in our pseudo-Java that doesn't call the super constructor, Super.name has to get a bit more complicated -- it has to check for name == null.
You can imagine that as the classes gain more fields, with more interesting invariants, this toy example can become more and more complicated. Forcing you to call the super constructor -- either explicitly or implicitly -- lets the authors of that super class establish their invariants, resulting in simpler, more maintainable code.
Every constructor calls its superclass constructor. super() call take place as the first line in the constructor. From javadoc:
If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the
no-argument constructor of the superclass. If the super class does not
have a no-argument constructor, you will get a compile-time error.
Object does have such a constructor, so if Object is the only
superclass, there is no problem.
more here
Because it says so in the Java Language Specification.
If a constructor body does not begin with an explicit constructor invocation and the constructor being declared is not part of the primordial class Object, then the constructor body implicitly begins with a superclass constructor invocation "super();", an invocation of the constructor of its direct superclass that takes no arguments.
Even it has a role with Abstract classes also. we can't initialize object of abstract class. But Child class of Abstract class calls the super() method by default. So abstract class constructor can initialize its instance variables.
for example:
public abstract class TestA {
private int a;
public TestA()
{
a=10;
}
public int displayA()
{
return a;
}
abstract void display();
}
public class TestB extends TestA{
#Override
void display() {
System.out.println("this is class B");
}
}
package Abstract;
public class TestMain {
public static void main(String[] args) {
TestA obj= new TestB();
System.out.println(obj.displayA());
}
}
Output is : 10
Here you can see, when we initiating object of class TestB , by default super constructor is calling and TestA's constructor is assigning the value of a. If super will not be called by default we can't assign instance variables of abstract class.
Inheritance is basically inheriting all the properties of your parent class. So if a sub class constructor is called, it should definitely and by default inherit all its parent class properties also. In the following code, all the properties of class A should be made available in class B also, so if I just call B's constructor, all the class A's properties(except private) are also initialized and made available, meaning B has inherited A's properties
class A {
protected int a;
A() {
a=12;
System.out.println("Inside A's constructor.");
}
}
class B extends A {
B() {
System.out.println("Inside B's constructor.");
System.out.println(a);
}
}
public class ConstructorInheritance {
public static void main(String args[]) {
B b=new B();
}
}
output:
Inside A's constructor.
Inside B's constructor.
12
Imagine class C accessing an unitialized variable of class B or A. Implicitly calling constructors of class B-->class A makes sure that you are always accessing initialized variables of inherited classes(A or B)
"The Java programming language" says "A constructor in subclass can initialize its individual state, however, as keeping contract, only super class knows how to initialize super class's state".
Thus, constructor of super class have to be called. There is sequence how the constructor processed:
Call super class constructor
Initialize fields with initializers and initialization blocks
Execute body of the constructor
For more details, have a look of the book to section "3.2".

Does JVM call default Constructor of Anonymous Class to create instance?

Does JVM call default Constructor of Anonymous Class to create instance.
My understanding may be stupid for that. I think, even if Reflection API is used to create an instance, there will be at least Default Constructor. Anonymous Class have a Default Constructor? Otherwise, how JVM or whatever create instance?
Yes it does. You can even use other constructors through specifying parameters:
Given
public abstract class A {
String str;
public A(String str){
this.str=str;
}
public abstract void doSomething();
}
You can do
...
A a = new A("Hello World") {
public void doSomething() {
System.out.println(str);
}
};
a.doSomething();
When a class doesn't have an explicit constructor, it has an implicit default empty constructor. That is called, just as any other constructor would be called.
It appears to me that unlike normal classes, anonymous classes has different behaviour associated with implicit constructors.
When you define a normal class, compiler can implicitly insert only a no-arg constructor.
But with anonymous class you can get (implicitly by a compiler) all the constructors the superclass has.
Say we have a class:
class A {
A(int i) {}
A(String s) {}
}
If we subclass it as follows...
class B extends A {}
...we get a compilation error because compiler tries to do this:
class B extends A {
B() {
super(); // Error: there's no no-arg superclass constructor!
}
}
But when we create an anonymous class it implicitly creates constructors as defined for a superclass (A)
A a1 = new A(1) {}; // OK. Uses (int) constructor
A a2 = new A("") {}; // OK. Uses (String) constructor
A a3 = new A() {}; // Error. There's no no-arg constructor
As if our anonymous class has these constructors
X(int i) {
super(i);
}
X(String s) {
super(s);
}
Anonymous classes have a default no args constructor that is called once by the JVM. Since an anonymous class has no name, it is not possible to define a constructor for an anonymous class. If your class requires a constructor, you must use a local class instead.
In any case, a constructor is called to initialize newly created object. Anonymous class has default constructor, which initialize the fields of the class, if any, and calls constructor of the superclass.

how to make constructor definition mandatory

I have an interface I that is implemented by a base class B. The base class is extended by a bunch of classes (A,C,D) that must init some of the protected vars declared in base class B. I'd like to make the declaration of a constructor mandatory in the subclasses (A,C,D), to discourage the user from relying on default constructor that's declared in B. Yet I do want the B's default constructor to execute automatically, since B can be used by itself as well. How can I accomplish this?
thanks
Use an abstract superclass of B with a private constructor:
public abstract class BSuper {
private BSuper() {
// initialize stuff
}
protected BSuper(some params) {
this():
// other init with parms
}
}
public class B extends BSuper {
public B(some other params) {
super(some params);
}
}
public class A extends B {
public A() {
super(some other params);
}
}
or similar
Make B's default constructor private and call this(); from within the parameterized constructor...
public class B {
private B() {
super();
}
public B( Foo foo ) {
this();
}
public static B createInstance() {
return new B();
}
}
Edit: Miss read the issue, removed abstract keyword from class declaration. Also added public static factory method for creating B class. It calls B's default constructor.
Just write a comment in the Javadoc that says "Use of default constructor is discouraged when subclassing." In my experience, trying to enforce that programmatically is not worth the effort and could cause problems latter on. Simple English will do.
If class B is going to have its own default constructor, what you want is impossible. When you derive from a class, you're telling the compiler that it should allocate memory for a base class object in every instance of the derived class. There's no way to tell a java compiler to suddenly take away some of the base class's functionality every time that something is inherited from it.
Also note that constructors and static factory methods can't be abstract, so even if B could be an abstract class you would have to do something like:
public class B {
B() {
initialize();
}
protected abstract void initialize();
}
...along with making sure that the derived classes implement default constructors that call super()

When do I use super()?

I'm currently learning about class inheritance in my Java course and I don't understand when to use the super() call?
Edit:
I found this example of code where super.variable is used:
class A
{
int k = 10;
}
class Test extends A
{
public void m() {
System.out.println(super.k);
}
}
So I understand that here, you must use super to access the k variable in the super-class. However, in any other case, what does super(); do? On its own?
Calling exactly super() is always redundant. It's explicitly doing what would be implicitly done otherwise. That's because if you omit a call to the super constructor, the no-argument super constructor will be invoked automatically anyway. Not to say that it's bad style; some people like being explicit.
However, where it becomes useful is when the super constructor takes arguments that you want to pass in from the subclass.
public class Animal {
private final String noise;
protected Animal(String noise) {
this.noise = noise;
}
public void makeNoise() {
System.out.println(noise);
}
}
public class Pig extends Animal {
public Pig() {
super("Oink");
}
}
super is used to call the constructor, methods and properties of parent class.
You may also use the super keyword in the sub class when you want to invoke a method from the parent class when you have overridden it in the subclass.
Example:
public class CellPhone {
public void print() {
System.out.println("I'm a cellphone");
}
}
public class TouchPhone extends CellPhone {
#Override
public void print() {
super.print();
System.out.println("I'm a touch screen cellphone");
}
public static void main (strings[] args) {
TouchPhone p = new TouchPhone();
p.print();
}
}
Here, the line super.print() invokes the print() method of the superclass CellPhone. The output will be:
I'm a cellphone
I'm a touch screen cellphone
You would use it as the first line of a subclass constructor to call the constructor of its parent class.
For example:
public class TheSuper{
public TheSuper(){
eatCake();
}
}
public class TheSub extends TheSuper{
public TheSub(){
super();
eatMoreCake();
}
}
Constructing an instance of TheSub would call both eatCake() and eatMoreCake()
When you want the super class constructor to be called - to initialize the fields within it. Take a look at this article for an understanding of when to use it:
http://download.oracle.com/javase/tutorial/java/IandI/super.html
You could use it to call a superclass's method (such as when you are overriding such a method, super.foo() etc) -- this would allow you to keep that functionality and add on to it with whatever else you have in the overriden method.
Super will call your parent method. See: http://leepoint.net/notes-java/oop/constructors/constructor-super.html
You call super() to specifically run a constructor of your superclass. Given that a class can have multiple constructors, you can either call a specific constructor using super() or super(param,param) oder you can let Java handle that and call the standard constructor. Remember that classes that follow a class hierarchy follow the "is-a" relationship.
The first line of your subclass' constructor must be a call to super() to ensure that the constructor of the superclass is called.
I just tried it, commenting super(); does the same thing without commenting it as #Mark Peters said
package javaapplication6;
/**
*
* #author sborusu
*/
public class Super_Test {
Super_Test(){
System.out.println("This is super class, no object is created");
}
}
class Super_sub extends Super_Test{
Super_sub(){
super();
System.out.println("This is sub class, object is created");
}
public static void main(String args[]){
new Super_sub();
}
}
From oracle documentation page:
If your method overrides one of its superclass's methods, you can invoke the overridden method through the use of the keyword super.
You can also use super to refer to a hidden field (although hiding fields is discouraged).
Use of super in constructor of subclasses:
Invocation of a superclass constructor must be the first line in the subclass constructor.
The syntax for calling a superclass constructor is
super();
or:
super(parameter list);
With super(), the superclass no-argument constructor is called. With super(parameter list), the superclass constructor with a matching parameter list is called.
Note: If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error.
Related post:
Polymorphism vs Overriding vs Overloading

Categories