示例:

public class ParentChildTest {
public static void main(String[] args) {
Parent parent=new Parent();
parent.printValue();
Child child=new Child();
child.printValue();

parent=child;
parent.printValue();

parent.myValue++;
parent.printValue();

((Child)parent).myValue++;
parent.printValue();

}
}

class Parent{
public int myValue=100;
public void printValue() {
System.out.println("Parent.printValue(),myValue="+myValue);
}
}
class Child extends Parent{
public int myValue=200;
public void printValue() {
System.out.println("Child.printValue(),myValue="+myValue);
}
}

 

总结:

     *如果子类与父类有相同的字段,则子类中的字段会代替或隐藏父类的字段,子类方法中访问的是子类中的字段(而不是父类中的字段)。如果子类方法确实想访问父类中被隐藏的同名字段,可以用super关键字来访问它。
     *如果子类被当作父类使用,则通过子类访问的字段是父类的!
牢记:
     * 在实际开发中,要避免在子类中定义与父类同名  的字段。不要自找麻烦!
 

 

附录:网络上摘取的一些代码和解释,可以帮助理解。

 

例1:

public class A {
    protected String a = "1";
    
    public String getA(){
        return this.a;
    }
}

public class B extends A {

    protected String a = "2"; 
    
//    public String getA(){
//        return a;
//    }
    
    public static void main(String[] args) {
        
        B x = new B();
        System.out.println(x.getA());
    }
}

输出的是1,父类的方法看到的变量是父类中的a。
如果B中也写一个getA方法,看到的a就是子类中的a了。

其实就是可见性的问题。
父类和子类的变量是同时存在的,即使是同名。
子类中看到的是子类的变量,父类中看到的是父类中的变量。
它们互相隐藏,而同名的方法则是实实在在的覆盖。

如A x = new B();
x是一个B,也是一个A,
那么调用方法时,是根据对象的实际类型调用的,
实际类型是B,所以永远调用子类的方法。

而访问成员变量就不同了,它是B时,访问的是子类的成员变量,
转型为A的话,访问的就是父类的成员变量了。

 

例2:

//Main.java
class c
{
  public int name = 12;
}
class d extends c
{
d()
{name =13;}
void d2()
{
System.out.println(super.name);
}
}
public class Main
{
  public static void main(String[]args)
  {
  d d1 = new d();
  System.out.println(d1.name);
d1.d2();
  }
}
//运行结果为:13,13
//Main1.java
class c
{
  public int name = 12;
}
class d extends c
{
int name =13;
void d2()
{
System.out.println(super.name);
}
}
public class Main
{
  public static void main(String[]args)
  {
  d d1 = new d();
  System.out.println(d1.name);
d1.d2();
  }
}
//运行结果为:13,12

 

首先要了解super这个关键字的意思,是调用父类的意思,
void d2()
{
System.out.println(super.name);
}这句话就是调用父类的name,虽然子类里面有一个name,但是并不是覆盖了父类里面的name,而只是父类的name隐藏起来了,使得直接调用子类里面的name显示的是子类定义的name。
第一个main。Java,不用说,子类没有定义name变量,并且父类里面的name变量不是private,子类可以直接继承name,这样子类和父类就共用一个name变量

如果父类定义了一个方法。子类重写了这个方法。那么这两个方法其实也是拥有各自的内存。

 

例3:

class Parent{

 

int i=10;// 父类变量

 

public void setI(int i){

this.i=i;

}

}

 

class Son extends Parent{

int i=10;// 子类与父类同名的变量

 

public static void main(String args[]){

Son son=new Son();

System.out.println("son.i="+son.i);

son.setI(100);

System.out.println("After setI(100) : son.i="+son.i);

 

Parent parent=son;

System.out.println("See son as Parent : son.i="+parent.i);

}

 

}

 

    在这段代码中,子类定义了一个父类中同名的成员变量int i,在父类中有一个对 i 赋值的方法setI(),而在子类中没有定义这个方法。当子类调用继承而来的setI()方法对成员变量i进行改变,直接打印son.i时,成员变量i然而却没有改变。当但当把son当作Parent类型来使用,再打印它的成员变量i时,输出的结果就对了,是setI()改变之后的值。

    java中类是分层次的,当子类和父类的定义同名时,父类变量被隐藏,父类的实例方法被重写,静态方法属于类级别的方法,在子类和父类中互不相碍。

 

 

例4:关于方法的重写Overriding和重载Overloading 。

方法的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父类与子类之间多态性的一种表现,重载Overloading是一个类中多态性的一种表现。Overloaded的方法是可以改变返回值的类型。也就是说,重载的返回值类型可以相同也可以不同。

1、重载(Overloading)

    a、方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在,具有不同的参数个数/类型。重载Overloading是一个类中多态性的一种表现。b、Java的方法重载,就是在类中可以创建多个方法,它们具有相同的名字,但具有不同的参数和不同的定义。调用方法时通过传递给它们的不同参数个数和参数类型来决定具体使用哪个方法,这就是多态性。

c、重载的时候,方法名要一样,但是参数类型和个数不一样,返回值类型可以相同也可以不相同。无法以返回型别作为重载函数的区分标准。

2、重写(Overriding)

    a、父类与子类之间的多态性,对父类的函数进行重新定义。如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写(Overriding)。在Java中子类可继承父类中的方法,而不需要重新编写相同的方法。但有时子类并不想原封不动地继承父类的方法,而是想作一定的修改,这就需要采用方法的重写。方法重写又称方法覆盖。b、若子类中的方法与父类中的某一方法具有相同的方法名、返回类型和参数表,则新方法将覆盖原有的方法。如需父类中原有的方法,可使用super关键字,该关键字引用了当前类的父类。

c、子类函数的访问修饰权限不能少于父类的