java入门生,在多态的时候遇到一个程序小问题,望大神们能解答

weixin_39491178 2017-07-12 04:41:10



求问 为什么倒数两句代码

who.method(); 为什么打印的是Sub的method()方法而不是Base的
who.staticMethod();要是按上面道理,这个为什么又不是打印Sub类的staticMethod()
...全文
856 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
liu15073458538 2017-07-21
  • 打赏
  • 举报
回复
java中的许多对象(一般都是具有父子类关系的父类对象)在运行时都会出现两种类型:编译时类型和运行时类型。 例如:Person p = new Student();该变量的编译时类型时Person,运行时类型时Student。 说明一下编译时类型和运行时类型: Java的引用变量有两个类型,一个是编译时类型,一个是运行时类型。编译时类型由声明该变量时使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,会出现所谓的多态。 因为子类其实是一个特殊的父类。因此java允许把一个子类对象直接赋值给一个父类引用变量,无须任何类型转换,或者称为向上转型,由系统自动完成。 引用变量在编译阶段只能调用其编译时类型所具有的方法,但运行时则执行它运行时类型所具有的方法,因此,编写java代码时,引用变量只能调用声明该变量所用类里包含的方法。与方法不同的是,对象的属性则不具备多态性。通过引用变量来访问其包含的实例属性时,系统总是试图访问它编译时类所定义的属性,而不是它运行时所定义的属性。
Iterator君 2017-07-21
  • 打赏
  • 举报
回复
关键还是要理解这句: Base who = new Sub(); //也就是向上转型 将一个父类对象的引用 指向了子类对象 通俗来讲,对象名(例如who)好比一个瓶子,其中的饮料就是属性和方法 这里向上转型做的是就是将一个父类瓶里装进子类饮料 这时,java有趣精妙的设计,使我们只能从这个”假父类瓶“中喝到父类的饮料,以及被子类重写的方法(此处用的是动态绑定) 我的个人理解分享一下
hml1993 2017-07-18
  • 打赏
  • 举报
回复
用对象调用静态方法和静态变量,编译后底层会转换成类名调用
楚乔 2017-07-17
  • 打赏
  • 举报
回复
成员变量没有多态,而方法有多态。记住这句话就比较好理解了。 Base who = new Sub();//who被声明为Base类型,引用Sub实例 所以,who的成员变量是Base的,who的方法用的是子类重写的。 对于静态变量和静态方法都是属于类的,who是属于Base类的,所以who.staticVar和who.staticMethod()相当于Base.staticVar和Base.staticMethod(),一般不建议对象去调静态的东西,不信你看你的代码who.staticVar和who.staticMethod()在IDE里标了黄线。静态的东西建议类名去调用。
csdn2750 2017-07-15
  • 打赏
  • 举报
回复
先解析你说的第一个问题 who.method();  为什么打印的是Sub的method()方法而不是Base的 因为在Base who = new  Sub() 实际上是new的一个子类对象,本质上是一个sub,所以在调用method的时候,就近原则,他调用的是Sub的method方法,因而会出现你看到的现象 再解释你遇到的第二个问题 who.staticMethod();要是按上面道理,这个为什么又不是打印Sub类的staticMethod() 这个问题涉及到栈,堆和静态方法区三个内存空间 按照内存的先后顺序,首先 Base who这个被你定义的变量进入到栈内存中,然后对应Base 对象的静态属性、方法都会被加载到静态区及静态方法区,然后再在堆中new Sub对象,Sub对象指向栈内存中的who,然后对应加载Sub这个对象的静态属性、静态方法。在执行静态方法的过程中,因为静态方法是随着类的加载而加载的,你定义的是父类类型的变量,所以在栈中定义Base类的时候,就已经加载了父类的静态方法。所以在调用who.staticMethod()的时候,相当于是在调用Base.staticMethod(),因此打印出的效果就是你所看到的打印出父类内容的效果。
Antonio_zjn 2017-07-15
  • 打赏
  • 举报
回复
Base who= new Sub()是父类引用指向子类对象,说白了就是多态,你可以把who的类型当成Base类,但他比普通的Base who=new Base()方法多一个功能,就是当调用父类在子类中被重写的方法是,会展现子类的特性,也就是会调用子类的方法,但这只对被重写的方法有效,还有就是静态成员和方法是不能被继承的
戴小码 2017-07-12
  • 打赏
  • 举报
回复
对于成员变量,不存在覆盖这一说,具体底层代码实现机制,我也不太清楚。
戴小码 2017-07-12
  • 打赏
  • 举报
回复
第一点再补充下相当于父类发送method()这个消息给子类,动态绑定就相当于中介,他会明确知道该消息应该发送给哪个子类,并检查该子类是否对该消息做出了处理(是否覆盖了该方法),然后调用相应子类的方法对该消息进行处理。
唱响艾泽拉斯 2017-07-12
  • 打赏
  • 举报
回复
引用 4 楼 CodeLoveDancer的回复:
1.第一个问题:要解决这个问题首先得理解两个概念,向上转型和动态绑定。 首先理解向上转型,Who被向上转型为Base类型,所以会调用Base的方法,这也就是多态的缺点之一,会丢失子类拓展的方法,那么既然这样为什么程序还会调用子类的method()方法呢?这就是动态绑定,程序上会在运行期间判定对象的确切类型,当方法被覆盖后,会调用子类的方法。 2.静态方法属于类,不属于任何对象,因此不存在静态方法覆盖。 3.回答的不正确的地方,欢迎补充。
我想请教一下,成员变量为什么也是看父类的,原理上怎么解释的
唱响艾泽拉斯 2017-07-12
  • 打赏
  • 举报
回复
引用 3 楼 weixin_39491178的回复:
不太理解左边右边? 编译和运行又是什么回事
看等于号的左边和右边啊
戴小码 2017-07-12
  • 打赏
  • 举报
回复
1.第一个问题:要解决这个问题首先得理解两个概念,向上转型和动态绑定。 首先理解向上转型,Who被向上转型为Base类型,所以会调用Base的方法,这也就是多态的缺点之一,会丢失子类拓展的方法,那么既然这样为什么程序还会调用子类的method()方法呢?这就是动态绑定,程序上会在运行期间判定对象的确切类型,当方法被覆盖后,会调用子类的方法。 2.静态方法属于类,不属于任何对象,因此不存在静态方法覆盖。 3.回答的不正确的地方,欢迎补充。
weixin_39491178 2017-07-12
  • 打赏
  • 举报
回复
不太理解左边右边? 编译和运行又是什么回事
唱响艾泽拉斯 2017-07-12
  • 打赏
  • 举报
回复
新手,不过会一点。 多态的特点: 成员变量 --- 编译运行都看 = 左边 成员函数 --- 编译看 = 左边,运行看 = 右边 静态函数 --- 编译运行都看 = 左边 对号入座就懂啦
weixin_39491178 2017-07-12
  • 打赏
  • 举报
回复
求大神们解答

62,615

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