Why It calls base class method when we declare method as static in base as well as in derive class and do upcasting.
class Base
{
static void show(){
System.out.println("Base class....");
}
}
class Derive extends Base
{
static void show(){
System.out.println("Drive class....");
}//method hidding.....
public static void main(String[] args)
{
Base b= new Derive();
b.show();
}
}
There are several issues here to mention:
static methods are not inherited and not overridden by the sub-classes
static methods do not need an instance to be called, they need a class
So, basically, calling b.show(); actually means calling Base.show();
You're calling Base.show, not Derive.show. Method hiding is not overriding.
ยง8.4.8.2. of the Java Language Specification gives an example that demonstrates exactly what happens here:
A class (static) method that is hidden can be invoked by using a reference whose type is the class that actually contains the declaration of the method. In this respect, hiding of static methods is different from overriding of instance methods. The example:
class Super {
static String greeting() { return "Goodnight"; }
String name() { return "Richard"; }
}
class Sub extends Super {
static String greeting() { return "Hello"; }
String name() { return "Dick"; }
}
class Test {
public static void main(String[] args) {
Super s = new Sub();
System.out.println(s.greeting() + ", " + s.name());
}
}
produces the output:
Goodnight, Dick
because the invocation of greeting uses the type of s, namely Super, to figure out, at compile time, which class method to invoke, whereas the invocation of name uses the class of s, namely Sub, to figure out, at run-time, which instance method to invoke.
Just one more completion to the answers above. It's best to invoke class methods by their class not by an instance variable: Base.show() not b.show() to make clear that the method is a static method. This is especially useful in your case when you are hiding a method, not overriding it.
Related
Method calls are always determined based on the runtime type of the object, however how can I call shadowed methods of base classes from an inherit instance?
class Base {
String str = "base";
String str() { return str; }
}
class Impl extends Base {
String str = "impl";
String str() { return str; }
}
class Test {
public static void main(String[] args) {
System.out.println(((Base) new Impl()).str); // print 'base'
System.out.println(((Base) new Impl()).str()); // print 'impl'
}
}
For example above, how can I call the str() method of Base class from an Impl instance, preferably without using reflection?
Using the Keyword super
Accessing Superclass Members
If your method overrides one of its superclass's methods, you can invoke the overridden method through the use of the keyword super. You can also use super to refer to a hidden field (although hiding fields is discouraged). an example below.
public class Superclass {
public void printMethod() {
System.out.println("Printed in Superclass.");
}
}
calling printMethod since child class
Here is a subclass, called Subclass, that overrides printMethod():
public class Subclass extends Superclass {
// overrides printMethod in Superclass
public void printMethod() {
super.printMethod();
System.out.println("Printed in Subclass");
}
public static void main(String[] args) {
Subclass s = new Subclass();
s.printMethod();
}
}
if you want to read more
https://docs.oracle.com/javase/tutorial/java/IandI/super.html
I'm extending from an abstract class named ChildClass, it has 4 constructors which should be implemented.
There is a set of general configuration common to all constructors.
I could abstract these tasks and call it in all constructors.
Is there anyway to call a specif method when an object is going to be initialized rather than calling it in all of the constructor signatures?
Since Java compiler must ensure a call to a constructor of the base class, you can place the common code in a constructor of your abstract base class:
abstract class BaseClass {
protected BaseClass(/*put arguments here*/) {
// Code that is common to all child classes
}
}
class ChildClassOne extends BaseClass {
public ChildClassOne(/*put arguments here*/) {
super(arg1, arg2, ...);
// More code here
}
}
As already stated in the comment, one way to call common initialization code would be the use of this(...), i.e. you'd call one constructor from another. The problem, however, is that this call would have to be the first statement of a constructor and thus might not provide what you want.
Alternatively you could call some initialization method (the most common name would be init()) in all constructors and in a place that is appropriate (e.g. at the end of the constructor). There is one problem though: if a subclass would override that method it could create undefined situations where the super constructor calls the method and the method uses non-yet-initialized fields of the subclass. To mitigate that the method should not be overridable, i.e. declare it final or make it private (I'd prefer to have it final though because that's more explicit).
Depending on your needs there's a 3rd option: use the initializer block:
class Super {
{
//this is the initializer block that is called before the corresponding constructors
//are called so it might or might not fit your needs
}
}
Here's an example combining all 3 options:
static class Super {
{
//called before any of the Super constructors
System.out.println( "Super initializer" );
}
private final void init() {
System.out.println( "Super init method" );
}
public Super() {
System.out.println( "Super common constructor" );
}
public Super(String name) {
this(); //needs to be the first statement if used
System.out.println( "Super name constructor" );
init(); //can be called anywhere
}
}
static class Sub extends Super {
{
//called before any of the Sub constructors
System.out.println( "Sub initializer" );
}
private final void init() {
System.out.println( "Sub init method" );
}
public Sub() {
System.out.println( "Sub common constructor" );
}
public Sub(String name) {
super( name ); //needs to be the first statement if used, calls the corrsponding Super constructor
System.out.println( "Sub name constructor" );
init(); //can be called anywhere
}
}
If you now call new Sub("some name"), you'll get the following output:
Super initializer
Super common constructor
Super name constructor
Super init method
Sub initializer
Sub name constructor
Sub init method
You can declare an instance method in the class which can be called from a constructor like this:
Class A{
public A(){
initialize();
}
public void initialize(){
//code goes here
}
}
This concept extends to abstract classes as well.
You could chain your constructors.
public class Test {
public Test() {
// Common initialisations.
}
public Test(String stuff) {
// Call the one ^
this();
// Something else.
}
You can then put your common code in the () constructor.
An alternative is to use an Initializer block.
Class A {
{
// initialize your instance here...
}
// rest of the class...
}
The compiler will make sure the initializer code is called before any of the constructors.
However, I would hesitate a bit to use this use this - perhaps only if there are no other alternatives possible (like putting the code in a base class).
If you can put the common code in one constructor and call it as the first instruction from the other constructors, it is the Java idiomatic way.
If your use case is more complex, you can call a specific method from the constructors provided it is private, final or static (non overidable). An example use case would be:
class Test {
private final void init(int i, String str) {
// do common initialization
}
public Test(int i) {
String str;
// do complex operations to compute str
init(i, str); // this() would not be allowed here, because not 1st statement
}
public Test(int i, String str) {
init(i, str);
}
}
Make a common method and assign it to instance variable. Another way of doing it.
import java.util.List;
public class Test {
int i = commonMethod(1);
Test() {
System.out.println("Inside default constructor");
}
Test(int i) {
System.out.println("Inside argument Constructor ");
}
public int commonMethod(int i) {
System.out.println("Inside commonMethod");
return i;
}
public static void main(String[] args) {
Test test1 = new Test();
Test test2 = new Test(2);
}
}
Since the subclass is not constructed yet, is it unsafe to call an abstract method in a super class constructor?
However, if the method's behaviour does not depend on the constrction of subclass, e.g. just return a constant with regard to the subclass, is it still unsafe or will it work reliably?
Moreover, if it works, how to do it if I do not want to make the super class abstract?
Update: for last question
public class SuperClass {
public SuperClass() {
System.out.println(getValue());
}
public String getValue() {
return "superclass";
}
public static void main(String[] args) {
new SubClass();
}
}
class SubClass extends SuperClass {
public SubClass() {
super(); // Comment out this or not will not affect the result
}
public String getValue() {
return "subclass";
}
}
I wrote a test, and figure it out: the result is : subclass
Thanks to #Tim Pote's example.
It is generally (though not necessarily) considered unsafe. As you said, the superclass may not be fully constructed, and therefore won't be ready to handle all of the calls a subclass might make in its overridden method.
However, in the case that all subclasses simply return a constant that isn't dependent on any other method, then it should be fine. The only downside is that you can't guarantee that a subclass will override that method in an appropriate manner.
In regards to your last question: this isn't an issue of an abstract vs. concrete superclass. This is an issue with calling overridable methods in a constructor. Abstract vs. concrete is beside the point.
Edit in response to the OP's comment
I'm not certain what you mean by "polymorphiscly". Calling a virtual method always invokes the sub-most implementation. The only time a superclasses implementation is invoked is via the super keyword. For example:
public class SuperClass {
public SuperClass() {
System.out.println(getValue());
}
public String getValue() {
return "superclass";
}
public static void main(String[] args) {
new SubClass();
}
public static class SubClass extends SuperClass {
public String getValue() {
return "subclass";
}
}
}
prints subclass.
And this:
public class SuperClass {
public SuperClass() {
System.out.println(getValue());
}
public String getValue() {
return "superclass";
}
public static void main(String[] args) {
new SubClass();
}
public static class SubClass extends SuperClass {
public String getValue() {
return super.getValue() + " subclass";
}
}
}
prints superclass subclass
As others have explained there is an inherent risk in calling abstract methods in super class constructor.
The one exception I have found is when the subclass provides some "constant" information, e.g getId(), getHandledMessages() and suchlike.
I just read in a document that "A static method can call only other static methods and can not call a non-static method from it". But when I tried to test it I think saw something different.
I have a class C which is described below
import pckage1.*;
public class C
{
public static void main(String par[])
{
}
public static void cc()
{
A ob = new A();
ob.accessA(0);
}
}
where class A is
package pckage1;
public class A
{
public A()
{
}
public void accessA(int x)
{
}
}
Now here from cc STATIC method in class C, a NON STATIC method accessA() is called. How could that be possible if the statement about static method is true?
A static method can call only other static methods and can not call a non-static method from it
That's wrong.
Static methods can call non-static methods as long as they have objects to call the methods on (as you discovered in your code snippet). How else would a non-static method ever be called?
You can't do nonStaticFoo() from a static method, since it is interpreted as this.nonStaticFoo() and since there is no this available in a static method.
Very similar question from earlier today:
Static method access to non-static constructor?
You didn't call a non-static method of your Class.
Try with this :
import pckage1.*;
public class C
{
public static void main(String par[])
{
}
public static void cc()
{
A ob = new A();
ob.accessA(0);
print();
}
public void print()
{
}
}
It won't work, because you're callign a non-static method from a static method, and you don't have an instance of the C class to work with in your static method.
Since every Java program starts executing from a static method, if the statement you cite were true, there would have been no way for any Java program to ever execute an instance method!
A static method has no default context in C, and not this.
However any method can use an intsnace of a class to call a method.
You're calling an instance method, on an instance--you're not trying to call an instance method directly.
You're creating an instance of class A and call a method on it.
So the method you are calling is instance method (not static method).
But you cannot call a non static method of class C.
interface I
{
void show();
}
class A implements I
{
void show()
{
System.out.println("class A");
}
public static void main(String s[])
{
I i=new A();
i.show();
i.toString();
}
}
Q> As interface I does not contain the abstract method toString() but still The following code gets compiled. How?
when super class variable is used to refer sub class obj then compiler first searches the similar method in the super class if not found gives error.
here Interface does not contain the method toString().
ex=>
class A
{
void show()
{
System.out.println("show");
}
}
class B
{
void show()
{
System.out.println("show B");
}
void display()
{
System.out.println("display B");
}
public static void main(String s[])
{
A a=new B();
a.show(); //will execute
a.display(); //give error
}
All classes inherit from Object. Object has a toString.
To use any interface it must be backed by a actual class. So the Java compiler knows that it can use any method defined in java.lang.Object when dealing with an Interface.
To put it a slightly different way:
interface I { ... }
has an "magic"
interface I extends Object { ... }
So you can use Objects methods when detail with I. However you can not use any methods in the concrete class that do not appear in the interface. So to combine you two examples:
interface Car {
void drive();
}
class Convertible implements Car {
void drive() {}
void openRoof() {}
public static void main() {
Car porscheBoxster = new Convertible();
porscheBoxster.drive(); // OK - exists in interface
porscheBoxster.toString(); // OK - exists in java.lang.Object.
porscheBoxster.openRoof(); // Error. All we know is the porscheBoxster is of type Car.
// We don't know if it is a Convertible or not.
}
}
Every class in Java is an Object, thus, they are always able to run the following methods:
clone()
equals(Object)
finalize()
getClass()
hashCode()
notify()
notifyAll()
toString()
wait()
wait(long)
wait(long, int)
Because 'toString()' is in the class Object which every non-primitive data is derived from. So every object has this method.
In Java, every class you construct, inherits from the base class Object.
This means that your class by default will have a lot of useful methods, amongst others toString().