Stackoverflow error in overriding static methods of static inner classes - java

public class StaticInnerClass {
public static void main(String[] args) {
//Outers out=new Outers();
Outers.Inner1 in=new Outers.Inner2();
in.display();
}
}
class Outers
{
static class Inner1
{
static void display()
{
display();
System.out.println("Inner1");
}
}
static class Inner2 extends Inner1
{
static void display()
{
System.out.println("Inner2");
}
}
}
The above program gives a stackoverflow error. Please explain that why doesn't it display "Inner1" because static methods don't override.

The static method that executes is based on the static type, not the instance type:
Outers.Inner1 in=new Outers.Inner2();
So when you call this line, the static type is Outers.Inner1 and therefore it calls the display method that's part of this class, which calls itself repeatedly (causing the StackOverflowError.)

Static methods are not invoked polymorphically!
This will cause the method display to invoke itself again and again until you get Stack Overflow Error. Also, see this question : Polymorphism and Static Methods

A static method can't be overridden by sub class
Static methods should be called with Class not with an object, even though you use object, it still going to use the type of the object.

Related

Why is superclass method called while that method is overriden? (from OCA practice test) [duplicate]

This question already has answers here:
Why doesn't Java allow overriding of static methods?
(22 answers)
Closed 5 years ago.
From question three in these OCA practice questions (pdf):
abstract class Writer {
public static void write() {
System.out.println("Writing...");
}
}
class Author extends Writer {
public static void write() {
System.out.println("Writing book");
}
}
public class Programmer extends Writer {
public static void write() {
System.out.println("Writing code");
}
public static void main(String[] args) {
Writer w = new Programmer();
w.write();
}
}
The output is Writing....
I don't understand why. As Programmer overrides Writer's write method, I thought it should call the method in Programmer and not in Writer.
Why?
You have to understand two points here.
There is no overriding concept in case of static members. They are simply static and never change based on instance.
And static members bind to class rather than instance. So no matter what is the instance, they look the type they got called and execute.
The type of the reference is Writer. You have called a static method for which overriding isn't applied - the method from the Writer is going to be invoked.
The mechanism is called method hiding.
Check out these cases:
new Programmer().write(); // code [Programmer]
((Writer)new Author()).write(); // ... [Writer]
new Author().write(); // book [Author]
((Writer)new Programmer()).write(); // ... [Writer]
new Writer() {{}}.write(); // ... [Writer]
As we know, static methods cannot be overridden. If we try to do so, it turns out to be method hiding instead. In the above case, both class- Writer and Programmer contain write() method.
When Programmer extends the Writer class and provides its own implementation of the write() method, it just hides the Writer implementation of it.
Now, on runtime, the compiler just checks the Reference type (since it is a static method, compiler is not concerned about the object created to call the method. Remember, static methods are class methods). Hence, compiler checks and finds that reference w is of type Writer, it calls the Writer version of the write method instead.
If the methods would not have been static, what you expect would have been the output instead.
Found the answer myself.
There is no such thing as overriding a static method in Java. This is why when you call a static method from the superclass reference, the superclass static method will be called.
So
public class SuperClass {
public static void write() {
System.out.println("Writing Super");
}
public void writeMore() {
System.out.println("super something");
}
}
public class SubClass extends SuperClass {
public static void write() {
System.out.println("Writing Sub");
}
public void writeMore() {
System.out.println("sub something");
}
}
public class Test {
public static void main(String[] args) {
SuperClass super = new SubClass();
super.write();
super.writeMore();
}
}
Will output
Writing super
sub something
If you want to call the static write() method from the subclass. You have to reference it from a subclass. E.g.:
SubClass sub = new Subclass();
sub.write();
Some sources where I learned about this:
https://www.geeksforgeeks.org/can-we-overload-or-override-static-methods-in-java/
Why doesn't Java allow overriding of static methods?

How can you declare that all subclasses of an abstract class will implement main?

