Why does this java code produce StackOverflowError? I understand that this somehow connected with recursive generic type parameter. But I don't understand clear the whole mechanism.
public class SomeClass<T extends SomeClass> {
SomeClass() {
new SomeClassKiller();
}
private class SomeClassKiller extends SomeClass<T> {
}
public static void main(String[] args) {
new SomeClass();
}
}
The generic part doesn't matter - nor does it really matter that the class is nested. Look at this mostly-equivalent pair of classes and it should be more obvious:
public class SuperClass
{
public SuperClass()
{
new SubClass();
}
}
public class SubClass extends SuperClass
{
public SubClass()
{
super();
}
}
So the subclass constructor calls the superclass constructor - which then creates a new subclass, which calls into the superclass constructor, which creates a new subclass, etc... bang!
Here it is invoking one constructor from another and from it the previous one, cyclic constructor chain, see the comments below
public class SomeClass<T extends SomeClass> {
SomeClass() {//A
new SomeClassKiller();// calls B
}
private class SomeClassKiller extends SomeClass<T> {//B
//calls A
}
public static void main(String[] args) {
new SomeClass(); //calls A
}
}
This is because of the Recursive constructor calls happening between the classes SomeClass and
SomeClassKiller.
public class SomeClass<T extends SomeClass> {
SomeClass() {
new SomeClassKiller();
}
private class SomeClassKiller extends SomeClass<T> {
public SomeClassKiller()
{
super(); //calls the constructor of SomeClass
}
}
public static void main(String[] args) {
new SomeClass();
}
}
The code produced by the compiler is something like this, so when u create an object it recursivly calls the SomeClass and SomeClassKiller for ever.
Constructors are invoked top-to-bottom, that is if a class A derives from B, A's constructors will first invoke the parent constructor (B).
In you case, new SomeClassKiller() recursively calls the constructor of SomeClass which in turn constructs another SomeClassKiller … there it is.
The main() method is creating a new instance of SomeClass which calls the SomeClass constructor that creates a new instance of SomeClassKiller that by default calls the parent constructor and the stackoverflow occurs.
To avoid the stackoverflow. Change the code to look as follows:
public class SomeClass<T extends SomeClass> {
SomeClass() {
new SomeClassKiller();
}
private class SomeClassKiller extends SomeClass<T> {
public SomeClassKiller(){
//super(); does this by default, but is now commented out and won't be called.
}
}
public static void main(String[] args) {
new SomeClass();
}
}
Related
class Yfk {
public static void main(String[] args) {
System.out.println(new YfkC().x);
}
}
abstract class YfkA {
int x = 3;
YfkA() { x++; }
}
class YfkB extends YfkA {}
class YfkC extends YfkB {}
The final result is 4. I am not clear about the extend process. In the main function, we create an object YfkC and invoke Yfkc.x. My understanding is since there is no method and filed in class yfkc, so we find in yfkb, and then find in yfkc. At this time, will YfkC be upcasted to YfkA automatically? Equal System.out.println(new YfkA().x); so we will get x = 4; I am confused about the process from YfkC to YfkA.
new YfkC().x
This internally calls the constructor of the sub class. so the value of x is incremented and printed as 4.
YfkC() -> YfkB() -> YfkA() { x++;};
The default constructor of each class is calling the super();. This calls the default constructor of the super class before executing it's own.
If you want to know about the constructor chaining then put as system out and see the calling chain.
public class Yfk {
public static void main(String[] args) {
System.out.println(new YfkC().x);
}
}
abstract class YfkA {
int x = 3;
YfkA() {
System.out.println("YfkA");
x++; }
}
class YfkB extends YfkA {
public YfkB() {
System.out.println("YfkB");
}
}
class YfkC extends YfkB {
public YfkC() {
System.out.println("YfkC");
}
}
output:
YfkA
YfkB
YfkC
4
When you invoke any Child constructor. There is a chain call to the immediate parent class constructor from the current class. And the call continues until the Object class constructor invokes since that the possible most Parent classes super class is.
Here is an example how constructor behaves in inheritance
public class ParentClass {
public ParentClass() {
System.out.println("Parent default constructor invoked");
}
public ParentClass(int a) {
System.out.println("Parent argumented constructor invoked");
}
public static void main(String[] args) {
SubSubClass sub = new SubSubClass();
}
}
class SubClass extends ParentClass {
public SubClass() {// not calling any super
System.out.println("Child default constructor invoked");
}
public SubClass(int b) {
super(b);
System.out.println("Child default constructor invoked");
}
}
class SubSubClass extends SubClass {
public SubSubClass() {// not calling any super
System.out.println("Sub Child default constructor invoked");
}
public SubSubClass(int b) {
super(b);
System.out.println("Sub Child default constructor invoked");
}
}
OUTPUT:
Parent default constructor invoked
Child default constructor invoked
Sub Child default constructor invoked
I wrote an article covering this topic, hope that clears your doubt.
Constructor inheritance(ovveriding) and reasons behind restricting constructor inheritance in Java
Whenever a child class is instantiated, its parent constructors are invoked in sequence, up the chain.
In your hierarchy, you have:
YfkC
YfkB
abstract YfkA
Object
...and in each of their constructors, there is an implicit call to super().
So, new YfkC invokes YfkB's constructor, which invokes the abstract class's YfkAs constructor, which results in the incrementation of x.
If you were to execute new YfkC().x again, you'd get 5, since every time you new up any of YfkA's children, you would be invoking that constructor.
I have generic class :
public class Test<T> {
private Test<? extends T> myInstance;
public Test<? extends T> getInstance () {
return myInstance;
}
public void setInstance (Test<? extends T> argType) {
this.myInstance = argType;
}
}
And I have two classes in my class hierarchy relations:
public abstract class Alphabet {
//code here
}
and
public class A extends Alphabet{
public A() {
super();
System.out.print("This is A call");
}
}
Finally I have a class where I want to store make generic class Test with particular type and set new Instance of Object -> A through setInstance() method:
public static void main(String[] args) {
List<Alphabet> list = new ArrayList<Alphabet>();
Test<Alphabet> tAlphabet = new Test<Alphabet>();
tAlphabet.setInstance(new A()); //Here is compilation ERROR
}
But I have got the compilation error in line tAlphabet.setInstance(new A());
What is the issue with my generic class?
Your instance is a Test object as it's currently written, and you are supplying it with an Alphabet object instead. You probably want your instance to be of type Alphabet:
public class Test<T> {
private T myInstance;
public T getInstance() {
return myInstance;
}
public void setInstance(T argType) {
myInstance = argType;
}
}
This way, your Test stores an Alphabet instead of another Test.
It seems you have made things more complicated than needed. You probably want this in your Test class instead of what you actually have:
private T myInstance;
public T getInstance () {
return myInstance;
}
public void setInstance (T argType) {
this.myInstance = argType;
}
With this arrangement you would be free to setInstance(new A()) on a Test<Alphabet> instance.
I have an object with two different constructors:
public class MyClass {
public MyClass(arg1, arg2) {
//constructor
}
public MyClass() {};
}
I need to invoke the second one only by a specific class of my software (the first one could be invoked anywhere). Is there a design pattern specific for this case?
MyClass and the invoking class are in two different packages, so a package-private constructor is not a solution.
Without design pattern it can be done in one way. Set one constructor public, which will be invoked from all class. And the other declare it package private. Now place this class and the specific on in the same package.
public class MyClass {
public MyClass(arg1, arg2) {
//constructor
}
MyClass() {}; // only for the class in the same package
}
So now the public constructor can be used from all while the package protected constructor can be invoked only by the class in the same package.
Another Option
You can use a different implementaion of factory pattern
public class MyClass {
public MyClass(arg1, arg2) {
//constructor
}
public MyClass() {};
}
And the factory
public class MyClassFactory{
public static MyClass createMyClass(Object o){
if (o instanceOf SpecificClass)
return new MyClass();
else
return new MyClass(arg1,arg2);
}
}
Now call like
MyClass mC = MyclassFactory.createMyClass(this);
N.B.. I just ommitted the arguments. You can pass the arguments in createMyClass method.
You can do something like this.
public class Test {
public Test() {
StackTraceElement[] stack = new Throwable().getStackTrace();
StackTraceElement topOfStack = stack[0];
if (!topOfStack.getClassName().equals("mypackage.MyClass"))
throw new SecurityException("Haha! You are not allowed to call me!");
// ....
}
public static void main(String[] args) {
new Test(); // Haha! You are not allowed to call me!
}
}
I wanted to implement a method in a abstract class that is called by the inherited classes and uses their values.
For instance:
abstract class MyClass{
String value = "myClass";
void foo(){System.out.println(this.value);}
}
public class childClass{
String value="childClass";
void foo(){super.foo();}
}
public static void main(String[] args){
new childClass.foo();
}
This will output "myClass" but what I really want is to output "childClass". This is so I can implement a "general" method in a class that when extended by other classes it will use the values from those classes.
I could pass the values as function arguments but I wanted to know if it would be possible to implement the "architecture" I've described.
A super method called by the inherited class which uses the values from the caller not itself, this without passing the values by arguments.
You could do something like this:
abstract class MyClass {
protected String myValue() {
return "MyClass";
}
final void foo() {
System.out.println(myValue());
}
}
public class ChildClass extends MyClass {
#Override
protected String myValue() {
return "ChildClass";
}
}
and so on
This is a place where composition is better than inheritance
public class Doer{
private Doee doee;
public Doer(Doee doee){
this.doee = doee;
}
public void foo(){
System.out.println(doee.value);
}
}
public abstract class Doee{
public String value="myClass"
}
public ChildDoee extends Doee{
public String= "childClass"
}
...
//Excerpt from factory
new Doer(new ChildDoee);
I believe you are asking whether this is possible:
public class MyClass {
void foo() {
if (this instanceof childClass) // do stuff for childClass
else if (this intanceof anotherChildClass) // do stuff for that one
}
}
So the answer is "yes, it's doable", but very much advised against as it a) tries to reimplement polymorphism instead of using it and b) violates the separation between abstract and concrete classes.
You simply want value in MyClass to be different for an instance of childClass.
To do this, change the value in the childClass constructor:
public class childClass {
public childClass() {
value = "childClass";
}
}
Edited:
If you can't override/replace the constructor(s), add an instance block (which gets executed after the constructor, even an undeclared "default" constructor):
public class childClass {
{
value = "childClass";
}
}
Is it possible to call a super static method from child static method?
I mean, in a generic way, so far now I have the following:
public class BaseController extends Controller {
static void init() {
//init stuff
}
}
public class ChildController extends BaseController {
static void init() {
BaseController.loadState();
// more init stuff
}
}
and it works, but I'd like to do it in a generic way, something like calling super.loadState(), which doesn't seem to work...
In Java, static methods cannot be overidden. The reason is neatly explained here
So, it doesn't depend on the object that it is being referenced. But instead, it depends on the type of reference. Hence, static method is said to hide another static method and not override it.
For example (Cat is a subclass of Animal):
public class Animal {
public static void hide() {
System.out.format("The hide method in Animal.%n");
}
public void override() {
System.out.format("The override method in Animal.%n");
}
}
public class Cat extends Animal {
public static void hide() {
System.out.format("The hide method in Cat.%n");
}
public void override() {
System.out.format("The override method in Cat.%n");
}
}
Main class:
public static void main(String[] args) {
Cat myCat = new Cat();
System.out.println("Create a Cat instance ...");
myCat.hide();
Cat.hide();
myCat.override();
Animal myAnimal = myCat;
System.out.println("\nCast the Cat instance to Animal...");
Animal.hide();
myAnimal.override();
Animal myAnimal1 = new Animal();
System.out.println("\nCreate an Animal instance....");
Animal.hide();
myAnimal.override();
}
Now, the output would be as given below
Create a Cat instance ...
The hide method in Cat.
The hide method in Cat.
The override method in Cat.
Cast the Cat instance to Animal...
The hide method in Animal.
The override method in Cat.
Create an Animal instance....
The hide method in Animal.
The override method in Animal.
For class methods, the runtime system invokes the method defined in the compile-time type of the reference on which the method is called.
In other words, call to static methods are mapped at the compile time and depends on the declared type of the reference (Parent in this case) and not the instance the reference points at runtime. In the example, the compile-time type of myAnimal is Animal. Thus, the runtime system invokes the hide method defined in Animal.
There is static inheritance in Java. Adapting the example from Nikita:
class A {
static void test() {
System.out.print("A");
}
}
class B extends A {
}
class C extends B {
static void test() {
System.out.print("C");
B.test();
}
public static void main(String[] ignored) {
C.test();
}
}
This now compiles, and invoking C prints "CA", of course. Now we change class B to this:
class B extends A {
static void test() {
System.out.print("B");
}
}
and recompile only B (not C). Now invoking C again, it would print "CB".
There is no super like keyword for static methods, though - a (bad) justification may be that "The name of the super class is written in the declaration of this class, so you had to recompile your class nevertheless for changing it, so you could change the static calls here, too."
The whole inheritance concept isn't applied to static elements in Java. E.g., static method can't override another static method.
So, no, you'll have to call it by name or make them instance methods of some object. (You might want to check out one of factory patterns in particular).
A practical example
class A {
static void test() {
System.out.println("A");
}
}
class B extends A {
static void test() {
System.out.println("B");
}
}
A a = new B();
B b = new B();
a.test();
b.test();
This prints A and then B. I.e., invoked method depends on how variable is declared and nothing else.
You can actually call the static method of a superclass in a generic way, given that you know the method name and its parameters.
public class StaticTest {
public static void main(String[] args) {
NewClass.helloWorld();
}
}
public class NewClass extends BaseClass {
public static void helloWorld() {
try {
NewClass.class.getSuperclass().getMethod("helloWorld", new Class[] {}).invoke( NewClass.class ,new Object[]{} );
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("myVar = " + myVar);
}
}
public class BaseClass extends BaseBaseClass {
protected static String myVar;
public static void helloWorld() {
System.out.println("Hello from Base");
myVar = "Good";
}
}
This should work and in the subclass you have everything set in the base class available.
The output should be:
Hello from Base
myVar = Good
The official name of your implementation is called method hiding. I would suggest introducing a static init(Controller controller) method, and calling an instance method to take advantage of overriding.
public class Controller {
static void init(Controller controller) {
controller.init();
}
void init() {
//init stuff
}
}
public class BaseController extends Controller {
#override
void init() {
super.init();
//base controller init stuff
}
}
public class ChildController extends BaseController {
#override
void init() {
super.init();
//child controller init stuff
}
}
You can then call Controller.init(controllerInstance).
For static methods there is no instance of a class needed, so there is no super.