移动承诺最低消费怎么取消谁有办法取消了,想改业务

7988人阅读
java(20)
Java方法调用的虚分派
JUN 2ND, 2013&|&
运行的结果为
Hello,world
Hello,le monde
Bonjour,le monde
前两行输出中,对于 intro 这个属性的访问,直接指向了父类中的变量,因为引用类型为父类。
第二行对于 target()的方法调用,则是指向了子类中的方法,虽然引用类型也为父类,但这是虚分派的结果,虚分派不管引用类型的,只查被调用对象的类型。
既然虚分派机制是从被调用对象本身的类开始查找,那么对于一个覆盖了父类中某方法的子类的对象,是无法调用父类中那个被覆盖的方法的吗?
在虚分派机制中这确实是不可以的。但却可以通过 invokespecial 实现。如下代码
public class FrenchGreeting extends Greeting {
String intro = &Bonjour&;
String target(){
return &le monde&;
public String func(){
return super.target();
public static void main(String[] args){
Greeting english = new Greeting();
FrenchGreeting french = new FrenchGreeting();
System.out.println(french.func());
func()就成功的调用了父类的方法 target(),虽然 target()已经被子类重写了。具体的调用细节,从字节码中可以看到:
ALOAD 0: this
INVOKESPECIAL Greeting.target() : String
其中使用了 invokespecial 指令,而不是施行虚分派策略的 invokevirtual 指令。
方法表(Method Table)
介绍了虚分派,接下来介绍是它的一种实现方式 – 方法表。类似于 C++的虚函数表 vtbl。
在有的 JVM 实现中,使用了方法表机制实现虚分派,而有时候,为了节省内存可能不采用方法表的实现。
不要被方法表这个名字迷惑,它并不是记录所有方法的表。它是为虚分派服务,不会记录用 invokestatic 调用的静态方法和用 invokespecial 调用的构造函数和私有方法。
JVM 会在链接类的过程中,给类分配相应的方法表内存空间。每个类对应一个方法表。这些都是存在于 method area 区中的。这里与 C++略有不同,C++中每个对象的第一个指针就是指向了相应的虚函数表。而 Java 中每个对象索引到对应的类,在对应的类数据中对应一个方法表。(关于链接的更多信息,参见博文)
一种方法表的实现如下:
父类的方法比子类的方法先得到解析,即父类的方法相比子类的方法位于表的前列。
表中每项对应于一个方法,索引到实际方法的实现代码上。如果子类重写了父类中某个方法的代码,则该方法第一次出现的位置的索引更换到子类的实现代码上,而不会在方法表中出现新的项。
JVM 运行时,当代码索引到一个方法时,是根据它在方法表中的偏移量来实现访问的。(第一次执行到调用指令时,会执行解析,将符号索引替换为对应的直接索引)。
由于 invokevirtual 调用的方法在对应的类的方法表中都有固定的位置,直接索引的值可以用偏移量来表示。(符号索引解析的最终目的是完成直接索引:对象方法和对象变量的调用都是用偏移量来表示直接索引的)
invokeinterface 与 invokevirtual 的比较
当使用 invokeinterface 来调用方法时,由于不同的类可以实现同一 interface,我们无法确定在某个类中的 inteface 中的方法处在哪个位置。于是,也就无法解析 CONSTANT_intefaceMethodref-info 为直接索引,而必须每次都执行一次在 methodtable 中的搜索了。 所以,在这种实现中,通过 invokeinterface 访问方法比通过 invokevirtual 访问明显慢很多。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:337858次
积分:4471
积分:4471
排名:第5934名
原创:76篇
评论:158条
(1)(7)(3)(5)(14)(8)(1)(1)(2)(4)(2)(1)(2)(3)(16)(2)(3)(2)(4)(1)4段代码了解Java虚拟机虚方法和非虚方法的分派 - 博客频道 - CSDN.NET
一只海滩上的贝壳
在知识海洋的浅滩上汲取
分类:Java基础jvm
&& &先从2段代码聊起,
&&&代码1:
public class SuperTest {
public static void main(String[] args) {
new Sub().exampleMethod();
class Super {
private void interestingMethod() {
System.out.println("Super's interestingMethod");
void exampleMethod() {
interestingMethod();
class Sub extends Super {
void interestingMethod() {
System.out.println("Sub's interestingMethod");
&&&代码2:
public class SuperTest {
public static void main(String[] args) {
new Sub().exampleMethod();
class Super {
void interestingMethod() {
System.out.println("Super's interestingMethod");
void exampleMethod() {
interestingMethod();
class Sub extends Super {
void interestingMethod() {
System.out.println("Sub's interestingMethod");
&&&两段代码唯一一处不同的地方在于代码1的父类Super中的interestingMethod()是private void方法,而代码2中父类Super的interestingMethod()方法为void方法。
&&&那么,这两段代码的输出结果会一样吗?
&&&第一段代码的输出
Super's interestingMethod
&&&可以看到,第一段代码调用了父类的interestingMethod方法。
&&&第二段代码的输出:
Sub's interestingMethod
&&&第二段代码则调用了子类的interestingMethod方法。
&&&为什么会这样呢?这里需要说到Java里哪些是虚方法,哪些是非虚方法?虚方法又如何分派? 除了静态方法之外,声明为final或者private的实例方法是非虚方法。其它(其他非private方法)实例方法都是虚方法。
&&&虚方法和非虚方法的调用又有什么区别呢?在Java 虚拟机里面提供了5条方法调用字节码指令,分别如下:
invokestatic:调用静态方法
invokespecial:调用实例构造器方法,私有方法和父类方法等非虚方法
invokevirtual:调用所有的虚方法
invokeinterface:调用所有的接口方法
invokedynamic:动态运行解析
&&&对非虚方法的调用,程序在编译时,就可以唯一确定一个可调用的版本,且这个方法在运行期不可改变,那么会在类加载的解析阶段,通过前面的指令1,指令2将对这个方法的符号引用转为对应的直接引用,即转为直接引用方法。在Java中,静态方法,final方法和private方法 都是不可在子类中重写的。所以他们都是非虚方法。
&&&代码1中的非虚方法调用的指令(…表示省略了一些上下文)javap -verbose Sub
Constant pool:
#30 = Methodref
void exampleMethod();
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #30
LineNumberTable:
line 16: 0
line 17: 4
LocalVariableTable:
Ljvmbook/S
&&&代码2中的虚方法调用的指令(…表示省略了一些上下文)javap -verbose Sub
Constant pool:
#30 = Methodref
void exampleMethod();
1: invokevirtual #30
Super su =new Sub();
&&&invokevirtual的语义是要尝试做虚方法分派,而invokespecial不尝试做虚方法分派。 即invokevirtual调用的方法需要在运行时,根据目标对象的实际类型(代码2中为sub)来动态判断需要执行哪个方法。而invokespecial则只根据常量池中对应序号是哪个方法就执行哪个方法(即看静态类型)。
这里有特殊的一点是,final方法是使用invokevirtual指令来调用的,但是由于它无法被覆盖(不存在其他版本),所以也无须对方法接收者进行多态选择,或者说多态选择的结果是唯一的。在Java语言规范中明确说明了final方法是一种非虚方法
&&&总结起来就是,非虚方法调用只看对象的静态类型。
&&&那虚方法调用呢?结论是invokevirtual调用分2步,第一步在编译期先看方法调用者和参数的静态类型,第二步在运行期再看且只看方法调用者的动态类型。
&&&代码3:
public class StaticSDispatch {
static abstract class Human {}
static class Man extends Human {}
static class Woman extends Human {}
public void sayHello(Human guy) {
System.out.println("hello,guy");
public void sayHello(Man man) {
System.out.println("hello,man");
public void sayHello(Woman woman) {
System.out.println("hello,woman");
public static void main(String[] args) {
Human man = new Man();
Human women = new Woman();
StaticSDispatch sd = new StaticSDispatch();
sd.sayHello(man);
sd.sayHello(women);
&&&代码3的解释:
&&&首先sayHello()方法是虚方法,通过invokevirtual指令调用。因为在编译期只看方法接收者和参数的静态类型,所以在编译完成后,产生了2条指令,选择了sayHello(Human)作为调用目标,并把这个方法的符号引用写到了main()方法里面的2条invokevirtual指令的参数中。然后在运行期,动态选择sd的实际类型,因为在这sd没有父类,所以不用考虑。
还有另外一种解释是,所有依赖静态类型来定位方法执行版本的分派动作称为静态分派,静态分派的典型例子是方法重载。
&&&代码3的字节码:
public static void main(java.lang.String[]);
26: invokevirtual #51
29: aload_3
30: aload_2
31: invokevirtual #51
&&&代码4:
public class DynamicDispatch {
static abstract class Human{
protected abstract void sayHello();
static class Man extends Human{
protected void sayHello() {
System.out.println("man say hello");
static class Women extends Human {
protected void sayHello() {
System.out.println("woman say hello");
public static void main(String[] args) {
DynamicDispatch dy =new DynamicDispatch();
Human man =new Man();
Human women =new Women();
man.sayHello();
women.sayHello();
man =new Women();
man.sayHello();
man say hello
woman say hello
woman say hello
&&&代码4的解释:
&&&首先,sayHello()是虚方法,所以调用指令是invokevirtual.因为该方法没有参数,且方法接收者man/women的实际类型是Human,所以在编译期完成后会产生2条指令:Human.sayHello();然后在动态运行时,只根据方法
接收者的动态类型来动态分派,即会分派Man/Women的sayHello()方法
&&&根据4段代码总结起来就是几句话:
&&&1.非虚方法(所有static方法+final/private 方法)通过invokespecial指令调用(final虽然是非虚方法,但是通过invokevirtual调用),不尝试做虚方法分派,对这个非虚方法的符号引用将转为对应的直接引用,即转为直接引用方法,在编译完成时就确定唯一的调用方法。
&&&2.虚方法通过invokevirtual指令调用,且会有分派。具体先根据编译期时方法接收者和方法参数的静态类型来分派,再在运行期根据只根据方法接收者的实际类型来分派,即Java语言是静态多分派,动态单分派类型的语言。需要注意的是,在运行时,虚拟机只关心方法的实际接收者,不关心方法的参数,只根据方法接收者的实际类型来分派。
&&&那么问题来了:
public class Dispatcher {
static class QQ {
static class _360 {
public static class Father {
public void hardChoice(QQ qq) {
System.out.println("father choose qq");
public void hardChoice(_360 _360) {
System.out.println("father choose 360");
public static class Son extends Father{
public void hardChoice(QQ qq) {
System.out.println("son choose qq");
public void hardChoice(_360 _360) {
System.out.println("son choose 360");
public static void main(String[] args) {
Father father = new Father();
Father son = new Son();
father.hardChoice(new _360());
son.hardChoice(new QQ());
&&&这段代码又会输出什么?
&&&还有一点,为什么Java方法的重载是静态多分派?因为动态单分派时不关心方法的参数,只关心方法的接收者。而方法重载是方法名一样,方法参数不一样,也就导致无法做到动态分派。所以Java重载是静态多分派的原因是动态分派是单分派,不关心方法参数。
FoolishAndStupid
排名:千里之外
(3)(9)(2)(2)(11)(2)(1)(2)(5)(1)(1)(2)(1)java里面有虚方法么_java吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:610,199贴子:
java里面有虚方法么收藏
南昌java教育机构选甲骨文培训,0基础,0学费入学,毕业包薪资,3个月入门到精通,先就业后付款,不用担心学费.
java里没有 虚函数
java里面的虚方法就是普通方法。子类和c#一样,都可以重写
登录百度帐号推荐应用
为兴趣而生,贴吧更懂你。或里面到底有没有虚函数?
全部答案(共6个回答)
类的非static成员函数都是“虚”的
C与C++的区别
C是一个结构化语言,如谭老爷子所说:它的重点在于算法和数据结构。C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理...
简单地说,虚函数就是在类的继承中可以被改写函数体(专业术语叫“重载”)的函数!
但是编译器在处理的时候还是按照函数编译的,内联实际上是不起作用的
因为虚函数是要为多态提供基础的,如果按照内联函数展开后就无法实现多态了。
你需要有个服务器,比如说tomcat之类的,将war包放到相应的目录下就可以,然后在地址栏里输入地址 端口号 项目入口
基本就可以
⊙﹏⊙b汗,下载是没问题的,能否成功安装就不得而知了。
大家还关注
tomcat 运行时找不到路径 装完了T...
确定举报此问题
举报原因(必选):
广告或垃圾信息
激进时政或意识形态话题
不雅词句或人身攻击
侵犯他人隐私
其它违法和不良信息
报告,这不是个问题
报告原因(必选):
这不是个问题
这个问题分类似乎错了
这个不是我熟悉的地区JAVA(22)
抽象方法是用abstract修饰的方法,只能声明不能实现,抽象方法必须被声明在抽象类里(反过来,抽象类里不一定要有抽象方法),抽象方法的的作用就是强制子类实现该抽象方法(如果子类不是抽象类的话)。
可以用对象引用调用的方法都可以称作实例方法,实例方法必须在对象实例化之后,通过对象引用来调用。
即不需要对象实例就可以调用的方法,也叫做类方法,可以通过类名直接调用。
可以被覆写的方法都可以称作虚方法,因此虚方法并不需要做特殊的声明,也可以理解为除了用static、final、private修饰之外的所有方法都是虚方法。
抽象类和接口的区别
1、抽象类可以有方法体,接口必须是方法声明。
2、可以把接口看成是更纯粹的抽象类。
3、他们都不可以被实例化,但可以完好的使用多态(好吧,这是相同点)。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:8753次
排名:千里之外
原创:72篇
(3)(1)(2)(10)(11)(46)

我要回帖

更多关于 移动最低消费能取消吗 的文章

 

随机推荐