Java constructor order of calling [duplicate] - java

I ended up the following scenario in code earlier today (which I admit is kinda weird and I have since refactored). When I ran my unit test I found that a field initialization was not set by the time that the superclass constructor has run. I realized that I do not fully understand the order of constructor / field initialization, so I am posting in the hopes that someone explain to me the order in which these occur.
class Foo extends FooBase {
String foo = "foobar";
#Override
public void setup() {
if (foo == null) {
throw new RuntimeException("foo is null");
}
super.setup();
}
}
class FooBase {
public FooBase() {
setup();
}
public void setup() {
}
}
#Test
public void testFoo() {
new Foo();
}
The abbreviated backtrace from JUnit is as follows, I guess I expected $Foo.<init> to set foo.
$Foo.setup
$FooBase.<init>
$Foo.<init>
.testFoo

Yes, in Java (unlike C#, for example) field initializers are called after the superclass constructor. Which means that any overridden method calls from the constructor will be called before the field initializers are executed.
The ordering is:
Initialize superclass (recursively invoke these steps)
Execute field initializers
Execute constructor body (after any constructor chaining, which has already taken place in step 1)
Basically, it's a bad idea to call non-final methods in constructors. If you're going to do so, document it very clearly so that anyone overriding the method knows that the method will be called before the field initializers (or constructor body) are executed.
See JLS section 12.5 for more details.

A constructor's first operation is always the invocation of the superclass constructor. Having no constructor explicitely defined in a class is equivalent to having
public Foo() {
super();
}
The constructor of the base class is thus called before any field of the subclass has been initialized. And your base class does something which should be avoided: call an overridable method.
Since this method is overridden in the subclass, it's invoked on an object that is not fully constructed yet, and thus sees the subclass field as null.

Here's an example of polymorphism in pseudo-C#/Java:
class Animal
{
abstract string MakeNoise ();
}
class Cat : Animal {
string MakeNoise () {
return "Meow";
}
}
class Dog : Animal {
string MakeNoise () {
return "Bark";
}
}
Main () {
Animal animal = Zoo.GetAnimal ();
Console.WriteLine (animal.MakeNoise ());
}
The Main function doesn't know the type of the animal and depends on a particular implementation's behavior of the MakeNoise() method.
class A
{
A(int number)
{
System.out.println("A's" + " "+ number);
}
}
class B
{
A aObject = new A(1);
B(int number)
{
System.out.println("B's" + " "+ number);
}
A aObject2 = new A(2);
}
public class myFirstProject {
public static void main(String[] args) {
B bObj = new B(5);
}
}
out:
A's 1
A's 2
B's 5
My rules:
1. Don't initialize with the default values in declaration (null, false, 0, 0.0...).
2. Prefer initialization in declaration if you don't have a constructor parameter that changes the value of the field.
3. If the value of the field changes because of a constructor parameter put the initialization in the constructors.
4. Be consistent in your practice. (the most important rule)
public class Dice
{
private int topFace = 1;
private Random myRand = new Random();
public void Roll()
{
// ......
}
}
or
public class Dice
{
private int topFace;
private Random myRand;
public Dice()
{
topFace = 1;
myRand = new Random();
}
public void Roll()
{
// .....
}
}

Related

Constructor, subclass method called from base and instance member order initialization problem [duplicate]

This question already has answers here:
Initialize field before super constructor runs?
(7 answers)
Closed 4 years ago.
So, I'm trying to design a small base abstract class:
public abstract class BaseClass
{
abstract void reload();
protected BaseClass()
{
reload();
// schedule reload for every X minutes
}
}
Now, subclass:
class SubClass extends BaseClass
{
private int member = 5;
#Override
void reload()
{
member = 20;
}
}
Now, the problem I'm facing is that reload() method is called before the member is initialized. Thus, member is assigned 20 and afterwards, assigned with the value 5. (this is only an example of course, the actual code is different, but the same idea).
What is the best design for what I'm trying to achieve?
I want the order of the initialization to be - member assigned 5, and if reload() fails for some reason i want it to stay with the initial value. However in this code, 5 overrides the value of reload(). If I don't assign an initial value for the instance member, it works of course.
Is it possible what I'm asking?
Override the constructor and call reload() there but do not call super(), this might not be acceptable for other reasons :)
class SubClass {
private int member = 5;
public SubClass() {
reload();
}
...
}
You can use a builder to achieve that.
This way you can achieve full control.
public abstract class Foo {
public abstract void postConstruct();
public static void main(String[] args) {
Bar bar = Foo.build(Bar.class);
System.out.println(bar);
}
public static <T extends Foo> T build(Class<T> clazz) {
T obj;
try {
obj = clazz.newInstance();
obj.postConstruct();
return obj;
} catch (Exception e) {
throw new IllegalArgumentException(
"Class "+clazz.getName()+" is not a valid class",e);
}
}
}
public class Bar extends Foo {
int value = 10;
protected Bar() {
super();
}
public void postConstruct() {
value = 7;
}
#Override
public String toString() {
return "Bar [value=" + value + "]";
}
}

