精华内容
下载资源
问答
  • 虚方法

    2019-10-04 07:33:50
    1. 若一个实例方法的声明中含有virtual修饰符,则称该方法为虚方法。若其中没用virtual修饰符,则称该方法为非虚方法。 实例 2. 创建一个虚方法和一个非虚方法,然后通过另一个类继承,并比较他们的调用结果 代码...

    1. 若一个实例方法的声明中含有virtual修饰符,则称该方法为虚方法。若其中没用virtual修饰符,则称该方法为非虚方法。

    实例

    2. 创建一个虚方法和一个非虚方法,然后通过另一个类继承,并比较他们的调用结果

    代码实例:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    namespace _8._4虚方法
    {
    //新建一个class类
    class class1
    {
    //默认的方法被指定为私有的,只能在当前的类中访问,需要在其他类中访问,就需要将其指定为public:
    //public访问权限最高,只要在项目内部都可以进行访问
    //virtual 关键字必须位于void关键字之前
    public virtual void virtualMethod() //因为虚方法能够在派生类中进行重写
    {
    Console.WriteLine("这是一个虚方法");
    }
    public void noVirtualMethod()
    {
    Console.WriteLine("这是一个非虚方法");
    }
    }
    class class2 : class1 //将class2 继承class1
    {
    public override void virtualMethod()   //重写必须类型完全统一
    {
    Console.WriteLine("这是一个新写的方法");
    }
    public new void nonVirtualMethod()
    {
    Console.WriteLine("这是一个新的方法");
    }
    }
    class Program
    {
    static void Main(string[] args)
    {
    class1 c1 = new class1();
    c1.virtualMethod();
    c1.noVirtualMethod();

    class2 c2 = new class2();
    c2.virtualMethod();
    c2.nonVirtualMethod();

    Console.ReadKey();
    }
    }
    }

    3.  非虚方法的实现是一成不变的:无论该方法是在声明它的类的实例上调用还是在派生类的实例上调用,实现均相同。与此相反,虚方法的实现可以由派生类取代,取代所继承的虚方法的实现的过程称为重写(override)该方法。在虚方法调用中,该调用所涉及的哪个实例的运行时类型确定了要被调用的究竟是该方法的哪一种实现,在非虚方法调用中,相关的实例的编译时类型时决定性因素

    转载于:https://www.cnblogs.com/wangjinya/p/9649155.html

    展开全文
  • 虚方法与非虚方法

    2020-07-13 11:15:33
    虚方法: 如果方法在编译期就确定了具体的调用版本,这个版本在运行时是不可变的,这样的方法称为非虚方法; 静态方法、私有方法、final方法、实例构造器、父类方法都是非虚方法虚方法: 不是非虚方法的...

    非虚方法:

    如果方法在编译期就确定了具体的调用版本,这个版本在运行时是不可变的,这样的方法称为非虚方法

    静态方法、私有方法、final方法、实例构造器、父类方法都是非虚方法;

    虚方法:

    不是非虚方法的方法,都是虚方法;

    调用指令:

    虚拟机中提供了以下几条方法调用指令:

    普通调用指令:

    1、invokestatic:调用静态方法,解析阶段确定唯一方法版本;

    2、invokespecial:调用<init>方法、私有及父类方法,解析阶段确定唯一方法版本;

    3、invokevirtual:调用所有虚方法;

    4、invokeinterface:调用接口方法;

    动态调用指令:

    5、invokedynamic:动态解析出需要调用的方法,然后执行;

    前4条指令固化在虚拟机内部,方法的调用执行不可人为干预,而invokedynamic命令则支持由用户确定方法版本。其中invoke static和invokespecial指令调用的方法称为非虚方法,其余的(final修饰的除外)称为虚方法。

    • JVM字节码指令集一直比较稳定,一直到Java7中才增加了一个invokedynamic指令,这是Java为了实现【动态类型语言】支持而做的一种改进。
    • 但是在Java7中并没有提供直接生成invokedynamic指令的方法,需要借助ASM这种底层字节码工具来产生invokedynamic指令。直到Java8的Lambda表达式的出现,invokedynamic指令的生成,在Java中才有了直接的生成方式;
    • Java7中增加的动态语言类型支持的本质是对Java虚拟机规范的修改,而不是对Java语言规则的修改,这一块相对来讲比较复杂,增加了虚拟机中方法的调用。最直接的受益者就是运行在Java平台的动态语言的编译期。
    展开全文
  • 虚方法&非虚方法

    千次阅读 2016-11-15 09:21:39
    虚方法:只能被invokestatic和invokespecial指令调用的方法,称为虚方法,常见的虚方法有:静态方法、私有方法、实例构造器、父类方法四种。 虚方法:除非虚方法以外的其它方法。 注意:被final修饰的方法,虽然是...

    非虚方法:只能被invokestatic和invokespecial指令调用的方法,称为非虚方法,常见的非虚方法有:静态方法、私有方法、实例构造器、父类方法四种。

    虚方法:除非虚方法以外的其它方法。

    注意:被final修饰的方法,虽然是invokevirtual指令调用,但依然为非虚方法,代码如下:


    Java代码:


    public class User {
    
        private Long userId;
    
        public User() {
        }
    
        public User(Long userId) {
            this.userId = userId;
        }
    
    
    }


    public class SuperClass {
    
    
        public void superMethod(){
    
        }
    
    }


    public class InvokeMethods extends SuperClass {
    
        public static void main(String[] args) {
            InvokeMethods finalMethodTest = new InvokeMethods();
            //调用被final修饰的方法
            finalMethodTest.finalMethod();
            //调用被static修饰的方法
            InvokeMethods.staticMethod();
            //调用被private修饰的方法
            finalMethodTest.privateMethod();
            //调用父类方法
            finalMethodTest.superMethod();
            //调用构造器
            User user = new User();
        }
    
        public final void finalMethod(){
    
        }
    
        public static void staticMethod(){
    
        }
    
        private void privateMethod(){
    
        }
    
    }



    字节码:


    // class version 52.0 (52)
    // access flags 0x21
    public class demo/InvokeMethods extends demo/SuperClass  {
    
      // compiled from: InvokeMethods.java
    
      // access flags 0x1
      public <init>()V
       L0
        LINENUMBER 6 L0
        ALOAD 0
        INVOKESPECIAL demo/SuperClass.<init> ()V
        RETURN
       L1
        LOCALVARIABLE this Ldemo/InvokeMethods; L0 L1 0
        MAXSTACK = 1
        MAXLOCALS = 1
    
      // access flags 0x9
      public static main([Ljava/lang/String;)V
       L0
        LINENUMBER 9 L0
        NEW demo/InvokeMethods
        DUP
        INVOKESPECIAL demo/InvokeMethods.<init> ()V
        ASTORE 1
       L1
        LINENUMBER 11 L1
        ALOAD 1
        INVOKEVIRTUAL demo/InvokeMethods.finalMethod ()V //final方法的调用
       L2
        LINENUMBER 13 L2
        INVOKESTATIC demo/InvokeMethods.staticMethod ()V //静态方法调用
       L3
        LINENUMBER 15 L3
        ALOAD 1
        INVOKESPECIAL demo/InvokeMethods.privateMethod ()V //私有方法调用
       L4
        LINENUMBER 17 L4
        ALOAD 1
        INVOKEVIRTUAL demo/InvokeMethods.superMethod ()V //调用父类方法
       L5
        LINENUMBER 19 L5
        NEW demo/User
        DUP
        INVOKESPECIAL demo/User.<init> ()V //调用类构造器
        ASTORE 2
       L6
        LINENUMBER 20 L6
        RETURN
       L7
        LOCALVARIABLE args [Ljava/lang/String; L0 L7 0
        LOCALVARIABLE finalMethodTest Ldemo/InvokeMethods; L1 L7 1
        LOCALVARIABLE user Ldemo/User; L6 L7 2
        MAXSTACK = 2
        MAXLOCALS = 3
    
      // access flags 0x11
      public final finalMethod()V
       L0
        LINENUMBER 24 L0
        RETURN
       L1
        LOCALVARIABLE this Ldemo/InvokeMethods; L0 L1 0
        MAXSTACK = 0
        MAXLOCALS = 1
    
      // access flags 0x9
      public static staticMethod()V
       L0
        LINENUMBER 28 L0
        RETURN
        MAXSTACK = 0
        MAXLOCALS = 0
    
      // access flags 0x2
      private privateMethod()V
       L0
        LINENUMBER 32 L0
        RETURN
       L1
        LOCALVARIABLE this Ldemo/InvokeMethods; L0 L1 0
        MAXSTACK = 0
        MAXLOCALS = 1
    }
    


    展开全文
  • 虚方法和非虚方法 如果方法在编译期就确定了具体的调用版本,这个版本在运行时是不可变的。这样的方法称为非虚方法。 静态方法、私有方法、final方法、实例构造器、父类方法都是非虚方法。 其他方法称为虚方法。 ...

    虚方法和非虚方法

    • 如果方法在编译期就确定了具体的调用版本,这个版本在运行时是不可变的。这样的方法称为非虚方法
    • 静态方法、私有方法、final方法、实例构造器、父类方法都是非虚方法
    • 其他方法称为虚方法。

    子类对象的多态的使用前提

    • 类的继承关系
    • 方法的重写
      虚拟机中提供了以下几条方法调用指令:

    普通调用指令:

    • invokestatic:调用静态方法,解析阶段确定唯一方法版本
    • invokespecial:调用方法、私有及父类方法,解析阶段确定唯一方法版本
    • invokevirtual:调用所有虚方法
    • invokeinterface:调用接口方法
      动态调用指令:
    • invokedynamic:动态解析出需要调用的方法,然后执行

    invokednamic指令

    JVM字节码指令集一直比较稳定,一直到Java7中才增加了一个invokedynamic指令,这是Java为了实现动态类型语言】支持而做的一种改进。

    但是在Java7中并没有提供直接生成invokedynamic指令的方法,需要借助ASM这种底层字节码工具来产生invokedynamic指令。直到Java8的Lambda表达式的出现,invokedynamic指令的生成,在Java中才有了直接的生成方式。

    Java7中增加的动态语言类型支持的本质是对Java虚拟机规范的修改,而不是对Java语言规则的修改(修改的对象是java虚拟机,而不是java语言),这一块相对来讲比较复杂,增加了虚拟机中的方法调用,最直接的受益者就是运行在Java平台的动态语言的编译器。

    动态类型语言和静态类型语言

    动态类型语言和静态类型语言两者的区别就在于对类型的检查是在编译期还是在运行期,满足前者就是静态类型语言,反之是动态类型语言。

    说的再直白一点就是,静态类型语言是判断变量自身的类型信息;动态类型语言是判断变量值的类型信息,变量没有类型信息,变量值才有类型信息,这是动态语言的一个重要特征。

    Java:String info = “mogu blog”; (Java是静态类型语言的,会先编译就进行类型检查)

    JS:var name = “shkstart”; var name = 10; (运行时才进行检查)

    方法重写的本质

    Java 语言中方法重写的本质:
    - 找到操作数栈顶的第一个元素所执行的对象的实际类型,记作C。
    - 如果在类型C中找到与常量中的描述符合简单名称都相符的方法,则进行访问权限校验,如果通过则返回这个方法的直接引用,查找过程结束;如果不通过,则返回java.1ang.I1legalAccessError 异常。
    - 否则,按照继承关系从下往上依次对C的各个父类进行第2步的搜索和验证过程。
    - 如果始终没有找到合适的方法,则抛出java.1ang.AbstractMethodsrror异常。

    IllegalAccessError介绍
    程序试图访问或修改一个属性或调用一个方法,这个属性或方法,你没有权限访问。一般的,这个会引起编译器异常这个错误如果发生在运行时,就说明一个类发生了不兼容的改变

    方法的调用:虚方法表

    在面向对象的编程中,会很频繁的使用到动态分派,如果在每次动态分派的过程中都要重新在类的方法元数据中搜索合适的目标的话就可能影响到执行效率。因此,为了提高性能,JVM采用在类的方法区建立一个虚方法表 (virtual method table)(非虚方法不会出现在表中)来实现。使用索引表来代替查找。

    每个类中都有一个虚方法表,表中存放着各个方法的实际入口

    虚方法表是什么时候被创建的呢?

    虚方法表会在类加载的链接阶段被创建并开始初始化,类的变量初始值准备完成之后,JVM会把该类的方法表也初始化完毕。
    在这里插入图片描述
    如上图所示:如果类中重写了方法,那么调用的时候,就会直接在虚方法表中查找否则将会直接连接到Object的方法中

    展开全文
  • 虚方法 特点: &amp;amp;lt;1&amp;amp;gt;虚方法必须使用virtual修饰 &amp;amp;lt;2&amp;amp;gt;虚方法同抽象方法(adstract)一样使用override关键字重写 &amp;amp;lt;3&amp;amp;gt;...
  • C#虚方法

    2019-10-07 09:10:16
    虚方法与非虚方法的最大不同是,虚方法的实现可以由派生类所取代,这种取代是通过方法的重写实现的(以后再讲)虚方法的特点:虚方法前不允许有static,abstract,或override修饰符虚方法不能是私有的,因此不能使用...
  • 虚方法和抽象方法

    2019-10-01 04:23:34
    1、虚方法就是以virtual关键字修饰并在一个或多个派生类中实现的方法,子类重写的虚方法则以override关键字标记。虚方法调用,是在运行时确定根据其调用对象的类型来确定调用适当的覆写方法。.NET默认是非虚方法,...
  • 今天在云和学院学了很多,我这次只能先总结一下C#中的虚方法和抽象的运用。 理论: 虚方法: 用virtual修饰的方法叫做虚方法 虚方法可以在子类中通过override关键字来重写 常见的虚方法:ToString() Equals 抽象...
  • 【C#】虚方法与抽象方法

    热门讨论 2016-12-06 14:32:04
    虚方法
  • 当子类重写了父类的同名虚方法后。当我们让父类变量运行这个子类对象的时候。通过这个父类变量调用这个虚方法。调用的仍然是父类的。仅仅只是父类的虚方法被子类覆盖带哦了。所以实际上调用的是子类的 using System...
  • 虚方法与动态方法

    2019-09-23 13:59:05
    也有了很多新名称, 譬如: 静态方法、虚方法、动态方法、抽象方法、类方法、消息方法.先从虚方法与动态方法开始吧 //下面的类中就定义了两个虚方法(virtual)、两个动态方法(dynamic) TMyClass = class ...
  • c#虚方法

    2019-01-18 10:58:37
    不同的对象调用同一个方法,就会有不同的表现行为,父类的虚方法可以有方法体,在子类中可以调用父类的虚方法,父类将一类物体共有的属性抽象到虚方法中,子类在进行补充不同的行为。 父类的方法用virtual修饰 ...
  • 抽象方法和虚方法

    2018-08-10 14:34:00
    抽象方法和虚方法的比较 1:抽象方法只有声明没有实现内容(只有声明),虚方法必须要有方法体{} 2:抽象方法必须写在抽象类中 3:虚方法被重写或者被覆盖,使用base.方法()可以调用原来的方法 转载于:...
  • c#方法-虚方法

    2017-07-02 09:30:54
    (virtual method)通过关键字virtual来定义虚方法虚方法有点类似java中的抽象方法 但不同的是虚方法可以由方法体; class @class { public void method1() { Console.WriteLine("这是一个非虚方法"); } ...
  • 理解虚方法

    2019-08-11 21:43:32
    1、什么是虚方法?  考虑Animal* pa = new Dog(); pa表面类型是Animal,实际类型是Dog。可以理解为,pa说,我指向Animal,说法是对的。但是不具体,实际上,pa指向Dog。pa->Say()是虚方法,在编译期,编译器只...
  • 利用实例巧妙区分“抽象方法”和“虚方法”!

    千次阅读 多人点赞 2020-07-08 08:39:47
    最近在开发中,get到了虚方法这个名词,由于当时是在抽象类中用到,并且抽象方法和虚方法的使用有那么一丝丝的相近,之前也有了解过虚方法,但是对其概念比较模糊,所以今天在这里记录一下抽象方法和虚方法的区别。...
  • C# 虚方法

    2020-04-25 11:38:06
    把一个基类方法声明为 virtual, 就可以在任何派生类(子类)中重写该方法: public class Shape { public virtual void Draw() ...// 这里演示如何重写父类的虚方法 public class MyClass : Shape...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,412
精华内容 5,364
关键字:

虚方法