public class Test
{
public static void main(String[] args)
{
A a = new B();//父类引用创建子类对象,这里是多态。
a.m();
a.n();
}
}
class A
{
public void m()
{
System.out.println("父类非静态方法!");
}
public static void n()
{
System.out.println("父类静态方法!");
}
}
class B extends A
{
public void m()//重写了父类非静态方法。
{
System.out.println("子类非静态方法!");
}
public static void n()//重写了父类静态方法。
{
System.out.println("子类静态方法!");
}
}
考虑到某些小白可能面向对象的基础不好,我尽可能详细的说一下:(实际上本贴就是为小白开的)
程序的内容是两个类A和B,B继承A,并且重写了A中的两个方法,分别为静态方法和非静态方法,然后用父类A创建子类对象B的对象,再调用两个方法。
首先,创建一个对象,A a = new B(); 这里大致可以分为两个部分,对象和引用。
B()是类B的对象或者叫类B的实例,存放在堆内存中,里面存放的数据是一个实例化后的类B,本程序当中,就是类B中的两个方法;
a是由类A创建的一个类类型的变量,存放在栈内存中,该变量是一个对象引用,指向堆内存中的对象B(),变量a中存放的数据就是对象B()在堆内存中的地址。
类中的普通成员方法分为两种,静态方法和非静态方法。
非静态方法必须用对象或者叫实例来调用,所以也叫实例方法,调用的方式是由该实例的引用来调用,比如 a.m();
静态方法可以用实例的引用来调用,比如a.n(); 因为静态元素是唯一的,所以也可以省略掉创建实例的过程,直接用类名来调用,比如A.n();
程序中容易让人迷惑的地方就是子类B把父类A中的静态方法和非静态方法全都重写了,那么,究竟会调用父类的方法还是子类的方法呢?
A a = new B();
因为创建对象的时候使用了多态,所以a既是A定义的引用变量,又是B的实例引用。
根据上面静态方法和非静态方法的区别,非静态方法必须用实例来调用,而这里只有一个实例,那就是B(),所以a调用的非静态方法是子类B中的。
而静态方法,如果用类名直接调用的话就一目了然了,但是它是由引用调用的,所以要看这个引用是哪个类定义的,a是A定义的,就调用A中的静态方法,如果是B定义的,当然就调用B中的静态方法。
所以,调用元素的时候(不仅仅是方法,变量也是),比如a.n();
如果n是静态的,要先看是谁定义的a,一看是A定义的,就要看看A类中有没有定义n,如果有,就是它了,等号后面是谁的对象都没有关系了,子类重写也没用,如果A类中没有n,再去看后面的实例是谁的,一看是B的,那调用的就肯定是B中的n了。
如果n是非静态的,就不要管n是谁定义的了,直接看后面的实例是谁的,一看是B的,那就调用B的n就对了,因为非静态的元素一定是实例引用调用的。如果B中没有方法n,那就一定是从父类继承来的。如果A和B中都有声明相同的方法n,那就是重写了。