I have an abstract class called Trader which acts like a client with a server (StockMarket) and I would like to declare in the Trader class that all classes that inherit from it will need to implement a main entry point so that they can be run.
The problem is that if I write:
public static abstract void main(String[] args) throws Exception;
it gives an error that only visibility modifiers are allowed. But if I remove the static modifier then it does not work as a main entry point allowing it to be run.
So how to declare all subclasses of an abstract class must implement a main method?
You can't.
What I would do instead is declare an abstract, non-static method in Trader:
public abstract void run(String[] args) throws Exception;
And then declare a separate main class that would instantiate an instance, and call the run method:
class RunTrader {
private static final String DEFAULT_CLASS = "...";
public static void main(String[] args) {
try {
String className = System.getProperty("main-trader-class", DEFAULT_CLASS);
Class<Trader> traderClass = (Class<Trader>)Class.forName(className);
Trader trader = traderClass.newInstance();
trader.run(args);
} catch (Exception e) {
// handle the exception
}
}
}
Lets start with the meaning of
public static void main (String[] args)...
static
means that this method does require an instance of the class (containing this method). Java virtual machine (JVM) states this as a requirement for the entry point of a program, reason being that the class may have multiple constructors or no default constructor and there is no way for JVM to know how to create object of the class.
public
allows the method to be accessible outside the package (and class obviously), so JVM is free to invoke this method.
main
is the name of the method that JVM looks for in the class, since there could be multiple public static methods.
void
returns nothing. This is the part of the signature that JVM looks for as entry point.
Now lets answer your question in light of this information. Polymorphism is relevant to OOP concept of inheritance and interface implementation, and it irrelevant to static methods.
So the only choice you have is to choose 1 'public static void main' method as the entry point based on the 'args', call other public static methods. However, other methods need not have the same signature.
Static methods cannot be abstract.
Static members data are same for all the objects and derived classes.
Static members can't be overridden by derived class.
Since abstract method need to be defined in derived class it can't be static.
Remove static and try.
static method does not supports polymorphism, so you can't declare it as abstract. but you can declaring an abstract class with abstract methods that #MauricePerry has been proposed. I will come up with how to get the Main class?
you can extract the Main class name from the system property sun.java.command.
truncate the args from the command.
second, truncate the IDE Main class name if present.
here is my implementation you can using:
public abstract class Trader {
protected abstract void run(String... args);
public static void main(String[] args) throws Exception {
runAs(getMainClass(args)).run(args);
}
private static Trader runAs(Class<?> mainClass)
throws IllegalAccessException, InstantiationException {
checking(!Modifier.isAbstract(mainClass.getModifiers())
, () -> "abstract class can't be run: " + mainClass);
checking(Trader.class.isAssignableFrom(mainClass)
, () -> "class is not a " + Trader.class
+ " can't be run: " + mainClass);
return Trader.class.cast(mainClass.newInstance());
}
private static void checking(boolean condition, Supplier<String> message) {
if (!condition) {
throw new IllegalArgumentException(message.get());
}
}
private static Class<?> getMainClass(String... args)
throws ClassNotFoundException {
String command = commandWithoutArgs(args);
String[] classes = command.split("\\s+");
return Class.forName(classes[ classes.length - 1]);
}
private static String commandWithoutArgs(String[] args) {
String command = System.getProperty("sun.java.command");
return command.substring(0, command.length() - argsLength(args)).trim();
}
private static int argsLength(String[] args) {
if (args.length == 0) {
return 0;
}
return Stream.of(args).collect(Collectors.joining(" ")).length() + 1;
}
}
Example
public class Application extends Trader {
#Override
protected void run(String... args) {
System.out.println("Application");
}
}
run the Application using command java Application or run it in IDE.
To run a program JVM find main method like
public static void main(String[] args)
abstract is not used with main method

error on Implement interface in main class

Hi friends im learning java from basics..
I have some doubt in implementing interface.
WORKING CODE
Using interface in a class is working....
interface bala
{
void prnt();
}
class ex implements bala{
#Override
public void prnt() {
System.out.print("hi");
}
}
public class Solution
{
public static void main(String arg[])
{
ex p = new ex();
p.prnt();
}
}
NOT WORKING
Here is my doubt, why i cant implement interface in main method?
plea
interface bala
{
void prnt();
}
public class Solution implements bala
{
public static void main(String arg[])
{
prnt();
}
#Override
public void prnt() {
System.out.println("hi");
}
}
What is happening here?
Why implementing on main() is not working?
Is there is a way to make working interface on main function?
Given Bellow code works well.
interface bala
{
void prnt();
}
public class Solution implements bala
{
public static void main(String arg[])
{
Solution sol = new Solution();
sol.prnt();
}
public void prnt() {
System.out.println("hi");
}
}
It's not working, because you're trying to access non-static (i.e. instance) method from a static context.
In order to invoke it, you need an instance of the Solution class (note that in your working code you have an instance of the ex class, so here you need to do the same with slight difference):
Solution instance = new Solution();
instance.prnt();
Problem is main() is static, static blocks can access static members or with object reference . So here you could simply create an object/instance to invoke the method:
new Solution().prnt();
try new Solution().prnt() instead of calling prnt()
the problem is :
main method is a static method. And your overridden method is non-static. You can't call non-static methods from static context.
In order to call overridden method prnt() to call, you need to instantiate you Solution class like -
Solution sol = new Solution();
and then
sol.prnt();
Best Option to Do it . Create the instance of class and Access it.since main method is a static method you can do like that
Solution instance = new Solution();//Creating instance of class
instance.prnt();//access prnt .
You should create the object of Solution class in main method
Solution s1 = new Solution();
s1.print();
Otherwise, you can create the method as static because you are trying to access
the method from static context.

Do Upcasting effects on Static methods?

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.

Confusion about static keyword

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.

Categories