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.
Related
I don't understand why the ab.m3() method calls the function of the parent class and not the child. I thought maybe passing a new Integer to the method might call the method of the parent class because Integer is an Object so I tried it with an int but still it gave me the same result!
public class A {
public void m1(){
System.out.println("A.m1");
}
public void m2(){
System.out.println("A.m2");
}
public void m3(Object x){
System.out.println("A.m3");
}
}
public class B extends A{
public void m1(){
System.out.println("B.m1");
}
public void m2(int x){
System.out.println("B.m2");
}
public void m3(int x){
System.out.println("B.m3");
}
public static void main(String[] argv){
A aa = new A();
A ab = new B();
int num = 2;
ab.m1();
ab.m2();
ab.m3(new Integer(2));
ab.m3(num);
}
}
Output:
B.m1
A.m2
A.m3
A.m3
B.m3 does not override A.m3, because the parameter lists are not compatible.
Because the only matching method in A is A.m3, and because there is no override in B, it is A.m3 that will be called.
Your ab reference is of type A.
When compiling ab.m3(num);, the compiler isn't looking at the object type. In general, it won't always know what the object type is. Instead, it's looking at the reference type. It cannot match B.m3(int), because the reference type is not of type B.
So the compiler chooses the A.m3(Object) method, which could be overridden at runtime. But it's not, so the A implementation is called.
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.
I have one class and one interface:
public interface A {
public void getNum();
}
public class B {
public void getNum() {
System.out.println("4");
}
}
public class C extends B implements A {
protected void getNum() {
System.out.println("3");
}
}
Now my question is, why this code is giving compilation error and how can we avoid it. Is there any way in which we can override this method in class C?
From Java Language Specification:
jls-8.4.8.3
The access modifier (ยง6.6) of an overriding or hiding method must provide at least as much access as the overridden or hidden method, as follows:
If the overridden or hidden method is public, then the overriding or hiding method must be public; otherwise, a compile-time error occurs.
...
Notice that you are trying to override public method getNum() inherited from class B (and also from interface A) with new one that has protected access modifier. It means that you are trying to reduce visibility of this method which according to specification is incorrect.
To be able to override this method you need to use public access modifier with your new version of that method.
Why you cant reduce visibility? Take a look at below code which uses your classes but is placed inside some other package and ask yourself "how should this code behave?".
package my.pckage;
import your.pckage.A;
import your.pckage.C;
public class Test{
public static void main (String[] args){
C C = new C();
c.getNum();// ERROR: Test class doesn't have access to `c`s protected method.
// Why should it have, Test doesn't extend C.
A a = (A)c;// Lets try using other reference
a.getNum();// Should `a` have access to method that is protected in `C`?
// If yes, then what is the point of declaring this method
// protected if all I would have to do to get access to it is
// casting instance of C to A interface?
}
}
Fix the typos and try again ;)
public interface A {
public void getNum();
}
public class B {
protected void getNum() {
System.out.println("4");
}
}
public class C extends B implements A {
public void getNum() {
System.out.println("3");
}
}
First of all scope should be from lower to higher while you are overriding method in Java. scope of subclass method should be high then super class for e.g
Valid Overriding
class B {
protected void getNum() {
System.out.println("4");
}
class C extends B {
public void getNum() {
System.out.println("3");
}
InValid Overriding
class B {
public void getNum() {
System.out.println("4");
}
class C extends B {
protected void getNum() {
System.out.println("3");
}
Your second problem is you have created two public class which is not valid you can create only one public class in your java file.
When you implement an interface you need to compulsorily override it to provide concrete implementation of function(unless the class implementing the interface is abstract). In your case you are implementing an interface which make you implement getNum() function and due to overriding class you have another function with same signature which is not allowed. So you get compilation error.
Possible solution : You can make B as an interface.
The explanation by Pshemo is perfectly right that you can not reduce visibility of overridden or the interface functions.
Lets take an exapmle
class B
{
protected void getProtected1()
{
System.out.println("4");
}
protected void getProtected2()
{
System.out.println("4");
}
public void getPublic1()
{
System.out.println("4");
}
public void getPublic2()
{
System.out.println("4");
}
}
class C extends B
{
#Override
private void getPublic1() //COMPILATION ERROR : Cannot reduce the visibility of the inherited method from myzeromqApp.B
{
System.out.println("3");
}
#Override
protected void getPublic2() //COMPILATION ERROR :Cannot reduce the visibility of the inherited method from myzeromqApp.B
{
System.out.println("3");
}
#Override
private void getProtected1() //COMPILATION ERROR : Cannot reduce the visibility of the inherited method from myzeromqApp.B
{
System.out.println("3");
}
#Override
public void getProtected2() // NO ERROR IT MEANS YOU ARE ALLOWED TO INCREASE THE VISIBILITY
{
System.out.println("3");
}
}
From the above example it is clear that you are not allowed to decrease the visibility of function in any case.
In your question you are trying to implement the interface function and we know interface in Java has rules that,
Method: only public & abstract are permitted
Field: (Variables) only public, static & final are permitted
As thumb of rule, you can never decrease the visibility, of overridden or implemented methods or variables and for interface it is always public (if visibility is concerned) so those should always be public in implemented classes.
As stated, only one public class can be used per file. So, to have them all public, one must create three separate .java files. I will write the code up below, as well as detailing how to override the method to use the correct version of it in each case.
One may always have methods with the same name, but for overriding, they must have different argument lists. This is one of the compiler errors, you have three methods with the same argument lists, namely none. You may create and call the method with the correct argument list to achieve the desired result.
A.java:
package stackOverflow.tests; // Sample package for visibility
public Interface A {
public void getNum(int a); // Method takes a single integer argument
}
B.java:
package stackOverflow.tests;
public class B {
protected void getNum(int a, int b) { // Method takes two integer arguments, differing in the argument list but equal in name
System.out.println("4");
}
}
C.java:
package stackOverflow.tests;
import stackOverflow.tests.A; // Importing both classes to use their methods
import stackOverflow.tests.B;
public class C extends B implements A {
public void getNum(int a, String x) { // Takes an integer and a string argument
System.out.println("3");
}
public void getNum(int a) {
//Do nothing, as in A.java, this code is necessary to be able to override the method.
}
public static void main(String[] arguments) { // Sample main method for implementation
C c = new C(); // Instantiating class C
int test = 0; // Initializing two integer variables and one String variable
int test2 = 0;
String test3 = "";
c.getNum(test); // takes one integer, using getNum() from A.java
c.getNum(test, test2); // takes two integers, using getNum() from B.java
c.getNum(test, test3); // takes an integer and a String, using getNum() from C.java
}
}
Output:
4
3
As seen in the code above, the argument lists define which version of the method is used. As a side tip, the definition getNum(int a) is no different from getNum(int b), so this would result in it not compiling.
In order to get this working you can do something like this since there can be only one public class per file and the file name should be the same name as that of the class
public class HelloWorld{
public static void main(String []args){
C obj=new C();
obj.getNum();
}
}
//interface
interface A {
public void getNum();
}
class B {
protected void getNum() {
System.out.println("4");
}
}
class C extends B implements A {
public void getNum() {
System.out.println("3");
}
}
output:
3
A java class file can have only one public class or interface.
Change the visibility of the interface and the defined class to default level or declare it in separate files.
Only public and abstract modifiers can be applied to interface methods. The class implementing the interface cannot change the visibility of the method (we cannot change it from public to protected).
I tried this:
class protectedfinal
{
static abstract class A
{
protected final Object a;
}
static class B extends A
{
{ a = new Integer(42); }
}
public static void main (String[] args)
{
B b = new B();
}
}
But I got this error:
protectedfinal.java:12: error: cannot assign a value to final variable a
{ a = new Integer(42); }
^
1 error
How to work around this problem?
Some people suggested here to use a constructor but this works only in some cases. It works for most objects but it is not possible to reference the object itself from within the constructor.
static abstract class X
{
protected final Object x;
X (Object x) { this.x = x; }
}
static class Y extends X
{
Y () { super (new Integer(42)); }
}
static class Z extends X
{
Z () { super (this); }
}
This is the error:
protectedfinal.java:28: error: cannot reference this before supertype constructor has been called
Z () { super (this); }
^
One could argue that it does not make much sense to store this kind of reference, because this exists already. That is right but this is a general problem which occurs with any use of this in the constructor. It is not possible to pass this to any other object to store it in the final variable.
static class Z extends X
{
Z () { super (new Any (this)); }
}
So how can I write an abstract class, which forces all child classes to have a final member which gets initialized in the child?
You have to initialize A.a in its constructor. Subclasses will use super() to pass initializer to A.a.
class protectedfinal {
static abstract class A {
protected final Object a;
protected A(Object a) {
this.a = a;
}
}
static class B extends A {
B() {
super(new Integer(42));
}
}
public static void main (String[] args) {
B b = new B();
}
}
You cannot use this until superclass constructors were called, because at this stage the object is not initialized, even Object constructor hasn't run at this point, therefore calling any instance methods would lead to unpredictable results.
In your case, you have to resolve circular reference with Z class in another way:
Z () { super (new Any (this)); }
Either use a non-final field or change class hierarchy. Your workaround with instance method super(new Any(a())); would not work for the same reason: you cannot call instance methods until superclass constructors were run.
In my personal oppinion, your problems hints towards a flaw in design.
But to answer your question. If absolutly necessary, you can change final fields in java using reflection.
And if everything fails, you can still utilize sun.misc.unsafe.
But I strongly discourage you from doing so, since it potentially kills your vm.
My work around so far is to use methods instead of final members:
class protectedfinal
{
static abstract class AA
{
protected abstract Object a();
}
static class BB extends AA
{
#Override
protected Object a() { return this; }
}
public static void main (String[] args)
{
AA a = new BB();
System.out.println (a.a());
}
}
But I would like to use final members, because I think accessing a final member is faster than calling a method. Is there any chance to implement it with final members?
From the Sun docs
Normally, you would put code to
initialize an instance variable in a
constructor.There are two
alternatives to using a constructor to
initialize instance variables:
initialize blocks and final methods.
I could understand the use of initialize blocks. Can anyone please explain the use of final methods for instance var initialization? A non-final public setter can do this job. Why not just use them ?
The advantage is already described in the very same Sun tutorial you linked to:
A final method cannot be overridden in a subclass. This is discussed in the lesson on interfaces and inheritance.
This is especially useful if subclasses might want to reuse the initialization method. The method is final because calling non-final methods during instance initialization can cause problems. Joshua Bloch describes this in more detail in Effective Java(item 17 Design and document for inheritance).
The reason a non-final method is dangerous in initialization is because the instance initialization of the superclass executes before the sub class is initialized. Therefore if the non-final method is overriden in the sub class and is executed during the initialization of the superclass it may be accessing uninitialized fields of the subclass giving erroneous results.
The general rule is(quoting from Effective Java): Constructors must not invoke overridable methods, directly or indirectly.
It's explained on the same page of the referenced tutorial. The reason is that a non-final method can be overriden by up subclass. Here's an example:
class Whatever {
private List<String> myVar = initializeInstanceVariable();
protected List<String> initializeInstanceVariable() {
return new ArrayList<String>();
}
}
class Whoever extends Whatever {
#Override
protected List<String> initializeInstanceVariable() {
return Collections.unmodifiableList(super.initializeInstanceVariable());
}
}
So if you create Whoever, myVar will become unmodifiable ;-)
Other examples
From alykhantejani.github.io
I made it compilable and simplified it.
Duck.java
public class Duck {
String sound = "quack";
protected String speech;
public Duck() {
initSpeech();
}
protected void initSpeech() {
speech = "sound = " + sound;
}
public void speak() {
System.out.println(speech);
}
protected String getSound() {
return sound;
}
}
SqueakyDuck
public class SqueakyDuck extends Duck {
String squeakSound = "squeak";
public SqueakyDuck() {
super();
}
#Override
protected void initSpeech() {
speech = "sound = " + squeakSound;
}
#Override
protected String getSound() {
return squeakSound;
}
}
Main.java
public class Main {
public static void main(String[] args){
Duck squeaky = new SqueakyDuck();
squeaky.speak();
System.out.println(squeaky.getSound());
}
}
Output:
sound = null
squeak
My example
Superclass.java
public class Superclass {
protected int x = m();
protected int m() {
return 8;
}
}
Subclass.java
public class Subclass extends Superclass {
private int y = 7;
#Override
protected int m() {
return y;
}
}
Main.java
public class Main {
public static void main(String[] args) {
Superclass s = new Subclass();
System.out.println(s.x);
}
}
Output:
0
Order of execution:
main
m from Subclass (y is not initialized in this moment and 0 is the default value for int)
constructor Superclass
constructor Subclass