When I change this code into Member m1 = new Member (); It works perfectly. Why it does not work for Super class reference? Please can someone explain?
public class Family {
String Surname = "Richard";
String Address = "No:10, High Street,Colombo";
}
public class Member extends Family{
String Name;
int age;
public void Details() {
System.out.println("full Name ="+ Name +" "+ Surname);
System.out.println("Age =" +age);
System.out.println("Address =" + Address);
}
public static void main(String[] args) {
Member m1 = new Family ();
m1.Name="Anne";
m1.age=24;
m1.Details();
}
You don't have a super class reference. You are having a subclass reference holding a reference to a super class object, that is simply illegal.
Secondly, you need to defined the method you have in subclass also in super class, if you want to see polymorphism into effect. You can only invoke that method on super class reference, that is also defined in super class.
So, you basically need this: -
Family m1 = new Member();
and then define the details() method(Yes, method name should start with lowercase alphabets), in your Family class.
And now, you will get another compiler error, when you try to access the fields of Member. For that, it's better to use a 2-arg constructor in Member class, and from that constructor, invoke the 2-arg super constructor (you need to do this explicitly), or 0-arg super constructor (this is implicit)
public Member(String name, int age) {
this.name = name;
this.age = age;
}
And use this constructor to create the object. It will implicitly call the 0-arg super constructor to initialize it's fields with their default value. If you want to give them a value, you can use a 4-arg constructor in Member class, passing the 2-parameters for super class fields, and then invoke the super class 2-arg constructor from there.
I think, you should better start with a good tutorial, starting with learning Inheritance in general, the access specifiers, then move ahead with polymorphism.
Related
I was practicing dome Java OO principles, when I encountered with this. I create to POJOs and when trying to make objects from it, if an empty constructor isn't defined, it wont compile.
I find this weird because I used to do that and the JVM included a default one for me. Is it new in Java 7? Am I missing something?
Here is the sample code I made
public class Dog {
String name;
String race;
int age;
/*
public Dog() {
If this isn't included, it doesn't compile if I try to
create no-args objects.
}*/
public Dog (String _name) {
this.name = _name;
}
public Dog (String _name, String _race) {
this.name = _name;
this.race = _race;
}
public Dog (String _name, String _race, int _age) {
this.name = _name;
this.race = _race;
this.age = _age;
}
}
Using Dog newDog = new Dog(); will not work in your current code, because you have not defined it.
A default constructor will only be automatically generated if no other constructors are present.
You don't have to provide any constructors for your class, but you must be careful when doing this. The compiler automatically provides a no-argument, default constructor for any class without constructors. This default constructor will call the no-argument constructor of the superclass. In this situation, the compiler will complain if the superclass doesn't have a no-argument constructor so you must verify that it does. If your class has no explicit superclass, then it has an implicit superclass of Object, which does have a no-argument constructor.
Source: http://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
If you define constructors with arguments, you also have to define a default one with no arguments.
In this case, trying to create a new Dog (Dog d = new Dog()) can't be done because the constructor with no args is not defined.
"If a class defines an explicit constructor, it no longer has a default constructor to set the state of the objects.
If such a class requires a default constructor, its implementation must be provided. Any attempt to call the default constructor will be a compile time error if an explicit default constructor is not provided in such a case."
http://www.javabeginner.com/learn-java/java-constructors
I have 2 classes: Date and Person
Person has two attributes of Date class
Case 1
Date class is separate class from Person class. I have this piece of code working properly:
private String name;
private Date born;
private Date died; // null indicates still alive.
public Person(String initialName, int birthMonth, int birthDay,
int birthYear) {
// requirement from the instructor:
// **implement using the this() constructor**
this(initialName, new Date(birthMonth, birthDay, birthYear), null);
}
Case 2: Inner class (an assignment requirement)
I put the Date as the private inner class of Person
Now the above constructor code does not work anymore.
Here is the error message:
Description Resource Path Location Type
No enclosing instance of type Person is available due to some intermediate constructor invocation Person.java /Wk03_Ch10_FileIO_Ch13_Interfaces/wk03_Ch10_FileIO_Ch13_Inner_Classes line 43 Java Problem`
How do I solve the problem? I can do this:
Date dt = new Date(birthMonth, birthDay, birthYear);
Unfortunately this() has to be the first line in the constructor
Another work around is
public Person(String initialName, int birthMonth, int birthDay,
int birthYear) {
// implement using the this() constructor
this.name = initialName;
this.born = new Date(birthMonth, birthDay, birthYear);
this.died = null;
}
However the last piece of code does not satisfy my instructor requirement of using this() method inside the constructor.
You can't create inner member (non-static) classes within a call to another constructor. From JLS §8.8.7.1:
An explicit constructor invocation statement in a constructor body (sic: the call to this()) may not refer to any instance variables or instance methods or inner classes declared in this class or any superclass, or use this or super in any expression; otherwise, a compile-time error occurs.
The reason is that non-static inner classes may require access to the class while it's being constructed. For example:
public class OuterClass {
private String name;
private InnerClass inner;
public OuterClass(String name, InnerClass inner) {
this.name = name;
this.inner = inner;
}
public OuterClass(String name) {
this(name, new InnerClass()); // Will not compile
}
public class InnerClass {
public InnerClass() {
// Access to name is allowed since this inner class isn't static
System.out.println(name);
}
}
}
The major problem here is that when we construct the non-static inner class, it can access non-static members from its enclosing instance (the OuterClass, but the enclosing OuterClass hasn't yet made its call to super() and is therefore considered unsafe to access. In fact, if that code was allowed to compile, it would print null due to constructor invocation order. In short, the InnerClass would be created before the call to this.name = name, a similar concept to the information presented in this question.
The solution is to make InnerClass a static inner class and pass the name to it directly:
public class OuterClass {
private String name;
private InnerClass inner;
public OuterClass(String name, InnerClass inner) {
this.name = name;
this.inner = inner;
}
public OuterClass(String name) {
this(name, new InnerClass(name));
}
public static class InnerClass {
public InnerClass(String name) {
System.out.println(name);
}
}
}
InnerClass cannot access name from the OuterClass once it's declared static, so we have to pass it explicitly on construction now, but this is better since the initial code would have been broken anyway.
Edit:
Per your question:
What confused me is that I can create an object of a Date type in the Person's constructor, as long as it is not inside the this() method. I can do this: Date dt = new Date(birthMonth, birthDay, birthYear); What is the difference between the above and this(...., new Date(birthMonth, birthDay, birthYear), ...)?
The difference is that in the call outside of this(), all the calls to super() have taken place, they take place as part of this() because of implicit calls to super(), so the object has reached a point where it is considered okay to be accessed. Your Date instance can't access the Person class because there is no context for the Person and its fields yet, so the compiler doesn't allow it.
In short, once this() has been called, then at least the calls to super() have happened, which is the driving force behind this constraint, and also why overridable method calls are discouraged. If a method is overridden by a subclass and then called in the superclass' constructor, fields from the subclass can be accessed before the subclass has even been initialized, even resulting in null being returned for final fields. Basically, it's all about protecting yourself from accessing your class before a call to super() has been invoked.
While I would never create a Date class inside of a Person class (sounds like a bad idea from an application-modeling perspective!), you seem to have said that it is a requirement in some assignment.
If you are set up like this:
public class Person {
...
class Date {
...
}
}
Then inside methods of Person, you will need to invoke the Date constructor with:
this.new Date(...)
That is the syntax Java uses. You need an enclosing instance of type Person on which to create objects of the inner class. The thing about inner classes (whether they are member, local, or anonymous) is that each instance exists bound to an instance of the outer class. So if I had a person instance p, I could say:
p.new Date(...)
The big problem here though is that you cannot create dates in the Person constructor that use the about-to-be-created person! For example, this fails:
public Person() {
this(this.new Date());
}
because the value of this isn't ready for use in this way yet (although interestingly, you can sometimes use this inside constructors in other cases, such as storing it in arrays, for example).
Like you realized, making Date a static nested class is fine, because instances of static nested classes are not tied to any instances of the enclosing class, so this is the best solution. If you really have to have an inner class, you're not going to be able to pass a new date as an "argument" of a this() expression and have it bound to the person you are creating! Maybe that is the point of the assignment (is this a graduate class? :-))
What i know is, the compiler writes a default no argument constructor in the byte code. But if we write it ourselves, that constructor is called automatically. Is this phenomena a constructor overriding?
What you describe isn't overriding. If you don't specify a default constructor, the
compiler will create a default constructor. If it's a subclass, it will call
the default parent constructor(super()), it will also initialize all instance variables to
a default value determined by the type's default value(0 for numeric types, false for booleans, or null
for objects).
Overriding happens when a subclass has the same name, number/type of parameters, and
the same return type as an instance method of the superclass. In this case, the subclass
will override the superclass's method. Information on overriding here.
Constructors are not normal methods and they cannot be "overridden". Saying that a constructor can be overridden would imply that a superclass constructor would be visible and could be called to create an instance of a subclass. This isn't true... a subclass doesn't have any constructors by default (except a no-arg constructor if the class it extends has one). It has to explicitly declare any other constructors, and those constructors belong to it and not to its superclass, even if they take the same parameters that the superclass constructors take.
The stuff you mention about default no arg constructors is just an aspect of how constructors work and has nothing to do with overriding.
It is never possible. Constructor Overriding is never possible in Java.
This is because,
Constructor looks like a method but
name should be as class name and no
return value.
Overriding means what we have declared
in Super class, that exactly we have
to declare in Sub class it is called
Overriding. Super class name and Sub
class names are different.
If you trying to write Super class
Constructor in Sub class, then Sub
class will treat that as a method not
constructor because name should
not match with Sub class name. And it
will give an compilation error that
methods does not have return value. So
we should declare as void, then only
it will compile.
Have a look at the following code :
Class One
{
....
One() { // Super Class constructor
....
}
One(int a) { // Super Class Constructor Overloading
....
}
}
Class Two extends One
{
One() { // this is a method not constructor
..... // because name should not match with Class name
}
Two() { // sub class constructor
....
}
Two(int b) { // sub class constructor overloading
....
}
}
You can have many constructors as long as they take in different parameters. But the compiler putting a default constructor in is not called "constructor overriding".
Cannot override constructor. Constructor can be regarded as static, subclass cannot override its super constructor.
Of course, you could call protected-method in super class constructor, then overide it in subclass to change super class constructor. However, many persons suggest not to use the trick, in order to protect super class constructor behavior. For instance, FindBugs will warn you that a constructor calls a non-final method.
No it is not possible to override a constructor. If we try to do this then compiler error will come. And it is never possible in Java. Lets see the example. It will ask please write a return type o the method. means it will treat that overriden constructor as a method not as a constructor.
package com.sample.test;
class Animal{
public static void showMessage()
{
System.out.println("we are in Animal class");
}
}
class Dog extends Animal{
public void DogShow()
{
System.out.println("we are in Dog show class");
}
public static void showMessage()
{
System.out.println("we are in overriddn method of dog class");
}
}
public class AnimalTest {
public static void main(String [] args)
{
Animal animal = new Animal();
animal.showMessage();
Dog dog = new Dog();
dog.DogShow();
Animal animal2 = new Dog();
animal2.showMessage();
}
}
But if we write it ourselves, that
constructor is called automatically.
That's not correct. The no-args constructor is called if you call it, and regardless of whether or not you wrote it yourself. It is also called automatically if you don't code an explicit super(...) call in a derived class.
None of this constitutes constructor overriding. There is no such thing in Java.
There is constructor overloading, i.e. providing different argument sets.
Because a constructor cannot be inherited in Java and Method Overriding requires inheritance. Therefore, it's not applicable.
Constructor overriding is not possible because of following reason.
Constructor name must be the same name of class name. In Inheritance practice you need to create two classes with different names hence two constructors must have different names. So constructor overriding is not possible and that thought not even make sense.
Your example is not an override. Overrides technically occur in a subclass, but in this example the contructor method is replaced in the original class.
Constructor looks like a method but name should be as class name and no return value.
Overriding means what we have declared in Super class, that exactly we have to declare in Sub class it is called Overriding. Super class name and Sub class names are different.
If you trying to write Super class Constructor in Sub class, then Sub class will treat that as a method not constructor because name should not match with Sub class name. And it will give an compilation error that methods does not have return value. So we should declare as void, then only it will compile.
It should also be noted that you can't override the constructor in the subclass with the constructor of the superclass's name. The rule of OOPS tells that a constructor should have name as its class name. If we try to override the superclass constructor it will be seen as an unknown method without a return type.
While others have pointed out it is not possible to override constructors syntactically, I would like to also point out, it would be conceptually bad to do so. Say the superclass is a dog object, and the subclass is a Husky object. The dog object has properties such as "4 legs", "sharp nose", if "override" means erasing dog and replacing it with Husky then Husky would be missing these properties and be a broken object. Husky never had those properties and simply inherited them from dog.
On the other hand, if you intend to give Husky everything that dog has, then conceptually you could "override" dog with Husky, but there would be no point in creating a class that is the same as dog, it's not practically an inherited class but a complete replacement.
method overriding in java is used to improve the recent code performance written previously .
some code like shows that here we are creating reference of base class and creating phyisical instance of the derived class.
in constructors overloading is possible.
InputStream fis=new FileInputStream("a.txt");
int size=fis.available();
size will return the total number of bytes possible in a.txt
so
I found this as a good example for this question:
class Publication {
private String title;
public Publication(String title) {
this.title = title;
}
public String getDetails() {
return "title=\"" + title + "\"";
}
}
class Newspaper extends Publication {
private String source;
public Newspaper(String title, String source) {
super(title);
this.source = source;
}
#Override
public String getDetails() {
return super.getDetails() + ", source=\"" + source + "\"";
}
}
class Article extends Publication {
private String author;
public Article(String title, String author) {
super(title);
this.author = author;
}
#Override
public String getDetails() {
return super.getDetails() + ", author=\"" + author + "\"";
}
}
class Announcement extends Publication {
private int daysToExpire;
public Announcement(String title, int daysToExpire) {
super(title);
this.daysToExpire = daysToExpire;
}
#Override
public String getDetails() {
return super.getDetails() + ", daysToExpire=" + daysToExpire;
}
}
It works fine when constructors are not defined, but gives errors if I define a parameterized constructor and not a default one and not passing any values while creating an object. I thought constructors are predefined.
Why do I need to define a default constructor if I've defined a parameterized constructor? Ain't default constructor predefined?
A default (no-argument) constructor is automatically created only when you do not define any constructor yourself.
If you need two constructors, one with arguments and one without, you need to manually define both.
While all the answers above are correct, it's a bit difficult for new-comers to wrap it in their head. I will try to answer the question anew for new-comers.
The problem that Ayush was facing was in trying to instantiate an Object for a class via a no-arg constructor. This class however has one or more parameterized constructor and this results in a compile time error.
For example, let us create a class Student with a single parameterized constructor and try to instantiate it via the no-arg constructor.
public class Student {
private String name;
private int rollNo;
public Student(String name, int rollNo) {
this.name = name;
this.rollNo = rollNo;
}
public static void main(String[] args) {
// The line below will cause a compile error.
Student s = new Student();
// Error will be "The constuctor Student() is undefined"
}
}
Woha! But when we remove the public Student(String name, int rollNo)
constructor all-together, the error is gone and the code compiles.
The reason behind this seeming anomaly lies in the fact that Java only
provides us with the default (no-arg) constructor when we do not define any
constructor for that class on our own.
For example, the following class is supplied with a default contructor:
public class Student {
private String name;
private int rollNo;
}
becomes:
public class Student {
private String name;
private int rollNo;
//Default constructor added by Java.
public Student() {
super();
}
}
In other words, the moment we define any parameterized constructor,
we must also define a no-arg constructor if we want to instantiate
the object of that class via a no-arg constructor.
Also in case of inheritance, a sub-class with no constructors; is supplied one
default constructor. This default constructor supplied by Java as above calls the super class's no-arg constructor. If it can't find one, then it will throw an error.
So yes it's always a good choice to define a no-arg/default constructor.
Ref : Oracle Java Tutorial
A no-arg constructor is automatically inserted for you, if you don't write one. This means, if you write a constructor with some parameters, it will be the only constructor you have, so you must pass some values for those parameters to create an instance of it.
This is exactly the expected behavior.
Java automatically generates a default (no arguments constructors) for classes that don't have any constructor.
If you define another constructor (with arguments), default constructor will not be generated. If you still want one, you need to define it yourself.
Whenever you class is complied, if compiler does not find any valid constructor in class (default,parametrized) only then it will substitute auto generated default constructor for your class.
You must have noticed, you can create objects without any default constructor defined in your class, there comes the concept of auto-generated default constructor.As whenever object is created,default constructor is called.
But, If you define Parametrized constructor in your class, that means you restrict the objects to have that parameters
Example:Every employee must have an id.
So,at that time, Compiler will not insert any default constructor there as there is valid constructor in a class.If you need default constructor too, you have to define by yourself.
There is also one curious case when you must define non argument constructor.
As the other wrote, if you don't specify default constructor - Java will do it for you. It's good to understand how "default generated by Java" constructor looks like.
In fact it calls constructor of the super class and this is fine.
Let's now imagine one case.
You are creating Vehicle class:
public class Vehicle {
private String name;
private String engine;
public Vehicle(String name, String engine) {
this.name = name;
this.engine = engine;
}
public String makeNoise(){
return "Noiseee";
}
}
As we can see Vehicle class has got only one defined 2 arguments constructor.
Now let's create Car class which inheritates from Vehicle class:
public class Car extends Vehicle {
#Override
public String makeNoise() {
return "Wrrrrrrr....";
} }
Maybe it looks strange but only one reason why wouldn't it compile is fact that Java cannot create default constructor for Car class which call super Vehicle class. Vehicle class doesn't have no argument constructor and it cannot be generated automatically while 2 arg constructor already exists.
I know that it's very rare case, but I found it as a interesting to know.
public abstract class Person {
private String name;
public Person(String name) {
this.name = name;
System.out.println("Person");
}
public String getName() {
return name;
}
abstract public String getDescription();
}
public class Student extends Person {
private String major;
public Student(String name, String major) {
super(name);
this.major = major;
}
public String getMajor() {
return major;
}
#Override
public String getDescription() {
return "student" + super.getName() + " having" + major;
}
}
public class PersonTest {
public static void main(String[] args) {
Person person = new Student("XYZ", "ABC");
System.out.println(person.getDescription());
}
}
Ques: We cannot create objects of abstract classes, then why Person Constructor has been invoked, even its an abstract class?
Because it's still a class and its constructor is invoked as a part of the object instantiation. The fact that it is abstract doesn't have anything to do with this.
Ques: We cannot create objects of
abstract classes, then why Person
Constructor has been invoked, even its
an abstract class?
If a class is declared abstract, no objects of that class can be created. That DOESNOT mean you cannot create objects of its subclasses.
You can have references(of type abstract class) refer to a subclass(non abstract) object.
Person person = new Student("XYZ",
"ABC");
And in order to construct a Student object, you need to have the "person" parts of the student initialized, thats what exactly the constructor of the abstract super class is called for.
What you can't do is to create an instance of an abstract class.
As a Student is 'partly' a Person super(...) initializes the 'Person part' of the student, it does not create a Person.
I hope you understand what I try to say
The constructor is just a method like others. And you are calling it explicitly from your child class' constructor with:
super(name);
The Person constructor is invoked from the Student class. From the Java tutorials
An abstract class is a class that is
declared abstract—it may or may not
include abstract methods. Abstract
classes cannot be instantiated, but
they can be subclassed.
An abstract class can have constructors - they cannot be invoked directly, but only as part of constructing a subclass instance, via a call to super() in the subclass constructor.
One cannot make an instance of an abstract class but subclasses can call super(name);. Even though it is a constructor, it is just another method.
The Abstract class is a part of your overall concrete class. An Abstract class is a class that is allowed to defer many parts to its concrete implementations but it must still initialize itself.
As such it has a constructor and as such the constructor with any parameters it requires to set itself up.
When you call the super(...) method from your Student class you are explicitly calling the constructor in the Person template class. The super() call must be in the first line of the Person constructor so if your person class wishes to override the defaults set up by the Person() constructor, then you have that option. But exactly one person constructor MUST be invoked when you extend a class (Abstract or concrete).