对 JAVA面试题解惑系列(三)——变量(属性)的覆盖 的质疑

上次看了这篇文章,原文地址:

JAVA面试题解惑系列(三)——变量(属性)的覆盖


这篇文章给出了很好的解疑方法,我也是跟着他来。。。下面我的文章将讲到:java中成员变量和方法的覆盖问题


对那篇文章中的提到的变量覆盖,我不同意。因此,在这里首先提出我的观点:


当子类继承父类的成员变量或方法同名时,


同名静态方法被隐藏,同名实例方法被覆盖;可见同名成员变量均被隐藏;同名不可见方法和成员变量不存在覆盖或隐藏问题,因为不可见。


首先来解释下隐藏覆盖的区别:隐藏是指在某种情况下仍可恢复,而覆盖则是指永远不可恢复。下面再来分别解释这三句话:


1、同名静态方法被隐藏,同名实例方法被覆盖


我们先看这段程序代码:

class ParentMethord{

// 静态方法
static void getClassName(){
System.out.println("static: "+ParentMethord.class.getName());
}

// 实例方法
void getName(){
System.out.println(ParentMethord.class.getName());
}
}

public class SubMethord extends ParentMethord{

// 重写父类静态方法
static void getClassName(){
System.out.println("static: "+SubMethord.class.getName());
}

// 重写父类实例方法
void getName(){
System.out.println(SubMethord.class.getName());
}


public static void main(String args[]){

ParentMethord parent= new SubMethord();
SubMethord sub=(SubMethord)parent;

parent.getClassName(); // 静态方法调用的仍然是父类的方法
parent.getName(); // 实例方法调用的是子类的方法

System.out.println();


sub.getClassName(); // 子类中调用的当然是子类的方法
sub.getName();
}
}

 

运行的结果为:

static: ParentMethord
SubMethord

 

static: SubMethord
SubMethord

 

从这里可以看出当把一个子类对象自动转型为父类对象(ParentMethord parent= new SubMethord(); )时,同名静态的方法只是被隐藏起来了,转型为父类后仍然可以调用;而同名实例方法是被覆盖,转型后调用的也是子类的方法,即方法的重写。

 

2、同名成员变量均被隐藏

 

下面来讨论这一点。这里所说的成员变量包括静态成员变量和实例成员变量,(包括final型的),当然均是指父类中对子类可见的变量。

 

看代码:

 

 class Parent{
 static String staticStr="父类静态变量";
 
 String str="父类实例变量";
}

public class SubVariable extends Parent{
 
 static String staticStr="子类静态变量";
 
 String str="子类实例变量";
 
 public static void main(String args[]){
  
  Parent parent= new SubVariable();
  SubVariable sub = (SubVariable)parent;

  
  System.out.println(parent.staticStr);
  System.out.println(parent.str);
  
  System.out.println();
  
  System.out.println(sub.staticStr);
  System.out.println(sub.str);
 }
}

 

运行结果为:

 

父类静态变量
父类实例变量

 

子类静态变量
子类实例变量

由此可见成员变量均只是被隐藏,当自动转型为父类时,仍然可见。final型的也一样,这里就不再讨论。

 

插入: 在这里还想扯到一个话题,以前总听胡总告诫:不要直接用来访问对象成员变量,而用方法来访问。从这里有所体会。因为子类对象和父类对象成员变量如果出现重名 ,当把一个子类对象当作父类使用时,访问的是父类对象的那个成员变量,就会出现数据的不一致;而用方法来方法问成员变量,由于方法被重写就不会出现这个问题。可以看如下代码:

 

class Parent{
 static String staticStr="父类静态变量";
 
 String str="父类实例变量";

 public static String getStaticStr() {
  return staticStr;
 }

 public String getStr() {
  return str;
 }

}

public class SubVariable extends Parent{
 
 static String staticStr="子类静态变量";
 
 String str="子类实例变量";
 
 public static String getStaticStr() {
  return staticStr;
 }

 public String getStr() {
  return str;
 }
 
 public static void main(String args[]){
  
  Parent parent= new SubVariable();
  SubVariable sub = (SubVariable)parent;
  
  
  // 方法调用
  System.out.println(parent.getStaticStr());
  System.out.println(parent.getStr());
  
  System.out.println();
  
  System.out.println(sub.getStaticStr());
  System.out.println(sub.getStr());
  
  
 }
}

 

运行的结果为:

父类静态变量
子类实例变量

 

子类静态变量
子类实例变量

 

这里看出,当用实例方法访问实例成员变量时,不会出现数据的不一致;当然静态方法访问静态成员变量仍然会出现数据的不一致,因为静态方法不会被重写

 

3、同名不可见方法和成员变量不存在覆盖或隐藏问题

 

这一点讨论的实际上是变量的修饰符问题。如果父类同名成员或方法对子类可见,即可符合前面两句话;如果父类成员或方法对子类不可见的话,既然看不到,其实就不存在同名问题。如果子类硬要访问父类中不可见成员变量或方法,就会出现非法,编译报错。所以大可不必去深究同名成员变量或方法的修饰符问题,而只是可见和不可见的问题。

 

对java中同名成员变量和方法的覆盖和隐藏问题就讨论到这里。欢迎大家发表自己的观点!

 

你可能感兴趣的:(java,虚拟机,qq,面试,idea)