overriding protected method of Superclass

In the below example why does the String b prints null and String c prints "gg".
Correct me if I am wrong, whenever a subclass (BClass) overrides a protected method (i.e initClass()) of the superclass (AClass).If you instantiate the subclass. The superclass must make use of overriden method specified by the subclass.
public class Example {
public class AClass {
private String a;
public AClass() {
initClass();
}
protected void initClass() {
a = "randomtext";
}
}
public class BClass extends AClass {
private String b = null;
private String c;
#Override
protected void initClass() {
b = "omg!";
c = "gg";
}
public void bValue() {
System.out.println(b); // prints null
System.out.println(c); // prints "gg"
}
}
public static void main(String[] args) {
Example.BClass b = new Example().new BClass();
b.bValue();
}
}
As of the JSF 12.5
In the example you can see the execution order. The first steps are the callings of the Constructor down to the Object constructor.
Afterwards this happens:
Next, all initializers for the instance variables of class [...] are executed.
Since your instance variable b is initialized to null it will be null again afterwards
This is happening because the superclass constructor is called before the fields of ClassB is initialized. Hence the initClass() method is called which sets b = "omg!" but then again when the super class constructor returns, b is initialized to the value declared in ClassB which is null.
To debug, put a break point and go step by step, you will find that b is first set to null and then changes to omg! and then comes back to null.
There have been already given several correct answers about what's happening. I just wanted to add that it is generally bad practice to call overridden methods from constructor (except of course if you know exactly what you are doing). As you can see, the subclass may not be completely initialised at the time its instance method is invoked (subclass constructor logic has not been executed yet, so effectively overridden method is invoked on an unconstructed object which is dangerous) which might lead to confusions like the one described in this question.
It is much better to write initialisation logic in the constructor and if it is too long then divide it between several private methods invoked from the constructor.
This is happening like this because, first constructor of AClass, which set value of b = omg! and c=gg. After that When BClass gets load in memory it set b=null and c remain as it is which is gg, this is happening because, because in BClass, for b you are doing declaration as well as initialization and for c you are doing only declaration, so as c is already in the memory it even won't get it's default value and as you are not doing any initialization for c, it remain with it's earlier state.
I believe that this example explains the issue:
public class Main {
private static class PrintOnCreate {
public PrintOnCreate(String message) {
System.out.println(message);
}
}
private static class BaseClass {
private PrintOnCreate member =
new PrintOnCreate("BaseClass: member initialization");
static {
System.out.println("BaseClass: static initialization");
}
public BaseClass() {
System.out.println("BaseClass: constructor");
memberCalledFromConstructor();
}
public void memberCalledFromConstructor() {
System.out.println("BaseClass: member called from constructor");
}
}
private static class DerivedClass extends BaseClass {
private PrintOnCreate member =
new PrintOnCreate("DerivedClass: member initialization");
static {
System.out.println("DerivedClass: static initialization");
}
public DerivedClass() {
System.out.println("DerivedClass: constructor");
}
#Override
public void memberCalledFromConstructor() {
System.out.println("DerivedClass: member called from constructor");
}
}
public static void main (String[] args) {
BaseClass obj = new DerivedClass();
}
}
The output from this program is:
BaseClass: static initialization
DerivedClass: static initialization
BaseClass: member initialization
BaseClass: constructor
DerivedClass: member called from constructor
DerivedClass: member initialization
DerivedClass: constructor
... which demonstrates that the derived class's members are initialized after the base class's constructor (and the invocation of the derived class's member function have completed). This also demonstrates a key danger of invoking an overridable function from a constructor, namely that the function can be invoked before the members of the class on which it depends have been initialized. For this reason, constructors should generally avoid invoking member functions (and, when they do, those functions should either be final or static, so that they either depend only on the current class which has been initialized or on none of the instance variables).

What is object field initialization and constructor order in Java

I ended up the following scenario in code earlier today (which I admit is kinda weird and I have since refactored). When I ran my unit test I found that a field initialization was not set by the time that the superclass constructor has run. I realized that I do not fully understand the order of constructor / field initialization, so I am posting in the hopes that someone explain to me the order in which these occur.
class Foo extends FooBase {
String foo = "foobar";
#Override
public void setup() {
if (foo == null) {
throw new RuntimeException("foo is null");
}
super.setup();
}
}
class FooBase {
public FooBase() {
setup();
}
public void setup() {
}
}
#Test
public void testFoo() {
new Foo();
}
The abbreviated backtrace from JUnit is as follows, I guess I expected $Foo.<init> to set foo.
$Foo.setup
$FooBase.<init>
$Foo.<init>
.testFoo
Yes, in Java (unlike C#, for example) field initializers are called after the superclass constructor. Which means that any overridden method calls from the constructor will be called before the field initializers are executed.
The ordering is:
Initialize superclass (recursively invoke these steps)
Execute field initializers
Execute constructor body (after any constructor chaining, which has already taken place in step 1)
Basically, it's a bad idea to call non-final methods in constructors. If you're going to do so, document it very clearly so that anyone overriding the method knows that the method will be called before the field initializers (or constructor body) are executed.
See JLS section 12.5 for more details.
A constructor's first operation is always the invocation of the superclass constructor. Having no constructor explicitely defined in a class is equivalent to having
public Foo() {
super();
}
The constructor of the base class is thus called before any field of the subclass has been initialized. And your base class does something which should be avoided: call an overridable method.
Since this method is overridden in the subclass, it's invoked on an object that is not fully constructed yet, and thus sees the subclass field as null.
Here's an example of polymorphism in pseudo-C#/Java:
class Animal
{
abstract string MakeNoise ();
}
class Cat : Animal {
string MakeNoise () {
return "Meow";
}
}
class Dog : Animal {
string MakeNoise () {
return "Bark";
}
}
Main () {
Animal animal = Zoo.GetAnimal ();
Console.WriteLine (animal.MakeNoise ());
}
The Main function doesn't know the type of the animal and depends on a particular implementation's behavior of the MakeNoise() method.
class A
{
A(int number)
{
System.out.println("A's" + " "+ number);
}
}
class B
{
A aObject = new A(1);
B(int number)
{
System.out.println("B's" + " "+ number);
}
A aObject2 = new A(2);
}
public class myFirstProject {
public static void main(String[] args) {
B bObj = new B(5);
}
}
out:
A's 1
A's 2
B's 5
My rules:
1. Don't initialize with the default values in declaration (null, false, 0, 0.0...).
2. Prefer initialization in declaration if you don't have a constructor parameter that changes the value of the field.
3. If the value of the field changes because of a constructor parameter put the initialization in the constructors.
4. Be consistent in your practice. (the most important rule)
public class Dice
{
private int topFace = 1;
private Random myRand = new Random();
public void Roll()
{
// ......
}
}
or
public class Dice
{
private int topFace;
private Random myRand;
public Dice()
{
topFace = 1;
myRand = new Random();
}
public void Roll()
{
// .....
}
}

super() in Java

Is super() used to call the parent constructor?
Please explain super().
super() calls the parent constructor with no arguments.
It can be used also with arguments. I.e. super(argument1) and it will call the constructor that accepts 1 parameter of the type of argument1 (if exists).
Also it can be used to call methods from the parent. I.e. super.aMethod()
More info and tutorial here
Some facts:
super() is used to call the immediate parent.
super() can be used with instance members, i.e., instance variables and instance methods.
super() can be used within a constructor to call the constructor of the parent class.
OK, now let’s practically implement these points of super().
Check out the difference between program 1 and 2. Here, program 2 proofs our first statement of super() in Java.
Program 1
class Base
{
int a = 100;
}
class Sup1 extends Base
{
int a = 200;
void Show()
{
System.out.println(a);
System.out.println(a);
}
public static void main(String[] args)
{
new Sup1().Show();
}
}
Output:
200
200
Now check out program 2 and try to figure out the main difference.
Program 2
class Base
{
int a = 100;
}
class Sup2 extends Base
{
int a = 200;
void Show()
{
System.out.println(super.a);
System.out.println(a);
}
public static void main(String[] args)
{
new Sup2().Show();
}
}
Output:
100
200
In program 1, the output was only of the derived class. It couldn't print the variable of neither the base class nor the parent class. But in program 2, we used super() with variable a while printing its output, and instead of printing the value of variable a of the derived class, it printed the value of variable a of the base class. So it proves that super() is used to call the immediate parent.
OK, now check out the difference between program 3 and program 4.
Program 3
class Base
{
int a = 100;
void Show()
{
System.out.println(a);
}
}
class Sup3 extends Base
{
int a = 200;
void Show()
{
System.out.println(a);
}
public static void Main(String[] args)
{
new Sup3().Show();
}
}
Output:
200
Here the output is 200. When we called Show(), the Show() function of the derived class was called. But what should we do if we want to call the Show() function of the parent class? Check out program 4 for the solution.
Program 4
class Base
{
int a = 100;
void Show()
{
System.out.println(a);
}
}
class Sup4 extends Base
{
int a = 200;
void Show()
{
super.Show();
System.out.println(a);
}
public static void Main(String[] args)
{
new Sup4().Show();
}
}
Output:
100
200
Here we are getting two outputs, 100 and 200. When the Show() function of the derived class is invoked, it first calls the Show() function of the parent class, because inside the Show() function of the derived class, we called the Show() function of the parent class by putting the super keyword before the function name.
Source article: Java: Calling super()
Yes. super(...) will invoke the constructor of the super-class.
Illustration:
Stand alone example:
class Animal {
public Animal(String arg) {
System.out.println("Constructing an animal: " + arg);
}
}
class Dog extends Animal {
public Dog() {
super("From Dog constructor");
System.out.println("Constructing a dog.");
}
}
public class Test {
public static void main(String[] a) {
new Dog();
}
}
Prints:
Constructing an animal: From Dog constructor
Constructing a dog.
Is super() is used to call the parent constructor?
Yes.
Pls explain about Super().
super() is a special use of the super keyword where you call a parameterless parent constructor. In general, the super keyword can be used to call overridden methods, access hidden fields or invoke a superclass's constructor.
Here's the official tutorial
Calling the no-arguments super constructor is just a waste of screen space and programmer time. The compiler generates exactly the same code, whether you write it or not.
class Explicit() {
Explicit() {
super();
}
}
class Implicit {
Implicit() {
}
}
Yes, super() (lowercase) calls a constructor of the parent class. You can include arguments: super(foo, bar)
There is also a super keyword, that you can use in methods to invoke a method of the superclass
A quick google for "Java super" results in this
That is correct. Super is used to call the parent constructor. So suppose you have a code block like so
class A{
int n;
public A(int x){
n = x;
}
}
class B extends A{
int m;
public B(int x, int y){
super(x);
m = y;
}
}
Then you can assign a value to the member variable n.
I have seen all the answers. But everyone forgot to mention one very important point:
super() should be called or used in the first line of the constructor.
Just super(); alone will call the default constructor, if it exists of a class's superclass. But you must explicitly write the default constructor yourself. If you don't a Java will generate one for you with no implementations, save super(); , referring to the universal Superclass Object, and you can't call it in a subclass.
public class Alien{
public Alien(){ //Default constructor is written out by user
/** Implementation not shown…**/
}
}
public class WeirdAlien extends Alien{
public WeirdAlien(){
super(); //calls the default constructor in Alien.
}
}
For example, in selenium automation, you have a PageObject which can use its parent's constructor like this:
public class DeveloperSteps extends ScenarioSteps {
public DeveloperSteps(Pages pages) {
super(pages);
}........
I would like to share with codes whatever I understood.
The super keyword in java is a reference variable that is used to refer parent class objects. It is majorly used in the following contexts:-
1. Use of super with variables:
class Vehicle
{
int maxSpeed = 120;
}
/* sub class Car extending vehicle */
class Car extends Vehicle
{
int maxSpeed = 180;
void display()
{
/* print maxSpeed of base class (vehicle) */
System.out.println("Maximum Speed: " + super.maxSpeed);
}
}
/* Driver program to test */
class Test
{
public static void main(String[] args)
{
Car small = new Car();
small.display();
}
}
Output:-
Maximum Speed: 120
Use of super with methods:
/* Base class Person */
class Person
{
void message()
{
System.out.println("This is person class");
}
}
/* Subclass Student */
class Student extends Person
{
void message()
{
System.out.println("This is student class");
}
// Note that display() is only in Student class
void display()
{
// will invoke or call current class message() method
message();
// will invoke or call parent class message() method
super.message();
}
}
/* Driver program to test */
class Test
{
public static void main(String args[])
{
Student s = new Student();
// calling display() of Student
s.display();
}
}
Output:-
This is student class
This is person class
3. Use of super with constructors:
class Person
{
Person()
{
System.out.println("Person class Constructor");
}
}
/* subclass Student extending the Person class */
class Student extends Person
{
Student()
{
// invoke or call parent class constructor
super();
System.out.println("Student class Constructor");
}
}
/* Driver program to test*/
class Test
{
public static void main(String[] args)
{
Student s = new Student();
}
}
Output:-
Person class Constructor
Student class Constructor
What can we use SUPER for?
Accessing Superclass Members
If your method overrides some of its superclass's methods, you can invoke the overridden method through the use of the keyword super like super.methodName();
Invoking Superclass Constructors
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.
Look at the code below:
class Creature {
public Creature() {
system.out.println("Creature non argument constructor.");
}
}
class Animal extends Creature {
public Animal (String name) {
System.out.println("Animal one argument constructor");
}
public Animal (Stirng name,int age) {
this(name);
system.out.println("Animal two arguments constructor");
}
}
class Wolf extends Animal {
public Wolf() {
super("tigerwang",33);
system.out.println("Wolf non argument constructor");
}
public static void main(string[] args) {
new Wolf();
}
}
When creating an object,the JVM always first execute the constructor in the class
of the top layer in the inheritance tree.And then all the way down the inheritance tree.The
reason why this is possible to happen is that the Java compiler automatically inserts a call
to the no-argument constructor of the superclass.If there's no non-argument constructor
in the superclass and the subclass doesn't explicitly say which of the constructor is to
be executed in the superclass,you'll get a compile-time error.
In the above code,if we want to create a Wolf object successfully,the constructor of the
class has to be executed.And during that process,the two-argu-constructor in the Animal
class is invoked.Simultaneously,it explicitly invokes the one-argu-constructor in the same
class and the one-argu-constructor implicitly invokes the non-argu-constructor in the Creature
class and the non-argu-constructor again implicitly invokes the empty constructor in the Object
class.
Constructors
In a constructor, you can use it without a dot to call another constructor. super calls a constructor in the superclass; this calls a constructor in this class :
public MyClass(int a) {
this(a, 5); // Here, I call another one of this class's constructors.
}
public MyClass(int a, int b) {
super(a, b); // Then, I call one of the superclass's constructors.
}
super is useful if the superclass needs to initialize itself. this is useful to allow you to write all the hard initialization code only once in one of the constructors and to call it from all the other, much easier-to-write constructors.
Methods
In any method, you can use it with a dot to call another method. super.method() calls a method in the superclass; this.method() calls a method in this class :
public String toString() {
int hp = this.hitpoints(); // Calls the hitpoints method in this class
// for this object.
String name = super.name(); // Calls the name method in the superclass
// for this object.
return "[" + name + ": " + hp + " HP]";
}
super is useful in a certain scenario: if your class has the same method as your superclass, Java will assume you want the one in your class; super allows you to ask for the superclass's method instead. this is useful only as a way to make your code more readable.
The super keyword can be used to call the superclass constructor and to refer to a member of the superclass
When you call super() with the right arguments, we actually call the constructor Box, which initializes variables width, height and depth, referred to it by using the values of the corresponding parameters. You only remains to initialize its value added weight. If necessary, you can do now class variables Box as private. Put down in the fields of the Box class private modifier and make sure that you can access them without any problems.
At the superclass can be several overloaded versions constructors, so you can call the method super() with different parameters. The program will perform the constructor that matches the specified arguments.
public class Box {
int width;
int height;
int depth;
Box(int w, int h, int d) {
width = w;
height = h;
depth = d;
}
public static void main(String[] args){
HeavyBox heavy = new HeavyBox(12, 32, 23, 13);
}
}
class HeavyBox extends Box {
int weight;
HeavyBox(int w, int h, int d, int m) {
//call the superclass constructor
super(w, h, d);
weight = m;
}
}
super is a keyword. It is used inside a sub-class method definition to call a method defined in the superclass. Private methods of the superclass cannot be called. Only public and protected methods can be called by the super keyword. It is also used by class constructors to invoke constructors of its parent class.
Check here for further explanation.
As stated, inside the default constructor there is an implicit super() called on the first line of the constructor.
This super() automatically calls a chain of constructors starting at the top of the class hierarchy and moves down the hierarchy .
If there were more than two classes in the class hierarchy of the program, the top class default constructor would get called first.
Here is an example of this:
class A {
A() {
System.out.println("Constructor A");
}
}
class B extends A{
public B() {
System.out.println("Constructor B");
}
}
class C extends B{
public C() {
System.out.println("Constructor C");
}
public static void main(String[] args) {
C c1 = new C();
}
}
The above would output:
Constructor A
Constructor B
Constructor C
The super keyword in Java is a reference variable that is used to refer to the immediate parent class object.
Usage of Java super Keyword
super can be used to refer to the immediate parent class instance variable.
super can be used to invoke the immediate parent class method.
super() can be used to invoke immediate parent class constructor.
There are a couple of other uses.
Referencing a default method of an inherited interface:
import java.util.Collection;
import java.util.stream.Stream;
public interface SkipFirstCollection<E> extends Collection<E> {
#Override
default Stream<E> stream() {
return Collection.super.stream().skip(1);
}
}
There is also a rarely used case where a qualified super is used to provide an outer instance to the superclass constructor when instantiating a static subclass:
public class OuterInstance {
public static class ClassA {
final String name;
public ClassA(String name) {
this.name = name;
}
public class ClassB {
public String getAName() {
return ClassA.this.name;
}
}
}
public static class ClassC extends ClassA.ClassB {
public ClassC(ClassA a) {
a.super();
}
}
public static void main(String[] args) {
final ClassA a = new ClassA("jeff");
final ClassC c = new ClassC(a);
System.out.println(c.getAName());
}
}
Then:
$ javac OuterInstance.java && java OuterInstance
jeff

Java: Superclass to construct a subclass on certain conditions, possible?

I have this condition
public class A {
public action() {
System.out.println("Action done in A");
}
}
public class B extends A {
public action() {
System.out.println("Action done in B");
}
}
when I create an instance of B, the action will do just actions in B, as it overrides the action of the superclass.
the problem is that in my project, the super class A is already used too many times, and I am looking for a way that under certain conditions, when i create an instance of A it makes a check and if it is true, replace itself with B.
public class A {
public A() {
if ([condition]) {
this = new B();
}
}
public action() {
System.out.println("Action done in A");
}
}
A a = new A();
a.action();
// expect to see "Action done in B"...
is this possible in some way?
I would say that doing this:
this = new B();
within the constructor for A would violate OO design principles, even it were possible to do (and it isn't).
That being said, if I were faced with this scenario:
the problem is that in my project, the super class A is already used too many times
I would solve it in one of the two following ways:
I have assumed that your condition is that you do not want too many objects of type A, otherwise feel free to substitute in any other condition.
Option 1 : Use a factory design pattern.
public class AFactory
{
private static count = 0;
private static final MAX_COUNT = 100;
public A newObject() {
if (count < MAX_COUNT) {
count++;
return new A();
} else {
return new B();
}
}
}
And then somehwere else you generate the objects like so:
A obj1 = factory.newObject();
A obj2 = factory.newObject();
Option 2 : Static counter + try&catch
Use a static counter within your A class that keeps track of the number of times A has been instantiated, by incrementing the static variable by one in the constructor. If it hits a limit for the max number of object of type A, throw an InstantiationError in A's constructor.
This would mean that whenever you instantiate A, you have to a try..catch block to intercept the InstantionError, and then create a new object of type B instead.
public class A {
private static count = 0;
private static final MAX_COUNT = 100;
public A() {
if (count > 100) {
throw new InstationError();
}
}
}
And when generating your objects:
A obj1, obj2;
try {
obj1 = new A();
} catch (InstantiationError ie) {
obj1 = new B();
}
try {
obj2 = new A();
} catch (InstantiationError ie) {
obj2 = new B();
}
Option 2 is closest to what you ask directly in the question. However, I would personally choose to use the factory design pattern, because it is much more elegant solution, and it allows you to achieve what you want to do anyway.
Not directly, no. Calling new A() will always create an instance of A. However, you could make the constructor of A protected, and then have a static method:
public static A newInstance() {
// Either create A or B here.
}
Then convert all current calls to the constructor to calls to the factory method.
It is possible to choose whether or not to use a superclass' constructor?
It is not possible to conditionally control whether or not to use a superclass' constructor, as one of the superclass' constructors must be called before constructing one's own object.
From the above, there is a requirement in Java, that the first line of the constructor must call on of the superclass' constructor -- in fact, even if there is no explicit call to a superclass' constructor, there will be an implicit call to super():
public class X {
public X() {
// ...
}
public X(int i) {
// ...
}
}
public class Y extends X {
public Y() {
// Even if not written, there is actually a call to super() here.
// ...
}
}
It should be stressed that it is not possible to call the superclass' constructor after performing something else:
public class Y extends X {
public Y() {
doSomething(); // Not allowed! A compiler error will occur.
super(); // This *must* be the first line in this constructor.
}
}
The alternative
That said, a way to achieve what is desired here could be to use the factory method pattern, which can select the kind of implementation depending on some kind of condition:
public A getInstance() {
if (condition) {
return new B();
} else {
return new C();
}
}
In the above code, depending on condition, the method can return either an instance of B or C (assuming both are a subclass of class A).
Example
The following is a concrete example, using an interface rather than a class.
Let there be the following interfaces and classes:
interface ActionPerformable {
public void action();
}
class ActionPerformerA implements ActionPerformable {
public void action() {
// do something...
}
}
class ActionPerformerB implements ActionPerformable {
public void action() {
// do something else...
}
}
Then, there would be a class which will return one of the above classes depending on a condition which is passed in through a method:
class ActionPeformerFactory {
// Returns a class which implements the ActionPerformable interface.
public ActionPeformable getInstance(boolean condition) {
if (condition) {
return new ActionPerformerA();
} else {
return new ActionPerformerB();
}
}
}
Then, a class which uses the above factory method which returns the appropriate implementation depending on a condition:
class Main {
public static void main(String[] args) {
// Factory implementation will return ActionPerformerA
ActionPerformable ap = ActionPerformerFactory.getInstance(true);
// Invokes the action() method of ActionPerformable obtained from Factory.
ap.action();
}
}
This would be possible if you used a factory method. When you use a constructor: nope, completely impossible.
Assuming you aren't willing to move it to an interface or factory its kind of ugly but you could keep a delegeate copy of B in A and rewrite your methods ot invoke the delegate:
public class A{
B delegate;
public A(){
if([condition]){
delegate = new B()
return;
}
...//normal init
}
public void foo(){
if(delegate != null){
delegate.foo();
return;
}
...//normal A.foo()
}
public boolean bar(Object wuzzle){
if(delegate != null){
return delegate.bar(wuzzle);
}
...//normal A.bar()
}
...//other methods in A
}

Categories

Resources