This question already has answers here:
Calling method from constructor
(2 answers)
Closed 7 years ago.
There is a Class with inner classes. I expected that the output would be 6 9
but suddenly it gave me 0 9. I wonder why I got such unexpected results?
It seems like in A class the f1 variable somehow becomes zero.
Why does this happen?
public static void main(String[] args) {
new B(6);
}
public static class A {
private int f1 = 7;
public A(int f2) {
this.f1 = f2;
initialize();
}
protected void initialize() {
System.out.println(f1);
}
}
public static class B extends A {
protected int f1 = 3;
public B(int f1) {
super(f1);
this.f1 += f1;
initialize();
}
protected void initialize() {
System.out.println(f1);
}
}
Class field assignment comes after the call to super(). This is why you are getting the 0.
The call super(f1) occurs before the assignment protected int f1 = 3;. And the default value for int (primitive type) is 0.
And as you know the function initialize() is overridden in B which is where it is executed.
Edit: As for the discussion in the comments, I found some nice reference from Effective Java 2nd Edition, Item 17: Design and document for inheritance, or else prohibit it:
There are a few more restrictions that a class must obey to allow inheritance. Constructors must not invoke overridable methods, directly or indirectly. If you violate this rule, program failure will result. The superclass constructor runs before the subclass constructor, so the overriding method in the subclass will be invoked before the subclass constructor has run. If the overriding method depends on any initialization performed by the subclass constructor, the method will not behave as expected.
Related
class Super {
public Integer i = 1;
void Sample() {
System.out.println("method of super class");
}
}
public class Sub extends Super {
public Integer i = 1000;
void Sample() {
System.out.println("method of sub class");
}
public static void main(String args[]) {
Super obj;
obj = new Super();
obj.Sample();
System.out.println(obj.i);
obj = new Sub();
obj.Sample();
System.out.println(obj.i);
}
}
Output:
method of superclass
1
method of subclass
1
When the Sample() method is called we get consequently different outputs (method of super class/subclass)
But when the variable, i is printed, outputs are identical (1)
Are problems the reference/object types or inheritance rules?
Variables in Java do not follow polymorphism and overriding is only applicable to methods, not variables. Thus, you see the overriding behaviour for the method, Sample() but not for the variable, i.
Note that in this case, the child class variable hides the parent class variable and the concept is known as variable hiding.
Note: Always follow the Java naming conventions e.g. you should rename the method, Sample() to sample().
I have the following exercise regarding inheritance and methods overriding, and the question is why the 'System.out.println(f1)' in the 'initialize()' method in the parent class is called with param '0', and what is needed to do to for it will be called with param '6'. Please help me understand it. Thanks in advance.
public class Solution {
public static void main(String[] args) {
new B(6);
}
public static class A {
private int f1 = 7;
public A(int f1) {
this.f1 = f1;
initialize();
}
protected void initialize() {
System.out.println(f1);
}
}
public static class B extends A {
protected int f1 = 3;
public B(int f1) {
super(f1);
this.f1 += f1;
initialize();
}
protected void initialize() {
System.out.println(f1);
}
}
}
Privare methods cannot be overriden. You can write the method in child but practically it is not overriding
From the Java language specification JLS.
Note that a private method cannot be hidden or overridden in the technical sense of those terms. This means that a subclass can declare a method with the same signature as a private method in one of its superclasses, and there is no requirement that the return type or throws clause of such a method bear any relationship to those of the private method in the superclass.
Your parent method is not getting called with parameter value as 0. if you can see parent's constructor is overriding the value this.f1=f1 the value of f1 will be 6. Therefore output will be 6 and 9.
This question already has answers here:
java constructor: this(.)
(3 answers)
Closed 6 years ago.
Why super have no effect on i field in class C ?
The output is 012, but why not 321, since class B extends class C ?
public class C {
protected int i;
public C(int i){
this(i,i);
System.out.print(this.i);
this.i=i;
}
public C(int i, int j) {
System.out.print(this.i);
this.i=i+j;
}
public C(){
this(1);
System.out.print(i);
}
public static void main(String[] args) {
C c=new C();
}
}
public class B extends C{
public B(){
super.i=3;
}
public static void main(String[] args){
C c=new B();
}
}
super.i just refers to this.i (or simply i) because class B does not declare its own version of i, so it inherits the field from C already.
public B(){
super.i=3; // the super here does not do anything
}
The first thing a constructor needs to do is invoke one of the super constructors. So this is equivalent to:
public B(){
super();
i=3;
}
As you can see, the code in the superclass C is executed before i is set to 3. That's why it prints the old value.
super can be used for accessing overridden methods. In your scenario i is an inherited member of B.
If you override a method in B that was defined in C, you can call it from B by using the super keyword.
It´s quite simple. That´s what is happening:
B Constructor is called.
B doesn´t have an explicit super constructor call- so implicity call super().
C() Constructor is called -> call C(int)
C(int) Constructor is called -> call C(int,int);
C(int, int) is called. print i. i only has the default value yet so print ->0
C(int, int) does increment i by j, which at this point is 1+1 = 2
C(int) Constructor callback, as C(int, int) is done, print i = 2
C(int) sets i = 1 and prints i = 1.
B() callback as C() is done. set instance variable i to 3.
As you can see you have a different output as 021 and that´s everyone that does happen.
I don´t know what your initial intention was, but super can have different meanings.
In the constructor you usually access a parents constructor with super.
by doing super.i you are only accessing the instance variable i of the parent class.
you could, by doing super.testMethod() call an method testMethod from the parentclass
This question already has answers here:
Multiple inheritance on Java interfaces
(5 answers)
Closed 7 years ago.
public class Test implements X, Y { //X.Y interface are shown below
public void myMethod() {
System.out.println(" Multiple inheritance example using interfaces");
}
public static void main(String[]args) {
Test t=new Test();
t.myMethod();
System.out.println(t.a); //compile time error ambigious field
}
}
Please help me to solve this issue
interface X {
public void myMethod();
int a = 0;
}
interface Y {
int a = 9;
public void myMethod();
}
Any variable defined in an interface is, by definition, public static final, in other words it's just a constant, it's not really a field (since there are no fields in interfaces).
So the compilation error you get points out that the compiler doesn't know witch constant you refer to.
You have 2 options here:
change the name of the constant in one of the interfaces, for example in interface Y declare int b = 9;
inside the main method point to a concrete constant: System.out.println(X.a);
Adding to one of the answer already provided.
If a class implements two interfaces and each interface have method with same signature and same name, then you are effectively defining only one method and they are same. If you have two methods of same name but different return types then there will be a compilation error.
Example ->
public interface A {
int a = 0;
void myMethod();
}
public interface B {
int a = 0;
void myMethod();
}
public class Test implements A, B {
#Override
public void myMethod() {
// My method is defined for both A and B
System.out.println(" Multiple inheritance example using interfaces");
}
public static void main(String[] args) {
Test object = new Test();
((A)(object)).myMethod();
((B)(object)).myMethod();
System.out.println(((A)object).a); //To print constant of A
System.out.println(((B)object).a); //To print constant of B
}
}
//Let's see other example
public interface A {
void myMethod();
}
public interface B {
boolean myMethod(); //changed void to boolean
}
public class Test implements A, B {
#Override
public void myMethod() { //Compilation error here, return type is incompatible
}
}
myMethod implements both myMethod declarations. I believe your problem is that in the two separate interfaces a has different values and is before and after the declaration of myMethod. The order is not important, since myMethod will surely be called after the declaration of a, but the difference of a values might cause some logical discrepancies. Maybe you could implement a getter for it as well, to handle the situation.
I have something like this:
public abstract class Menu {
public Menu() {
init();
}
protected abstract void init();
protected void addMenuItem(MenuItem menuItem) {
// some code...
}
}
public class ConcreteMenu extends Menu {
protected void init() {
addMenuItem(new MenuItem("ITEM1"));
addMenuItem(new MenuItem("ITEM2"));
// ....
}
}
//Somewhere in code
Menu menu1 = new ConcreteMenu();
As you can see superclass's init method is abstract and is called by constructor automatically after object is created.
I'm curious if i can run into some sort of problems with code like this, when i need to create some object of this kind whose structure wont't be changed in time.
Would be any approach better? It works in Java, but will it work in C++ and possibly ActionScript?
Thank you for answer.
DO NOT INVOKE OVERRIDEABLE METHODS FROM THE CONSTRUCTOR.
A quote from Effective Java 2nd Edition, Item 17: Design and document for inheritance, or else prohibit it:
There are a few more restrictions that a class must obey to allow inheritance. Constructors must not invoke overridable methods, directly or indirectly. If you violate this rule, program failure will result. The superclass constructor runs before the subclass constructor, so the overriding method in the subclass will be invoked before the subclass constructor has run. If the overriding method depends on any initialization performed by the subclass constructor, the method will not behave as expected.
Here's an example to illustrate:
public class ConstructorCallsOverride {
public static void main(String[] args) {
abstract class Base {
Base() { overrideMe(); }
abstract void overrideMe();
}
class Child extends Base {
final int x;
Child(int x) { this.x = x; }
#Override void overrideMe() {
System.out.println(x);
}
}
new Child(42); // prints "0"
}
}
Here, when Base constructor calls overrideMe, Child has not finished initializing the final int x, and the method gets the wrong value. This will almost certainly lead to bugs and errors.
Related questions
Calling an Overridden Method from a Parent-Class Constructor
State of Derived class object when Base class constructor calls overridden method in Java
See also
FindBugs - Uninitialized read of field method called from constructor of superclass
You are right in that it might cause problems with a derived class whose instance variables are initialised in the constructor or when the instance is created.
If you had this:
public class ConcreteMenu extends Menu {
String firstItem = "Item1";
protected void init() {
addMenuItem(new MenuItem(firstItem));
// ....
}
}
Then the MenuItem would have null as it's constructor argument!
Calling non-final methods in constructors is a risky practise.
A simple solution could be to separate the construction and the initialisation, like so:
Menu menu = new ConcreteMenu();
menu.init();
As others mentioned, calling an overridable method from the constructor is entering a world of pain ...
Have you considered doing the initialization in the constructor itself?
public abstract class Menu {
public Menu() {
....
}
protected void addMenuItem(MenuItem menuItem) {
// some code...
}
}
public class ConcreteMenu extends Menu {
public ConcreteMenu() {
super();
addMenuItem(new MenuItem("ITEM1"));
addMenuItem(new MenuItem("ITEM2"));
// ....
}
}