public class Test {
public static void main(String args[]){
Student s = new Student();
s.printPerson();
}
}
class Person{
private String getInfo(){
return "Person";
}
public void printPerson(){
System.out.println(getInfo());
}
}
class Student extends Person{
private String getInfo(){
return "Student";
}
}
The output is Person. I am confused with this result. In the main method, the reference type is Student. So when executing s.printPerson(), it should executes the method of Student. The key point is, in the public method inherited from superclass, which private method is invoked? And why?
I thought in s.printPerson(), it invokes getInfo() of Student. But it turns out not. The IDE tells me
private String getInfo(){
return "Student";
}
is never used.
Can anyone help me with this please?
In Java, private methods are not inherited.
A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass.
You cannot override getInfo by creating another getInfo method because it's not inherited. That's why your IDE gave you the "never used" warning, because nothing in Student uses it. The getInfo from Person is called, because it is available to Person's printPerson method, so Person is printed.
To override a method, it must not be private. You can make getInfo package-private (no access modifier), protected, or public. Then Student will be able to override it.
You use the private modifier. This modifier means that the method is only visible from within the class itself, not other classes, not even its sub- and superclasses. So when you call getInfo() from class Person, the only method visible is the method defined in the Person class. Effectively this means that private methods are not inherited in Java.
Try to change the private modifier to protected. Then the subclasses can see the method from the superclass, and so they can overide the method.
Related
public class Test{
public static void main(String[] args){
new Person().printPerson();
new Student().printPerson();
}
}
class Student extends Person{
private String getInfo(){
return"Student";
}
}
class Person{
private String getInfo(){
return "Person";
}
public void printPerson(){
System.out.println(getInfo());
}
}
I have some questions related to Student().printPerson() in the second line of the main function.
What I know is that: Java will first try to find the printPerson() in Student class. Since it couldn't find one, it will go to find the printPerson() in the superclass of Student which is Person. Now it executes the Person's printPerson() and here are my questions:
The printPerson() invokes another method getInfo(), so which getInfo will Java choose? Could you please explain with details?
Please explain how the modifiers of the getInfo() affect the output.
For your reference, If I remembered correctly. If the modifiers of both getInfo() are public, the output will be: Person Student If they are both private, the output will be Person Person
I’m on my mobile, so forgive me for grammar and typos.
Also disclaimer, I’m not heavy with java implementation so I am giving a generic explanation and I may have a few things incorrect with how java implements.
What happens is because of access level modifiers and restricting scope.
For your person class,
You have your two methods, public print and private getInfo.
You person class can see both the methods.
Your student class you have one method, private getInfo, and you extend the person class.
Because getInfo is private, it is only know to that class and nothing else. Because of this Java will not override the super (person) getInfo with the Student’s getInfo.
Because the method is not be overridden when Student.Print is being called, student.super.print is resolving to the student.super.getInfo method instead of student.getInfo.
This is a piece of code that I have that I'm testing right now, and I noticed that when I change public to private on the getInfo() method in Person, both Student().printPerson() & Person().printPerson() print out "Person". However, when it's public, "Student" is displayed. Can someone explain this? Why is it that the private modifier disallows access to the getInfo method from Student?
new Student().printPerson();
new Person().printPerson();
}
}
class Student extends Person {
public Student(){
System.out.println("student invoked") ;
}
public String getInfo() {
return "Student";
}
}
class Person {
public Person(){
System.out.println("person invoked");
}
private String getInfo() {
return "Person";
}
public void printPerson() {
System.out.println(getInfo());
}
public (or protected) method in Java are always virtual.
This means that if a derived class overrides the method, calls made through the base class will call the derived class (if the object is actually an instance of the derived class).
When your base method is public, this happens, and calling it from printPerson() calls the overriding derived version.
When it's private, it is not virtual, so calls from the base class always call the base version (since it doesn't know about the derived class' method).
This is the pac.java file
package P1;
public class pac {
int a;
public int b;
private int c;
protected int d;
public pac(){
a=1;
b=2;
c=3;
d=4;
}
public void test(){
System.out.println(a);
System.out.println(b);
System.out.println(c);
System.out.println(d);
}
}
This is other file pack1.java in different package
package P3;
class pac1 extends P1.pac{
public static void main(String args[]) {
pac1 ob=new pac1();
ob.test();
}
}
Question:
How is that possible that from the two files I have shown, the file P3\pac1.java creates an object which access the private variable of the class P1\pac.java?
In Java, a subclass object cannot access private variables (or methods) of any super class.
In your example, pac1 class only access public functionality of class pac, such as the public default constructor & the public method test(). Since the implemnetation of these methods is defined within the super class, both can access its private funvtionality - such as the private int c.
If you override these method in subclass however, the overriding methods implementation won't be able to access class pac private functionality.
HTH.
The method " test() " is inside of the class "pac". Therefore, when you create an instance of pac, the test method belongs to this instance, and can see and use all the variables.
If you had done this, it would have caused an error.
int mainC = ob.c;
the main method (where this is happening) cannot access the variable "c"
What I understand from your unalligned code is that you instantiate a public class and call a public method of it. This is perfectly fine, the test() method has access to variables. You can't access them directly from another method in pac1.
pac1.java only didn't access the private member c of pac.java. It only called the public method test of pac, and that method access the member of the same class.
If I understand you correctly, you are curious how calling ob.test () accesses the private members, despite ob being an object of the derived class. The reason is that whether a method has access is determined at compile time, not run time, and is determined by the location of the method. Your test method is declared in your pac class. So the compiler gives it access to all the private members of the pack class. Now, when it comes to executing the method, it transpires that the type of object your method is executing on is pac1. That does not matter.
This feature of object oriented languages is not a mistake. It makes it possible for the writer of a class to provide limited access to private members, by providing a method that gives only that limited access.
The statement pac1 ob=new pac1(); is creating a new object of Pac1 class and it is possible because it is public.
using ob.test() you are calling a method on the object itself. As private int c is member of the same class in which test() is defined, it can access it.
A private member variable or method is accessible throughout the class in which it is defined.
You can create the object of Pac1 because the class is public.
To clarify your doubt, you cannot access the private member outside the class like this ob.c in the main method.
Consider a very simple example. For a javabean, we make member as private and getter setters as public. We can access them using only getter and setter as they are public.
public class SomeClass{
private int someMember;
public int getSomeMember(){
return this.someMember;
}
}
Now from outside the class,suppose in your main method,
SomeClass someClass = new SomeClass();
someClass.someMember; // This is not possible as we are directly accessing private field
someClass.getSomeMember; // possible because `getSomeMember` is public and it belongs to `SomeClass` so can access private member `someMember`.
`
In Java, I can't create instances of abstract classes. So why doesn't eclipse scream about the following code?
public abstract class FooType {
private final int myvar;
public FooType() {
myvar = 1;
}
}
The code is fine, the final variable is initialized in the constructor of FooType.
You cannot instantiate FooType because of it being abstract. But if you create a non abstract subclass of FooType, the constructor will be called.
If you do not have an explicit call to super(...) in a constructor, the Java Compiler will add it automatically. Therefore it is ensured that a constructor of every class in the inheritance chain is called.
You can have constructors, methods, properties, everything in abstract classes that you can have in non-abstract classes as well. You just can't instantiate the class. So there is nothing wrong with this code.
In a deriving class you can call the constructor and set the final property:
public class Foo extends FooType
{
public Foo()
{
super(); // <-- Call constructor of FooType
}
}
if you don't specify a call to super(), it will be inserted anyway by the compiler.
You can create concrete sub-classes of FooType and they will all have a final field called myvar.
BTW: A public constructor in an abstract class is the same as a protected one as it can only be called from a sub-class.
What is your doubt?
Ok. See, an abstract class can have a constructor. It's always there-implicit or explicit. In fact when you create an object of a subclass of an abstract class, the first thing that the constructor of the subclass does is call the constructor of its abstract superclass by using super(). It is just understood, that's why you don't have to write super() explicitly unless you use parameterized constructors. Every class even if it is abstract, has an implicit constructor which you cannot see. It is called unless you create some constructor of your own. so long you created abstract classes without creating any custom constructor in it, so you didn't know about the existence of the implicit constructor.
You definitely can declare final variable in abstract class as long as you assign value to it either in the constructor or in declaration. The example that guy gave makes no sense.
No you can't declare final variables inside an Abstract class.
Check Below example.
public abstract class AbstractEx {
final int x=10;
public abstract void AbstractEx();
}
public class newClass extends AbstractEx{
public void AbstractEx(){
System.out.println("abc");
}
}
public class declareClass{
public static void main(String[] args) {
AbstractEx obj = new newClass ();
obj.AbstractEx();
// System.out.println(x);
}
}
This code runs correct and produce output as
abc
But if we remove comment symbol of
System.out.println(x);
it will produce error.
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).