class Top{
public Top(String s){System.out.print("B");}
}
public class Bottom2 extends Top{
public Bottom2(String s){System.out.print("D");}
public static void main(String args[]){
new Bottom2("C");
System.out.println(" ");
} }
In the above program, I guessed the output must be BD, but in the book they said the compilation fails. Can anyone explain this?
The derived class Bottom2 is required to call the base class constructor using super, otherwise you'll get a compile error. For example, if you do this, it will compile:
public Bottom2(String s) { super(s); System.out.print("D"); }
See the section on Subclass Constructors.
When you have public Top(String s) then java doesn't create the default constructor with no arguments then when you write the child class, the constructor look for the default constructor (because you are not calling explictly)... then the compilations fails.
Related
public class Base {
public Base() {
foo();
}
public void foo() {
System.out.println("Base.foo()");
}
}
public class Derived extends Base {
public Derived () {}
public void foo() {
System.out.println("Derived.foo()");
}
}
And then, when i call those:
public class Running {
public static void main(String[] args) {
Base b = new Base();
Derived d = new Derived();
}
}
It outputs:
*Base.foo()*
*Derived.foo()*
So why, when it gets to derived constructor, it invokes the base constructor but uses the derived's method instead?
PS: If I mark those methods as private, it will print out:
*Base.foo()*
*Base.foo()*
This is how Java works read this page https://docs.oracle.com/javase/tutorial/java/IandI/super.html
And more specifically the Note here :
Note: If a constructor does not explicitly invoke a superclass
constructor, the Java compiler automatically inserts a call to the
no-argument constructor of the superclass. If the super class does not
have a no-argument constructor, you will get a compile-time error.
Object does have such a constructor, so if Object is the only
superclass, there is no problem.
So as you can see this is expected behavior. Even though you dot have a super call it is still automatically inserting it.
In regards of the second Question even though you are within the super constructor body still you Instance is of the Subtype. Also if you have some familiarity with C++ read this Can you write virtual functions / methods in Java?
The reason why it will write the base class when marking with private is because private methods are not Inherited. This is part of the Inheritance in Java topic.
To answer the question in your title. As I said, you cannot avoid the base class constructor being called (or one of the base class constructors if it has more than one). You can of course easily avoid the body of the constructor being executed. For example like this:
public class Base {
public Base(boolean executeConstructorBody) {
if (executeConstructorBody) {
foo();
}
}
public void foo() {
System.out.println("Base.foo()");
}
}
public class Derived extends Base {
public Derived() {
super(false);
}
public void foo() {
System.out.println("Derived.foo()");
}
}
public class Running {
public static void main(String[] args) {
Base b = new Base(true);
Derived d = new Derived();
}
}
Now the main method prints only:
Base.foo()
Because in the contructor of the Derived class it automatically gets injected a call to super(), if you do not add a call to super or to other constructor in the same class (using this).
I would like to know whether it is possible to have a constructor with void return type as in the below example.
For example
class A
{
void A(){} //where A is constructor and for which return type is void
public static void main(string arg[]){
A a = new A();
}
}
A constructor does not have a result / return type.
If you add a result / return type to a "constructor" you turn it into a method whose name is the same as the class name. Then new won't be able to use it, and any this(...) or super(...) call in the method will be a syntax error.
For your example, you won't actually get an error. That is because Java will add a default no-args constructor for A ... because you haven't actually defined any constructors. The new in your example will actually be using the default constructor ....
If you changed your code to this:
class A {
void A() { System.err.println("hello"); }
public static void main(string arg[]) {
A a = new A();
}
}
and compiled and ran it, you should see that it DOES NOT give you any output. Remove the void and you will see output.
so here A() work as a method
It >>is<< a method. But it is not "working". As my version of your example shows ... the method is not being called at all.
You are confused why your code compiles. It's because A() is not actually a constructor but a method (that unfortunately has the same name as the class). The class A has an implicit default constructor which is used by main. The method A() is not used.
As others have pointed out, constructors do not have a return type.
Constructors don't have return type - https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
Hope this example would be more easy to understand. In this example you can see Main as the class, constructor and method and how those works. Please see the output too.
See what happens when you call the constructor and what happens when the method called with constructor.
Program:
//Class
public class Main
{
//Constructor
public Main(){
System.out.println("Hello World 1");
}
//Method
public void Main(){
System.out.println("Hello World 2");
}
//Another method but static
public static void main(String[] args) { //This should be small letter 'main'
System.out.println("Hello World 3"); //Print this first
Main constructor = new Main(); //Run constructor and print.
constructor.Main(); //Run method (void Main()) and print.
}
}
Output:
Hello World 3
Hello World 1
Hello World 2
Note: Naming conventions not followed.
Let's assume below is the code snippet then how to kknow the number of constructors invoked?
private class First{
}
class Second extends First{
public Second(){
super();
}
}
public class DriverClass extends Second{
String class_name=null;
public DriverClass(){
class_name="DriverClass";
}
public static void main(String[] args){
new DriverClass();
}
}
There are at least four constructors invoked: DriverClass which in turn invokes Second which in turn invokes First and of course Object.
The program gives compile time error, because private class is can not be inheritable.
In the given program the class First is prefixed with "private" keyword.
So, in line "class Second extends First" gives compile time error
As DriverClass is not extending any of the classes only one constructor that is of default no-args constructor of DriverClass will be invoked.
Please explain the concept of static and dynamic binding in Java.
What I have grasped is that Static binding in Java occurs during compile time while dynamic binding occurs during Runtime, static binding uses Type (Class in Java) information for binding while dynamic binding uses Object to resolve binding.
This is the code for my understanding.
public class StaticBindingTest {
public static void main (String args[]) {
Collection c = new HashSet ();
StaticBindingTest et = new StaticBindingTest();
et.sort (c);
}
//overloaded method takes Collection argument
public Collection sort(Collection c) {
System.out.println ("Inside Collection sort method");
return c;
}
//another overloaded method which takes HashSet argument which is sub class
public Collection sort (HashSet hs){
System.out.println ("Inside HashSet sort method");
return hs;
}
}
and the output of the above program was inside the collection sort method
for dynamic binding...
public class DynamicBindingTest {
public static void main(String args[]) {
Vehicle vehicle = new Car(); //here Type is vehicle but object will be Car
vehicle.start(); //Car's start called because start() is overridden method
}
}
class Vehicle {
public void start() {
System.out.println("Inside start method of Vehicle");
}
}
class Car extends Vehicle {
#Override
public void start() {
System.out.println ("Inside start method of Car");
}
}
the output was inside the start method of Car. Please advise: Is this understanding correct and please advise some more examples. Thanks.
Static binding is used at compile time and is usually common with overloaded methods - the sort() methods in your example where the type of the argument(s) is used at compile time to resolve the method.
Dynamic binding (dynamic dispatch) is usually associated with polymorphism and overriding methods - the start() method in your example where the type of the receiver (vehicle) is used at runtime to resolve the method.
I think you have summarized it correctly and shams also correctly added more information for you. Just to add little more information for you first let me step back by stating that the association of method definition to the method call is known as binding. So, static binding as you pointed out correctly, is the binding that can be resolved at compile time by compiler (also known as early binding or static binding). On the other hand, dynamic bidding or late binding it means compiler is not able to resolve the call/binding at compile time (it happens at the run time). See below for some examples:
//static binding example
class Human{
....
}
class Boy extends Human{
public void walk(){
System.out.println("Boy walks");
}
public static void main( String args[]) {
Boy obj1 = new Boy();
obj1.walk();
}
}
//Overriding is a perfect example of Dynamic binding
package beginnersbook.com;
class Human{
public void walk()
{
System.out.println("Human walks");
}
}
class Boy extends Human{
public void walk(){
System.out.println("Boy walks");
}
public static void main( String args[]) {
//Reference is of parent class
Human myobj = new Boy();
myobj.walk();
}
}
source
I have an interface called Namable
public interface Namable { public String getName(); public void setName(String name); };
Several classes will implement this.
When I make code like this:
Namable foo = new X(); foo.getName();
(X is an implementing class)
I get the error:
java.lang.NoSuchMethodError: Namable.getName()Ljava/lang/String;
This is very strange to me and I'm wondering why this is happening, any thoughts?
Compilable example:
Namable class:
public interface Namable
{
public String getName();
}
Extending class X:
public class X extends java.util.ArrayList implements Namable
{
private String name;
public X()
{
this.name = "bar";
}
public String getName()
{
return name;
}
}
Testing class:
public class Test
{
public static void main()
{
Namable foo = new X();
foo.getName();
}
}
After running this, I get the same error. I am using BlueJ
I have run an example with the classes you have given here and it works as expected once the main method is changed to:
public static void main(String[] args)
However, as you are using BlueJ this may not be a problem (I remember BlueJ using a special mechanism to run classes).
Do you have another class Nameable in your classpath? Check the package import and make sure it is the interface you have defined. It appears the error is with your environment and not with the code.
You need to call
foo.getName()
not
X.getName()
You are trying to call a class (static) method that doesn't exist.
And it should be Namable foo = new X(); - your example code shouldn't even compile as shown.
Can you provide a SSCCE ?
Updated following corrections and SSCCE: Just a wild guess now, but does BlueJ define a Namable already, or do you have a Namable in another package that might be imported instead? What happens if you rename Namable to Namable2 throughout, in the example above?
As stated by DNA your post would be better with a SSCCE
My guess would be that maybe you could have missed a "static" keyword in main function
public static void main(String args[])
not
public void main(String args[])
Could be something a classpath problem too... Or a file name and class mismatch. Or something else.
When I ran your code snippet, the error shown is
Error: Main method not found in class Test, please define the main
method as: public static void main(String[] args)
Change your main method to
public static void main(String[] args)
I am not getting
java.lang.NoSuchMethodError: Namable.getName()Ljava/lang/String;
with your given code snippet.