首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

深入探究JVM之方法调用及Lambda表达式实现原理

正文 解析 Java中方法的调用对应字节码有5条指令: invokestatic:用于调用静态方法。 invokespecial:用于调用实例构造器方法、私有方法和父类中的方法。...invokevirtual:用于调用所有的虚方法。 invokeinterface:用于调用接口方法,会在运行时再确定一个实现该接口的对象。...Java中有非虚方法和虚方法,前者是指在解析阶段可以确定的唯一的调用版本,如静态方法、构造器方法、父类方法(特指在子类中使用super调用,而不是在客户端使用对象引用调用)、私有方法(上述几种方法是使用...这里的解释看似合情合理,但仍然有一个问题,调用子类构造器首先会调用父类构造器,也就是说这时候子类还没有初始化完成,那为什么父类就可以调用子类的实例方法呢?...Lambda还分为捕获和非捕获,当从表达式外部获取了非静态的变量时,这个表达式就是捕获的,反之就是非捕获的,如下面两个方法:第一个方法就是非捕获的,第二个是捕获的。

72930

JVM精通面试系列 | 掘金技术征文

; 当遇到访问静态字段的指令时,初始化该静态字段所在的类; 子类的初始化会触发父类的初始化; 如果一个接口定义了 default 方法,那么直接实现或者间接实现该接口的类的初始化,会触发该接口的初始化;...如果这两个方法都是静态的,那么子类中的方法隐藏了父类中的方法。如果这两个方法都不是静态的,且都不是私有的,那么子类的方法重写了父类中的方法。 Java 虚拟机是怎么识别方法的。...invokespecial:用于调用私有实例方法、构造器,以及使用 super 关键字调用父类的实例方法或构造器,和所实现接口的默认方法。 invokevirtual:用于调用非私有实例方法。...方法表满足两个特质:其一,子类方法表中包含父类方法表中的所有方法;其二,子类方法在方法表中的索引值,与它所重写的父类方法的索引值相同。...如果一个字段占据 C 个字节,那么该字段的偏移量需要对齐至 NC。这里偏移量指的是字 段地址与对象的起始地址差值。 子类所继承字段的偏移量,需要与父类对应字段的偏移量保持一致。 虚共享是怎么回事?

81020
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    面霸篇:高频 Java 基础问题(核心卷一)

    通过使用继承我们能够非常方便地复用以前的代码,需要注意的是,过度使用继承,层级深就会导致代码可读性和可维护性变差。 关于继承如下 3 点请记住: 子类拥有父类非 private 的属性和方法。...子类可以拥有自己属性和方法,即子类可以对父类进行扩展。 子类可以用自己的方式实现父类的方法。(以后介绍)。...继承:在多态中必须存在有继承关系的子类和父类。 重写:子类对父类中某些方法进行重新定义,在调用这些方法时就会调用子类的方法。...向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备技能调用父类的方法和子类的方法。...重写:发生在父子类中,方法名、参数列表必须相同,返回值小于等于父类,抛出的异常小于等于父类,访问修饰符大于等于父类(里氏代换原则);如果父类方法访问修饰符为 private 则子类中就不是重写。

    40011

    C++ 万字长文第二篇---拿下字节面试

    如果构造函数是虚函数,则需要通过虚函数表来调用,而对象还没有构造出来,无法找到虚函数表。 从使用角度,虚函数主要用于信息不全的情况下,使子类重写的函数能得到对应的调用。...操作方法就是在 B 和 C 的继承处加上 virtual 修饰。 虚继承底层实现一般通过虚基类指针和虚基类表实现。每个虚继承的子类都有一个虚基类指针和一个虚基类表,虚表中记录了虚基类与本类的偏移地址。...} [capture]:捕获列表,可以捕获上下文的变量来供 lambda 函数使用 [var]:值传递的方式捕获 var [&var]:引用传递的方式捕获 var [=]:值传递的方式捕获父作用域的所有变量...如何控制一个类只能在堆或栈上创建对象 在 C++ 中创建对象的方法有两种,一种是静态建立,一个是动态建立。 静态建立由编译器为对象分配内存,通过调用构造函数实现。这种方法创建的对象会在栈上。...如果子类对象赋值给父类变量,则使用该变量只能访问子类的父类部分。 如果反过来,这个子类变量如果去访问它的扩充成员变量,就会访问不到,造成内存越界。

    1.4K20

    有效处理Java异常的三个原则,你知道吗?

    这四个类是泛化的,并不提供多少出错信息,虽然实例化这几个类是语法上合法的(如:new Throwable()),但是最好还是把它们当虚基类看,使用它们更加特化的子类。...这被称为"延迟捕获",下文就会谈到。 提早抛出 异常堆栈信息提供了导致异常出现的方法调用链的精确顺序,包括每个方法调用的类名,方法名,代码文件名甚至行数,以此来精确定位异常出现的现场。 ?...真正 的问题出在抛出NullPointerException处的数行之外,这之间有可能存在好几次方法的调用和类的销毁。...把异常处理的责任往调用链的上游传递的办法,就是在方法的throws子句声明异常。在声明可能抛出的异常时,注意越具体越好。这用于标识出调用你方法的程序需要知晓并且准备处理的异常类型。...然而声明它是为 了文档化我们的代码(这些异常也应该在方法的JavaDocs中标注出来)。 当 然,最终你的程序需要捕获异常,否则会意外终止。

    1.6K10

    JVM之栈

    这样的方法称为非虚方法 静态方法、私有方法、final方法、实例构造器、父类方法都是非虚方法 其他方法称为虚方法 虚方法和子类对象的多态对应,前提是1、类的继承关系 2、方法的重写 四条普通指令 invokestatic...:调用静态方法,解析阶段确定唯一方法版本 invokespecial:调用方法、私有及父类方法,解析阶段确定唯一方法版本 invokevirtual:调用所有虚方法 invokeinterface:调用接口方法...showFinal(); //invokespecial super.showCommon(); //invokevirtual //有可能子类会重写父类的...4.7、虚方法表 在面向对象的编程中,会很频繁的使用到动态分派,如果在每次动态分派的过程中都要重新在类的方法元数据中搜索合适的目标的话就可能影响到执行效率。...虚方法表会在类加载的链接阶段被创建并开始初始化,类的变量初始值准备完成之后,JVM会把该类的虚方法表也初始化完毕。

    9800

    C++异常

    ✈️C++异常 异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的直接或间接的调用者处理这个错误。 throw: 当问题出现时,程序会抛出一个异常。...这是通过使用 throw 关键字来完成的。 catch: 在您想要处理问题的地方,通过异常处理程序捕获异常.catch 关键字用于捕获异常,可以有多个catch进行捕获。...只需要在main函数中创建父类对象的引用,当子类中有错误抛出的时候,会返回到main函数的父类,父类指向子类,就完成了一次多态调用,调用子类重写的what()函数。...{ // 这里走了一个多态, 父类指针指向子类的对象,指向谁调用谁 cout << e.what() << endl; } catch (...上面这么多的异常看起来眼花缭乱的,我们依旧可以使用多态的方式,只需要在main函数内构建一个父类对象,当子类内部发生异常返回的main函数,此时父类指针指向子类,实现多态,完成对子类what()方法的调用

    9910

    C++相关基础知识总结笔记

    捕获列表,用于指定哪些变量可以被 lambda 函数捕获。...四大类型转换 static_cast(静态转换) 1、父类到子类的转换,( 进行下行转换,把基类的指针或引用转换为派生类表示)不保证安全。...动态绑定:当调用一个虚函数时,编译器会通过对象的虚表指针找到正确的函数地址并调用,而不是在编译时就确定调用哪个函数。这就是动态绑定。...虚表是动态绑定的,它是在创建时进行绑定的,需要注意的是如果在析构时,先调用子类析构,然后还原到父类的析构函数。...虚析构函数的作用,没有虚析构会导致什么后果 虚析构函数(Virtual Destructor)是一个虚函数,用于确保当通过基类指针删除派生类对象时,派生类的析构函数也能被正确调用,没有虚析构会导致资源泄露

    21330

    【C++进阶】C++11的认识与学习

    修饰类时,表示该类不可以被继承 修饰虚函数时,表示该虚函数不可以被重写 override 作用发生在编译时 override只能修饰子类的虚函数 用于显式地表明派生类中的函数是重写基类中的虚函数。...这可以确保派生类中的函数正确地重写了基类中的虚函数,并且可以避免一些程序错误。...如果派生类中的函数没有正确地重写基类中的虚函数,则编译器会发出警告 六.lambda表达式 语法:[capture-list] (parameters) mutable -> return-type {...[val],表示值传递方式捕获某个变量 [=],表示值传递方式捕获所有父作用域中的变量(包括this) [&var],表示引用传递捕捉变量var [&],表示引用传递捕捉所有父作用域中的变量(包括this...return 0; } 注意: 父作用域指包含lambda函数的语句块 捕捉列表不允许变量重复传递,否则就会导致编译错误 在块作用域以外的lambda函数捕捉列表必须为空 lambda表达式之间不能相互赋值

    16510

    c++11面试宝典(final,delete,deault,explicit,lambda表达式)

    这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情 c++11 1. final 作用: final在修饰类时,表示该类无法被继承 ​ 修饰父类的虚函数时,表示该虚函数无法被重写...注:只能修饰类和虚函数 2.override 作用: 修饰子类虚函数时,编译时编译器会自动检测该函数是否在父类中被重写。...注意: override只能修饰子类的虚函数 好处: 可以帮助我们更好的检查出是否在重写父类虚函数的过程中出来什么问题。...[var]:表示值传递方式捕捉变量var [=]:表示值传递方式捕获所有父作用域中的变量(包括this) [&var]:表示引用传递捕捉变量var [&]:表示引用传递捕捉所有父作用域中的变量(包括this...在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者非局部变量都 会导致编译报错。

    58620

    《逆袭进大厂》第三弹之C++提高篇79问79答

    继承的优点是子类可以重写父类的方法来方便地实现对父类的扩展。 继承的缺点有以下几点: ①:父类的内部细节对子类是可见的。...②:子类从父类继承的方法在编译时就确定下来了,所以无法在运行期间改变从父类继承的方法的行为。 ③:如果对父类的方法做了修改的话(比如增加了一个参数),则子类的方法必须做出相应的修改。...抽象类不能用于实例化对象,否则会报错。抽象类一般用于定义一些公有的方法。子类继承抽象类也必须实现其中的纯虚函数才能实例化对象。..._fun = _fB; //子类的对象调用子类的同名函数 _A* p2 = &_a; //定义一个父类指针指向父类的对象 p2->_fun(); //调用父类的同名函数 p2...= (_A*)&_b; //让父类指针指向子类的对象,由于类型不匹配所以要进行强转 p2->_fun(); //调用子类的同名函数 } 183、动态编译与静态编译 1) 静态编译,编译器在编译可执行文件时

    2.2K30

    十一、多态

    特性: 接口性:多态是超类通过方法签名,向子类提供一个共同的接口。 延迟绑定(动态绑定):调用方法时,在运行时再决定调用哪个类的方法。 替换性:多态对已存在具有继承关系的类进行扩展。...这样,当使用父类类型的引用指向子类对象时,就可以根据对象的实际类型调用相应的方法,从而提高代码的复用性。...,如果子类写了个和父类函数原型一样的函数,并且父类中的函数没有声明为虚函数,则子类会直接覆盖掉父类的函数 通过父类指针或引用执行子类对象时,会调用父类的函数 虚函数重写 必须发生于父类和子类之间...这可能导致资源泄漏或未定义行为,因为派生类可能分配了需要手动释放的资源(如动态分配的内存、文件句柄等)。 使用场景: 当通过基类指针删除派生类对象时,确保派生类的析构函数被调用。...模板方法模式:在模板方法模式中,抽象类定义了一个算法的骨架,将一些步骤延迟到子类中实现。纯虚函数用于定义这些必须由子类实现的步骤。

    10110

    面向对象编程基础2(干货)

    注意:为屏蔽父类中的那个方法,派生类中声明名称和类型、及函数名都要与父类的对应的方法相同,且声明这个方法的时候要用new关键字。 ? ?...3.虚方法和多态:面向对象编程中,都遵循一个原则,依赖导致原则。换句话说就是,程序要依赖于抽象类(pet),而不是依赖于具体类(Dog)如上图。...目的:统一提高效率,但是又存在子类差异性如何体现问题。 概念:虚方法--声明为virtual的方法即为虚方法,基类的虚方法可以在派生类中使用override进行重写。...调用顺序: ? ? ? 5.抽象方法和抽象类:解释一下,就是比虚方法更需虚的方法,为什么呢,虚方法里面可以有实现的代码块,但是抽象方法里面是不允许有的。关键字abstract。...(目的:使得对象获得最大化的扩展) 5.集合 动态数组,列表;字典;栈;队列 (目的:管理对象) 6.委托 委托;Lambda表达式;事件 -- (用于对象之间的通讯方式)

    1.1K20

    C++进阶:继承和多态

    单继承:一个子类继承一个父类的属性和方法 多继承:一个子类可以继承多个父类的属性和方法 什么是菱形继承呢? 类似于下图的关系就是菱形继承,菱形继承有什么特点呢?...由于多继承导致的重复继承同一个基类,使得相同的数据成员或方法被继承多次,从而产生多余的拷贝和不必要的资源占用。这种冗余性会导致效率低下和维护困难。...多态的主要类型包括编译时多态(静态多态)和运行时多态(动态多态)。 简单来说多态就是:就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会产生出不同的状态。...它允许基类指针或引用调用派生类的重载方法。 本篇主要以动态多态为主。 多态的定义以及实现 多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为。比如Student继承了 Person。...在继承中要构成多态的必要条件(缺一不可): 虚函数重写 父类指针或者引用进行调用虚函数 虚函数 class Person { public: virtual void BuyTicket() { cout

    9510

    【C++】异常,你了解了吗?

    在之前的C语言处理错误时,会通过assert和错误码的方式来解决,这导致了发生错误就会直接把程序关闭,或者当调用链较长时,就会一层一层的去确定错误码,降低效率,所以c++针对处理错误,出现了异常,一起来学习...C++异常概念   异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的 直接或间接的调用者处理这个错误。...catch: 在您想要处理问题的地方,通过异常处理程序捕获异常.catch 关键字用于捕获异 常,可以有多个catch进行捕获。...这样大家抛出的都是继承的派生类对象,捕获一个基类就可以了。 这就有了用子类抛异常,父类来捕获异常。什么意思呢?...这里其实也用到了多态的调用,通过父类的引用,来调用重写以后的虚函数,从而实现多态调用。 这就很好的解决了问题。 C++ 提供了一系列标准的异常 ,我们可以在程序中使用这些标准的异常。

    54020

    C++继承、虚函数、RTTI、友元类、异常处理

    成员函数属性 ==当使用private继承时,父类的所有public成员在当前子类中会变为private。...当使用protected继承时,父类的所有public成员在当前子类中会变为protected。==。 虚函数 c++中,被定义为虚函数的成员,能被子类重写,虚函数是用virtual修饰的函数。...因为引用类型是父类型,在调用普通方法时,仍是父类方法,只有调用虚方法时,使用了真正的子类方法。而指针类型也是与引用类型类似。 析构函数与继承 c++中子类析构函数结束会自动调用父类析构函数。...,因为delete是显示调用当前指针类型的析构函数处理,面对这种情况可以通过把父类的析构函数定义为虚函数,则delete调用时为调用虚函数,要去动态绑定会重新根据内存对象的类型选择子类的析构函数 class...,编译器会认为是覆盖,将对子类隐藏父类的同名方法,为了加强对这种情况的检查,可以通过在子类方法后面加上override关键字,代表是重写父类方法而不是覆盖,此时如果形参类型不一致,会导致编译失败。

    80510

    十三、异常、类型转换和 lambda

    noexcept noexcept 关键字用于指定一个函数不抛出异常。如果一个标记为 noexcept 的函数尝试抛出异常,程序将调用 std::terminate(),导致程序非正常退出。...它定义了一个名为what的虚成员函数,该函数返回一个表示异常的字符串描述。 std::bad_alloc:当new操作符无法分配足够的内存时抛出。它继承自std::exception。...全局状态(如errno) 在C(和兼容C的C++代码)中,errno是一个全局变量,用于报告函数调用的错误状态。当某些库函数(如I/O函数)失败时,它们会设置errno以指示具体的错误类型。...double d = 3.14; int i = static_cast(d); // 将 double 转换为 int 动态类型转换(dynamic_cast) dynamic_cast主要用于安全地将基类指针或引用转换为派生类指针或引用...mutable:一个可选的说明符,用于指定lambda表达式体内的代码可以修改被捕获的按值传递的变量的值。

    7510

    Java基础

    维护灵活性:单继承使得类的继承关系更稳定,这有助于减少代码的脆弱性。如果一个类具有多个父类,当其中一个父类的实现发生变化时,可能会影响所有子类,这可能导致不可预测的结果。...当调用一个被子类重写的方法时,根据实际对象的类型,会执行相应的子类方法,而不是父类的方法。动态绑定(Dynamic Binding):在运行时,根据对象的实际类型来确定调用哪个方法。...当使用父类的引用指向子类的对象时,编译器只能确定引用的静态类型,而具体调用的方法将在运行时确定。向上转型(Upcasting):通过将子类的对象赋值给父类的引用,实现了向上转型。...向下转型(Downcasting):当使用父类引用指向子类对象时,可以将父类引用转换为子类引用,以便调用子类特有的方法。这需要使用强制类型转换,并在转换之前进行类型检查,以避免类型转换异常。...类加载时机:类的加载是在运行时动态进行的,根据需要进行加载。当创建类的实例时。当访问类的静态变量或静态方法时。当使用反射机制操作类时。当类的父类未被加载时,需要先加载父类。

    23020

    封装、继承与多态究极详解(面试必问)

    每个对象都有一个虚函数表(vtable),用于支持多态(如果使用了虚函数)。当你创建一个子类对象时,它不仅包含自己的数据成员,还会包含父类的数据成员(如果父类有数据成员的话)。...扩展性:子类可以继承父类的功能,并在此基础上扩展或重写,满足更多需求。 缺点: 紧密耦合:继承会导致类之间的紧密耦合,子类对父类的依赖较强,修改父类可能影响子类的行为。...在OOP中,多态指的是同一个操作作用于不同类型的对象时,可以有不同的表现形式。最常见的多态形式是方法重写(overriding),即子类可以重写(覆盖)父类的方法。...多态的实现方式 父类指针或引用指向子类对象:当父类指针或引用指向子类对象时,调用虚函数会动态绑定到子类的实现上,而不是父类的实现。这样就实现了多态。...每个包含虚函数的类,在编译时会生成一个虚函数表,其中存储着类的所有虚函数指针。当通过父类指针调用虚函数时,程序会查找虚函数表,找到对应的子类实现并调用。

    12410

    .net 读书笔记

    继承的类称为子类、派生类,而被继承类称为父类、基类或超类。通过继承,使得子类具有父类的属性和方法,同时子类也可以通过加入新的属性和方法或者修改父类的属性和方法建立新的类层次。....NET 中对象的继承两个原则: 1.关注对象原则:调用子类还是父类的方法,取决于创建的对象是子类对象还是父类对象,而不是它的引用类型。...例如 Bird bird2 = new Chicken()时,我们关注的是其创建对象为 Chicken 类型,因此子类将继承父类的字段和方法,或者覆写父类的虚方法,而不用关注 bird2 的引用类型是否为...静态绑定在编译期就可以确定关联,一般是以方法重载来实现的;而动态绑定则在运行期通过检查虚拟方法表来确定动态关联覆写的方法,一般以继承和虚方法来实现。严格来讲,.NET 中并不存在静态绑定。...在.NET 中,默认情况下方法是非虚的,以 C#为例必须显式地通过 virtual 或者 abstract 标记为虚方法或者抽象方法,以便在子类中覆写父类方法。

    65010
    领券