A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 周世阳 中级黑马   /  2012-7-31 01:02  /  2831 人查看  /  9 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 周世阳 于 2012-8-1 18:35 编辑

又一个学院的问题实验后引申的一个静态方法问题,编写如下类

class A{
        public void method(){
                System.out.println("A.method");
        }
        
        public static void static_method(){
                System.out.println("A.static_method");
        }
}

public class B extends A{
        
        public static void static_method(){
                System.out.println("B.static_method");
        }
        
        public static void main (String [] args){
                A a = new B();
                B b = new B();
                a.method();
                a.static_method();
                b.method();
                b.static_method();
        }
}


得到结果
A.methodA.static_methodA.methodB.static_method

a和b都是同一个类型对象,为什么调用的静态方法不一样?

9 个回复

倒序浏览
静态方法是按"编译时期的类型"进行调用的,而不是按"运行时期的类型"进行调用的.所以是根据类型而不是对象掉用的. 非static方法,才是按"运行时期的类型"进行调用的.
回复 使用道具 举报
静态方法不存在覆盖的问题,可以用类名和对象调用
回复 使用道具 举报
在父类引用指向子类对象时,A  a = new B();  这时候a能调用的方法必须是父类A中拥有的,如果子类B中覆盖了就输出子类B中的方法。。如果子类B中没有覆盖就相当于输出父类A中的方法,而静态成员和静态方法都可以直接通过类名直接调用,不需实例化多想;
回复 使用道具 举报
本帖最后由 余清兰 于 2012-7-31 08:37 编辑

楼主,您问的是a和b都是同一个类型对象,为什么调用的静态方法不一样?
那你的代码误写错了,下面代码的红字地方应该是a.static_method();
public static void main (String [] args){
                A a = new B();
                B b = new B();
                a.method();
                A.static_method(); //这个代码改为a.static_method();               
                b.method();
                b.static_method();
        }
分析如下:A a = new B();这个是父类的引用指向了自己的子类对象,是多态的体现。虽然跟b指向的是同一个类型对象,但是b是本类引用指向本类对象。
在多态中,静态成员函数的特点是无论编译和运行,都参考左边。这也称为静态绑定。
也就是说类一加载,方法就跟类绑定在一起了,跟着类走。所以就算新建对象用a.static_method();来调用静态方法,
走的还是引用型变量所属的类,这里也就是走的父类静态方法,所以无论编译和运行时期都参考左边。
B b = new B();而这个是本类引用指向本类对象。调用的就是本类的静态方法,静态方法是跟着类走的。

记住如下结论:
在多态中(父类引用指向子类对象的时候)非静态成员函数的特点:
在编译时期:参阅引用型变量所属的类中是否有调用的方法,如果有,编译通过,如果没有,
编译失败。
在运行时期:参阅对象所属的类中是否有调用的方法。
总结:成员函数在多态调用时,编译看左边,运行看右边。
在多态中,成员变量的特点:
无论编译和运行,都参考左边(引用型变量所属的类)。
在多态中,静态成员函数的特点:
无论编译和运行,都参考左边。


评分

参与人数 1技术分 +1 收起 理由
韦念欣 + 1 赞一个!

查看全部评分

回复 使用道具 举报
本帖最后由 黑马-王言龙 于 2012-7-31 11:31 编辑

1、一般的方法,编译看左边,运行看右边。
       你这个例子的类B继承了类A,而B没有覆盖A的method()方法;调用a.method()时,因为new的是类B,所以会去找类B的method()方法,所以只找到从类A继承来的method()方法。

2、静态方法只能覆盖静态方法,编译运行都看左边。
回复 使用道具 举报
余清兰 发表于 2012-7-31 08:22
楼主,您问的是a和b都是同一个类型对象,为什么调用的静态方法不一样?
那你的代码误写错了,下面代码的红 ...

sorry  小写a写成大写  thanks  大概看懂了
回复 使用道具 举报
邱成 中级黑马 2012-7-31 10:51:11
8#
下面是总结的一些静态的知识,希望对你米有帮助:
static: 关键字,是一个修饰符,用于修饰成员(成员变量和成员函数)。
特点:
1,想要实现对象中的共性数据的对象共享,可以将这个数据进行静态修饰。
2,被静态修饰的成员,可以直接被类名所调用。也就是说,静态的成员多了一种调用方式。类名.静态方式。
3,静态随着类的加载而加载,而且优先于对象存在。
弊端:
1,有些数据是对象特有的数据,是不可以被静态修饰的。因为那样的话,特有数据会变成对象的共享数据。这样对事物的描述就出了问题。所以,在定义静态时,必须要明确,这个数据是否是被对象所共享的。
2,静态方法只能访问静态成员,不可以访问非静态成员。
因为静态方法加载时,优先于对象存在,所以没有办法访问对象中的成员。
3,静态方法中不能使用this,super关键字。
因为this代表对象,而静态在时,有可能没有对象,所以this无法使用。
4,主函数是静态的。
什么时候定义静态成员呢?或者说:定义成员时,到底需不需要被静态修饰呢?
成员分两种:
1,成员变量。(数据共享时静态化)
该成员变量的数据是否是所有对象都一样:
如果是,那么该变量需要被静态修饰,因为是共享的数据。
如果不是,那么就说这是对象的特有数据,要存储到对象中。
2,成员函数。(方法中没有调用特有数据时就定义成静态)
        如果判断成员函数是否需要被静态修饰呢?
        只要参考,该函数内是否访问了对象中的特有数据:
        如果有访问特有数据,那方法不能被静态修饰。
        如果没有访问过特有数据,那么这个方法需要被静态修饰。
成员变量和静态变量的区别:
1,成员变量所属于对象,所以也称为实例变量。
静态变量所属于类,所以也称为类变量。
2,成员变量存在于堆内存中。
静态变量存在于方法区中。
3,成员变量随着对象创建而存在,随着对象被回收而消失。
静态变量随着类的加载而存在,随着类的消失而消失。
4,成员变量只能被对象所调用。
静态变量可以被对象调用,也可以被类名调用。
所以,成员变量可以称为对象的特有数据,静态变量称为对象的共享数据。
静态的注意:静态的生命周期很长。
回复 使用道具 举报
王峰 中级黑马 2012-7-31 16:46:33
9#
//为什么调用的静态方法不同呐,我给你的注释是这样的,你可以看下我的注释细细琢磨下,希望给你有帮助
class A{
        public void method(){
                System.out.println("A.method");
        }
        
        public static void static_method(){
                System.out.println("A.static_method");
        }
}

public class B extends A{
        
        public static void static_method(){
                System.out.println("B.static_method");
        }
        
        public static void main (String [] args){
                A a = new B();
                B b = new B();
//(1): 这里a的类型被声明为类A,又因为method的方法只在父类A中实现,所以肯定调用父类中的method方法,子类中没有该方法,
                a.method();
   //(2):这里a的类型被声明为类A,而调用的方法为静态方法,这个静态方法父类和子类都实现了,但是a的类型为A,所以调用父类的静态方法,也可以写成A.static_method()
     //如果这里要让A调用子类的静态方法,可以用这种方法((B)a).static_method(),或者直接写成B.static_method();
                a.static_method();
    //(3): 原因同(1),这里理所当然的也调用父类中的method方法
                b.method();
        //(4): 因为b的类型为子类B,又它的应用类型为B,所以调用子类中的静态方法
                b.static_method();
        }
}
回复 使用道具 举报
静态方法不能重写,你用那个类调用就调用哪个类的静态方法,如果子类没有定义该静态方法,就会调用父类的静态方法
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马