I'm reviewing for a certification exam and I experimented with the following codes:
class A {
B b = new B();
static {
System.out.println("A static.");
}
{
System.out.println("A instance.");
}
A() {
System.out.println("A constructor.");
}
}
class B extends A {
static {
System.out.println("B static.");
}
{
System.out.println("B instance.");
}
B() {
System.out.println("B constructor.");
}
}
public class Raaawrrr {
public static void main(String args[]) {
A a = new A();
}
}
It prints:
A static.
B static.
and causes a stack overflow afterwards. I'm having a hard time understanding why. Would you be able to help me out?
A instantiates B. B happens to also be of type A, so that gets instantiated again. Which instantiates B... and so forth.
You are creating an object of class B which is sub-class of A in class A. Note that the constructor of super-classes must be executed before the execution of sub-class constructor.
Related
I'm running over this problem while working with the following inheritance and JDK 14
interface A {
default void a() {
System.out.println("default a");
}
default void b() {
System.out.println("default b");
}
}
class AImp implements A {
#Override
public void a() {
System.out.println("a from AImp");
}
#Override
public void b() {
System.out.println("b from AImp");
this.a();
}
}
class B extends AImp {
#Override
public void a() {
System.out.println("a from B");
}
#Override
public void b() {
System.out.println("b from B");
super.b();
}
}
when I run
B b = new B();
b.b();
console gives
b from B
b from AImp
a from B
How come the keyword this in the AImp is referencing the instance of class B?
Am I being confused with something here?
Thank you for spending time.
You have created an instance of B, it is it's dynamic type and due to dynamic binding always the method declared in B is called, because it overrides from A.
It does not matter from where you call the method, but it matters, what is the dynamic type.
With super.method() it is different, it explicitly goes up in the inheritance.
Note: constructors are not overriden, ever. So calling this(params) will not delegate to subclass.
If an anonymous class is extending/implementing a class/interface, why can't I add a new method?
In other words, this works:
class A {
void a() {
System.out.println("a in A");
}
}
class B extends A {
#Override
void a() {
System.out.println("a in B");
}
void b() {
System.out.println("b in B");
}
}
Why doesn't this work:
class C {
A anonA() {
return new A() {
void b() {
System.out.println("b in C");
}
};
}
}
Given:
public static void main(String[] args) {
B b = new B();
b.b();
// C c = new C();
// A anonA = c.anonA();
// anonA.b();
// yields: java: cannot find symbol \ symbol: method b()
}
Method invocations, at compile time, are determined based on the type of the expression they are invoked on. In your example, you are attempting to invoke b() on an expression of type A. A does not declare a b() method and so it won't work.
It does not work on your concrete B class example either
A notAnonA = new B();
notAnonA.b(); // fails to compile
You can very well add a new method inside the body of the new anonymous class, but you'll only be able to use it within the class or on the actual new anonymous class instance creation expression.
new A() {
void undeclared() {}
}.undeclared();
public class Questions {
public static void main(String[] args) {
D d = new D();
}
}
class A {
A() {
System.out.println("A");
}
}
class B extends A {
B() {
System.out.println("B");
}
class C {
C() {
System.out.println("C");
}
}
}
class D extends B.C {
D() {//compilation error
System.out.println("D");
}
}
This shows an error while D is created that some intermediate constructor call. please tell me how do I extend such inner classes and what is wrong with this code.
Thank you.
You have to make the class C static so that it can be accessed from outside B.
class B extends A {
B () {
System.out.println("B");
}
static class C {
C () {
System.out.println("C");
}
}
}
Apart from a theoretical question, why would you do this?
All non-static inner classes need to have reference to instance of its outer class. If you want to extend such class you need to assure that object which will be used as base will have instance of its outer object. So you can do something like this:
class D extends B.C {
D(B b) {
b.super();
System.out.println("D");
}
}
and use
D d = new D(new B());
is there a diffrence between this :
public class A {
B b;
A() {
b=new B();
}
}
and this :
public class A {
B b=new B();
A() {
}
}
if there is, what is it? and what is better practice?
if there is no, whats recommanded?
As far as i know there is no difference as long as you only have one constructor. If you have more than one constructor you will need to make sure it's assigned in all constructors. For that reason i would recommend the second approach.
The constructor runs after the instance variables are initialized, so there is a difference. It doesn't matter in a small example, but it can matter with more complex code. (Note, the order of the code doesn't matter. If the initialization is in the constructor, it runs second.)
The second approach is more convenient, so I tend to start with it. The first approach can be more useful though (for Inversion of Control and Polymorphism), so it often gets used in "real" code.
class B {
B() {
System.out.println("B constructor");
}
}
public class A {
B b=new B();
A() {
System.out.println("A constructor");
}
public static void main(String[] args) {
new A();
}
}
Output:
B constructor
A constructor
....
class B {
B() {
System.out.println("B constructor");
}
}
public class A {
B b;
A() {
System.out.println("A constructor");
b=new B();
}
public static void main(String[] args) {
new A();
}
}
Output:
A constructor
B constructor
Big Difference between them.
In first option Class B only instantiate when constructor without parameter is called. If you put and call any parametrized constructor Class B will not instantiate.
But in case of second option Class B will always instantiate regardless of any constructor call.
Consider the following code classes.
public class A
{
public A()
{
callCreation();
}
protected void callCreation()
{
System.out.println("A Created!!");
}
}
public class B extends A
{
protected void callCreation()
{
System.out.println("B Created!!");
}
}
public class C extends B
{
protected void callCreation()
{
System.out.println("C Created!!");
}
public static void main(String[] args)
{
A a = new A();
A b = new B();
A c = new C();
}
}
The output of running the class C is given below.
A Created!!
B Created!!
C Created!!
The first output line in the output A Created!! is printed because when the constructor of class A is called, it calls the super class's constructor (java.lang.Object) implicitly before calling the callCreation() method in the class A's constructor. And this will be the case for B and C classes too. In that case when the constructor of B is called the call flow should be typically : B's constructor -> A's Constructor -> java.lang.Object's Constructor -> come back to A's callCreation() method to finish calling A's constructor. If so how is the overridden value printed and not the super class's value is printed? So the question is 'when is an object of a class created exactly? to put it in other words, the object of a class should be created only after the constructor finishes calling/initializing all the elements within itself. If so how can a method be called from a child class and not from the parent class?
The callCreation methods in B and C override the method from A. So when the method is called in the constructor A the implementations in B and C will be run, even though the constructors of B and C have not been executed yet. This is possible because constructors don't actually create the object, rather they are called to initialize some moments after the JVM has created it.
In general it's a very bad idea to call methods that can be overridden from a constructor for this very reason. A method in B or C may assume that the constructor and object initializers have already been run, and read an unexpected value from a field. For example the following ends up printing "B Created!! null" because the field still has not be assigned its value.
public class B extends A
{
final String msg = "Yes!";
protected void callCreation()
{
System.out.println("B Created!! "+msg);
}
}
thinking in this way makes it more obvious:
when an object of type B is being created super() keyword calls the A constructor,
then in A constructor "this.callCreation()" is executed, which refers to the current
object which is B, so callCreation corresponding to the current object(B) is called.
the same process is done for C.
public class A {
public A() {
this.callCreation();
}
protected void callCreation() {
System.out.println("A Created!!");
}
}
class B extends A {
public B() {
super();
}
protected void callCreation() {
System.out.println("B Created!!");
}
}
class C extends B {
public C() {
super();
}
protected void callCreation() {
System.out.println("C Created!!");
}
public static void main(String[] args) {
A a = new A();
A b = new B();
A c = new C();
}
}