[java] 反射和多态实现原理详解以及对比

Java基础-多态实现原理 多态是面向对象编程里面的概念,一个接口的多种实现不同的实现方式,即为多态这里的接口不应理解得太死板,比如在 Java 里面,继承一个类和实现一个接口本质上都是一种继承行为,因此都可以理解为多态的体现。从静态和动态的角度进行划分,多态可以分为编译时多态和运行时多态。编译时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的方法,编译之后会变成两个不同的方法。而运行时多态是动态的,是通过动态绑定来实现的,也就是大家通常所说的多态性,本篇博客主要讨论运行时多态。 阅读详情

Table of Contents

反射和多态

多态

什么是多态

java里多态的具体用法

多态的实现原理

反射

什么是反射

反射的实现原理

反射的应用

反射的弊端

反射相关类

反射应用实例

一些问题

private修饰的方法可以通过反射访问,那么private意义何在?

反射和多态的区别


反射和多态

事实上,反射和多态这两种技术并无直接联系,之所以把它们放在一起说,是因为,在Java技术体系中所提供的能够让我们在运行时识别对象和类的类型信息的方式,一共有两种:即反射和多态关键技术RTTI

RTTI,即run-Time Type Identification运行时类型判定,它的作用是在我们不知道某个对象的确切的类型信息时,即某个对象是哪个类的实例的时候,可以通过RTTI相关的机制帮助我们在编译时获取对象的类型信息,这其实也就是多态的实现基础。

反射机制允许我们在运行时发现和使用类的信息。因此多态和反射两者的最大的共同点在于,他们都是运行时获取程序信息的技术。反射技术对于java世界的众多框架以及特性都发挥着至关重要的作用,博主认为中文的基石一词能够准确形容反射技术的地位,理解反射技术对于学习java相关技术的背后原理非常重要,许多java世界里的特性的实现原理背后都离不开反射。

让我们先来看一下相对简单一点的多态的相关知识以及实现原理RTTI相关的知识。

多态

什么是多态

首先明确一点我们在这里只考虑运行时多态,而不考虑编译时多态(方法重载)。因此下列多态默认都是指运行时多态。

多态是面向对象编程里面的概念,一个接口的多种不同的实现方式,即为多态。注意这里的接口,不应理解得太死板,比如在java里面,继承一个类和实现一个接口本质上都是一种继承行为,因此都应该理解为多态的体现。

在计算机的世界里,尤其是编程的世界里,多态体现在:只有在运行的时候才知道引用变量所指向的具体实例对象。且有三个必要的条件:

  • 继承
  • 重写/实现
  • 父类引用指向子类对象

多态的概念来源于生活,生活中的很多现象都是多态的体现,例如打印机,打印功能可以打印黑白色也可以打印彩色。同一款汽车可以用2.0l排量也可以有1.0l的排量。

多态的技术带来的一个重要影响是:由于一个借口可能有多个实现,而每个实现之间的大小,规模,是不一样的。因此多态对内存的分配是有影响的,不同的实现会有不同的内存分配. 这一点与现实世界的多态例子相比就会非常有意思,第一,我们会发现软件里的多态是动态的多态,而现实世界里的多态大部分是一个预先设定好的多态体现,现实里的多态更多的类似于编译时多态,即方法重载,例如打印机的例子。

java里多态的具体用法

如上面我们提到的一样多态通常有两种实现方法:

  1. 子类继承父类(extends)
  2. 类实现接口(implements)

核心之处就在于对父类方法的改写或对接口方法的实现,以取得在运行时不同的执行效果。要使用多态,在声明对象时就应该遵循一条法则:声明的总是父类类型或接口类型,而创建的是实际类型. 

以ArrayList为例子,要使用多态的特性,要按照如下方式定义

List list = new ArrayList();

此外,在定义方法参数时也通常总是应该优先使用父类类型或接口类型,例如:

public void test(List list);

这样声明最大的好处在于它的灵活性,假如某一天ArrayList无法满足要求,我们希望用LinkedList来代替它,那么只需要在对象创建的地方把new ArrayList()改为new LinkedList即可,其它代码一概不用改动。

多态的实现原理与RTTI

RTTI,即Run-Time Type Identification运行时类型认定,通过运行时类型信息程序能够使用父类的指针或引用来检查这些指针或引用所指的对象的实际派生类型,是多态实现的技术基础。RTTI的功能主要是通过Class类文件实现的,更精确一点是通过Class类文件的方法表实现的。

Class类是"类的类"(class of classes)。如果说类是对象的抽象的话,那么Class类就是对类的抽象。Class对象就是用来创建一个类的所有的常规对象的。每个类都有一个Class对象,每当编写好并且编译了一个新的类,就会生成一个它对应的Class对象,被保存在一个与类同名的.class文件中。java虚拟机中的被称为类加载器的子系统,就是专门拿来做生成这个类的Class对象的工作的。关于类加载器,请参考这篇博客:[JVM]虚拟机类加载机制

每一个Class类的对象代表一个特定的类。请看如下代码

import java.lang.Class;

public class Test {
    public static void main(String[] args) throws ClassNotFoundException {
        Cycle unicycle = new Unicycle("Unicycle");
        Cycle.ride(unicycle);
        Class c1 = unicycle.getClass();//获取clas对象
        System.out.println(c1.getName());

        Cycle bicycle = new Bicycle("Bicycle");
        Cycle.ride(bicycle);
        Class c2 = Class.forName("basic.Bicycle");//获取clas对象
        System.out.println(c2.getName());

        Cycle tricycle = new Tricycle("Tricycle");
        Cycle.ride(tricycle);
        Class c3      = Tricycle.class;//获取clas对象
        System.out.println(c3.getName());
    }
}

//父类
class Cycle {
    private String name;

    public Cycle(String str) {
        name = str;
    }

    public static void ride(Cycle c) {
        System.out.println(c.name + "is riding");
    }
}

class Unicycle extends Cycle {
    private String name;

    public Unicycle(String str) {
        super(str);
        name = str;
    }
}

class Bicycle extends Cycle {
    private String name;

    public Bicycle(String str) {
        super(str);
        name = str;
    }
}

class Tricycle extends Cycle {
    private String name;

    public Tricycle(String str) {
        super(str);
        name = str;
    }
}

这是一个普通的多态的示例程序,但是我在每一处多态调用时,分别去获取了他们的class对象并打印出来。打印结果如下:

Unicycleis riding
basic.Unicycle
Bicycleis riding
basic.Bicycle
Tricycleis riding
basic.Tricycle

可以发现即使我们将对象的引用向上转型,对象所指向的Class类对象依然是实际的实现类。

Java中每个对象都有相应的Class类对象,因此,我们随时能通过Class对象知道某个对象“真正”所属的类。无论我们对引用进行怎样的类型转换,对象本身所对应的Class对象都是同一个。这意味着java在运行时的确能确定真正的实现类是哪一个。

下面从虚拟机运行时的角度来简要介绍多态的实现原理,这里以Java虚拟机规范的实现为例。

在JVM执行Java字节码时,类型信息被存放在方法区中,通常为了优化对象调用方法的速度,方法区的类型信息中增加一个指针,该指针指向一张记录该类方法入口的表(称为方法表),表中的每一项都是指向相应方法的指针。

方法表的构造如下:

由于Java的单继承机制,一个类只能继承一个父类,而所有的类又都继承自Object类。方法表中最先存放的是Object类的方法,接下来是该类的父类的方法,最后是该类本身的方法。方法表从上至下如下图所示

这里关键的地方在于,如果子类改写了父类的方法,那么子类和父类的那些同名方法共享一个方法表项,都被认作是父类的方法。如下所示

注意这里只有非私有的实例方法才会出现,并且静态方法也不会出现在这里,原因很容易理解:静态方法跟对象无关,可以将方法地址直接引用,而不像实例方法需要间接引用。

更深入地讲,静态方法是由虚拟机指令invokestatic调用的,私有方法和构造函数则是由invokespecial指令调用,只有被invokevirtual和invokeinterface指令调用的方法才会在方法表中出现。

由于以上方法的排列特性(Object——父类——子类),使得方法表的偏移量总是固定的。例如,对于任何类来说,其方法表中equals方法的偏移量总是一个定值,所有继承某父类的子类的方法表中,其父类所定义的方法的偏移量也总是一个定值。

前面说过,方法表中的表项都是指向该类对应方法的指针,这里就开始了多态的实现:

假设Class B是Class A的子类,并且B重写了A的方法method(),那么在B的方法表中,method()方法的指针指向的就是B的method方法入口而非类A的同名方法入口,也就是说,在虚拟机编译生成B的Class文件中的方法表时,就实现了多态,之后只需让对应的指令调用即可。

而对于A来说,它的方法表中的method方法则会指向其自身的method方法而非其父类的(这在类加载器载入该类时已经保证,同时JVM会保证总是能从对象引用指向正确的类型信息)。

结合方法指针偏移量是固定的以及指针总是指向实际类的方法域,我们不难发现多态的机制就在这里:

在调用方法时,实际上必须首先完成实例方法的符号引用解析,结果是该符号引用被解析为方法表的偏移量。虚拟机通过对象引用得到方法区中类型信息的入口,查询类的方法表,当将子类对象声明为父类类型时,形式上调用的是父类方法,此时虚拟机会从实际类的方法表(虽然声明的是父类,但是实际上这里的类型信息中存放的是子类的信息)中查找该方法名对应的指针(这里用“查找”实际上是不合适的,前面提到过,方法的偏移量是固定的,所以只需根据偏移量就能获得指针),进而就能指向实际类的方法了。

我们的故事还没有结束,事实上上面的过程仅仅是利用继承实现多态的内部机制,多态的另外一种实现方式:实现接口相比而言就更加复杂,原因在于,Java的单继承保证了类的线性关系,而接口可以同时实现多个,这样光凭偏移量就很难准确获得方法的指针。所以在JVM中,多态的实例方法调用实际上有两种指令:

invokevirtual指令用于调用声明为类的方法;

invokeinterface指令用于调用声明为接口的方法。

当使用invokeinterface指令调用方法时,就不能采用固定偏移量的办法,只能老老实实挨个找了(当然实际实现并不一定如此,JVM规范并没有规定究竟如何实现这种查找,不同的JVM实现可以有不同的优化算法来提高搜索效率)。我们不难看出,在性能上,调用接口引用的方法通常总是比调用类的引用的方法要慢。这也告诉我们,在类和接口之间优先选择接口作为设计并不总是正确的,当然设计问题不在本文探讨的范围之内,但显然具体问题具体分析仍然不失为更好的选择。

这就是多态的原理。总结起来说就是两点:

1.是方法表起了决定性作用,如果子类改写了父类的方法,那么子类和父类的那些同名方法共享一个方法表项,都被认作是父类的方法,因此可以写成父类引用指向子类对象的形式。

2.类和接口的多态实现不一样,类的方法表可以使用固定偏移,但接口只能挨个找,原因是接口的实现不是确定唯一的。

关于RTTI技术,典型的应用除了多态这样的类型转换,以及根据类生成Class对象这两种形式以外。还有一种常见的用法,就是关键字Instanceof。Instanceof的作用是返回一个布尔值,告诉我们一个对象是不是某个特定类的一个实例。例如:

if(x instanceof Dog){

}

即在判断x对象是不是Dog类的一个实例。

思考题:为什么使用多态创建一个对象引用之后,有的方法引用中不能调用?

反射

RTTI的作用是,当我们不知道一个对象的确切的类型的时候,可以通过RTTI来获取。但是这个功能存在一个限制:要通过RTTI获取的类型信息必须是在编译时已知的,这句话怎么理解,我们通过多态的例子来说明:

Animal dog = new Dog();

上述代码定义的引用是Animal类型,但是在编译时期,虚拟机可通过我们后面的new的代码获取到这个Animal的真正类型,这就是编译时已知,这里有个前提条件是代码里面其实是要给虚拟机留下这样的判断信息的。这事实上是一个限制。原因在于,我们在很多时候并不能在编译时获知某个对象所述的类。例如,我们有个api的功能是接收字段并解析它属于哪个类,但是传入的字段可能是我们定义好的多个类的其中一个,这个时候就没办法在编译时知道类型信息了。而只能在运行时通过传入的字段进行判断才有可能知道。

什么是反射

反射的定义如下:java程序在运行状态中,对于任意一个类,都能够在运行时知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

上面这段话需要非常仔细的理解,我想通过问问题的形式来帮助读者理解反射的概念。

问题1:什么是类的属性和方法?

这个问题比较愚蠢,甚至有侮辱人的智商之嫌,但是博主的本意肯定不是这样。这是一个很简单问题,假设我们有下面代码:

public class Test{
    
    private String s;

    public void doNothing(){
    
    }
}

那么,字符串s就是它的属性,doNothing就是它的方法

问题2:什么叫一个类的所有属性和方法

答:所有这个类中定义的成员变量,以及所有属于这个类的方法。

问题3:问题2中的所有属性和方法包含私有的吗?

答案是包含的

问题4:任何一个类,除了属性和方法,还有别的内容吗?

答案是没有了。注意,内部类不属于外部类,本质上是两个类。

问题5:什么叫获取一个方法,什么叫获取一个属性?

这是一个很好的问题,理解了这个问题之后也就不会觉得反射过于抽象了。java当中提供了专门的方法的抽象Method类和专门的属性的抽象Field类,以及专门的所有类的抽象Class类,并提供了一系列的方法,来帮助我们获取一个类的属性和方法。获取到的属性和方法,将以普通对象的方式存在。与我们自己写的类并无任何区别。下面是一个代码例子:

public class MethodClass {

    public static void main(String[] args) throws Exception {
        //1.获取Class对象
        Class xxxClass = Class.forName("com.XXX.XXX");
        //2.获取所有公有方法
        Method[] methodArray = xxxClass .getMethods();
        //3.获取字段
        Field[] fieldArray = xxxClass .getFields();
    }
}

 

反射的实现原理

Class类与java.lang.reflect库一起对反射的概念提供了技术支持。java.lang.reflect类库包含了Field类,Method类以及Constructor类。这些类用来表示未知类里对应的成员。Class类提供了获取getFields()、getMethods()和getConstructors()等方法,而这些方法的返回值类型就定义在java.lang.reflect当中。

如果不知道某个对象的确切类型(即list引用到底是ArrayList类型还是LinkedList类型),RTTI可以告诉你,但是有一个前提:这个类型在编译时必须已知,这样才能使用RTTI来识别它。

要想理解反射的原理,必须要结合类加载机。反射机制并没有什么神奇之处,当通过反射与一个未知类型的对象打交道时,JVM只是简单地检查这个对象,看它属于哪个特定的类,然后再通过拿到的某一个类的全限定名去找这个类的Class文件 。因此,那个类的.class对于JVM来说必须是可获取的,要么在本地机器上,要么从网络获取。所以对于RTTI和反射之间的真正区别只在于:

  • RTTI,编译器在编译时打开和检查.class文件
  • 反射,运行时打开和检查.class文件

对于反射机制而言.class文件在编译时是不可获取的,所以是在运行时获取和检查.class文件。

总结起来说就是,反射是通过Class类和java.lang.reflect类库一起支持而实现的,其中每一个Class类的对象都对应了一个类,这些信息在编译时期就已经被存在了.class文件里面了,Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的defineClass方法自动构造的。对于我们定义的每一个类,在虚拟机中都有一个应的Class对象。

那么在运行时期,无论是通过字面量还是forName方法获取Class对象,都是去根据这个类的全限定名(全限定名必须是唯一的,这也间接回答了为什么类名不能重复这个问题。)然后获取对应的Class对象

总结: java虚拟机帮我们生成了类的class对象,而通过类的全限定名,我们可以去获取这个类的字节码.class文件,然后再获取这个类对应的class对象,再通过class对象提供的方法结合类Method,Filed,Constructor,就能获取到这个类的所有相关信息. 获取到这些信息之后,就可以使用Constructor创建对象,用get和set方法读取和修改与Field对象相关的字段,用invoke方法调用与Method对象关联的方法。

反射的应用

反射机制非常重要,应用也非常之广泛。在使用反射时,我们的代码里面可以出现任何一个具体的构造器,字段信息,方法,但是却能动态的生成对象,调用他们的方法,这是一个非常通用的功能,由此带来的价值也是惊人的。反射比较出名的应用有:

1. Spring/Mybatis等框架,行内有一句这样的老话:反射机制是Java框架的基石。最经典的就是xml的配置模式。

2. JDBC 的数据库的连接

3. 动态生成对象,应用于工厂模式中. spring的bean容器也就是一个工厂

4. jdk动态代理

利用反射获取传入接口的实现类

5. 注解机制的实现

   利用反射可以获取每一个filed,Filed类提供了getDeclaredAnnotations方法以数组形式返回这个字段所有的注解....

6. 编辑器代码自动提示的实现

等等

反射的弊端

1.性能

反射包括了一些动态类型,所以 JVM 无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。我们应该避免在经常被 执行的代码或对性能要求很高的程序中使用反射。

2. 安全

使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如 Applet,那么这就是个问题了。

3. 内部暴露

由于反射允许代码执行一些在正常情况下不被允许的操作(比如访问私有的属性和方法),所以使用反射可能会导致意料之外的副作用--代码有功能上的错误,降低可移植性。反射代码破坏了抽象性,因此当平台发生改变的时候,代码的行为就有可能也随着变化。

4.丧失了编译时类型检查的好处,包括异常检查。如果程序企图用反射去调用不存在或者不可访问方法,在运行时将会失败。

5.从代码规范的角度来说,执行反射访问所需要的代码非常笨拙和冗长。这样的代码阅读起来很困难

核心反射机制最初是为了基于组件的应用创建工具而设计的,如spring。这类工具通常需要装载类,并且用反射功能找出它们支持哪些方法和构造器。这些工具允许用户交互式的构建访问这些类的应用程序。

反射功能只是在应用程序设计阶段被用到,通常,普通应用程序运行时不应该以反射方式访问对象。对于特定的复杂系统编程任务,它也许是非常必要的,但它也有一些缺点,如果你编写的程序必须要与编译时未知的类一起工作,如有可能就使用反射机制来实例化对象,而访问对象时则使用编译时已知的某个接口或者超类。

基于此,在effective java也总结了一条接口优先于反射机制的开发原则。

反射相关类

Class类

关于Class类请参考博客:[面向对象] 类与对象与Java里的Class类解析

Field类

即字段类,我们可以通过一个类的Class对象获取其Field类的对象,然后java当中提供了这个Field类来提供反射获取字段的相关信息,以及进行一些操作,比如set一个字段的值等功能。

Method类

即方法类,我们可以通过一个类的Class对象获取其Method类的一个实例对象,并且使用获得的Method对象去获取这个方法的相关信息,以及调用这个方法的功能。

以上三个类建议读者直接查看源代码,看看他们提供的方法,就会理解得更加清楚。

反射应用实例

下面的代码是使用反射获取方法的例子程序

model类

package com.dr.Reflection.getMethodByReflect;

public class Student {
    //**************成员方法***************//
    public void show1(String s) {
        System.out.println("调用了:公有的,String参数的show1(): s = " + s);
    }

    protected void show2() {
        System.out.println("调用了:受保护的,无参的show2()");
    }

    void show3() {
        System.out.println("调用了:默认的,无参的show3()");
    }

    private String show4(int age) {
        System.out.println("调用了,私有的,并且有返回值的,int参数的show4(): age = " + age);
        return "abcd";
    }
}

测试类

package com.dr.Reflection.getMethodByReflect;
import java.lang.reflect.Method;
/*
 * 获取成员方法并调用:
 *
 * 1.批量的:
 *      public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
 *      public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
 * 2.获取单个的:
 *      public Method getMethod(String name,Class<?>... parameterTypes):
 *                  参数:
 *                      name : 方法名;
 *                      Class ... : 形参的Class类型对象
 *      public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
 *
 *   调用方法:
 *      Method --> public Object invoke(Object obj,Object... args):
 *                  参数说明:
 *                  obj : 要调用方法的对象;
 *                  args:调用方式时所传递的实参;

):
 */
public class MethodClass {

    public static void main(String[] args) throws Exception {
        //1.获取Class对象
        Class stuClass = Class.forName("com.dr.Reflection.getMethodByReflect.Student");
        //2.获取所有公有方法
        System.out.println("***************获取所有的”公有“方法*******************");
        stuClass.getMethods();
        Method[] methodArray = stuClass.getMethods();
        for(Method m : methodArray){
            /*
            注意,这里虽然student类自身只写了一个public方法,但是由于java所有的类都继承于object类,
            因此object类中所有的public方法也会被打印出来
             */
            System.out.println(m);
        }
        System.out.println("***************获取所有的方法,包括私有的*******************");
        methodArray = stuClass.getDeclaredMethods();
        for(Method m : methodArray){//不包含父类的,仅仅是这个自身定义的方法
            System.out.println(m);
        }
        System.out.println("***************获取公有的show1()方法*******************");
        Method m = stuClass.getMethod("show1", String.class);//根据方法名称,以及参数,获取方法对象
        System.out.println(m);
        //实例化一个Student对象
        Object obj = stuClass.getConstructor().newInstance();
        m.invoke(obj, "刘德华");

        System.out.println("***************获取私有的show4()方法******************");
        m = stuClass.getDeclaredMethod("show4", int.class);
        System.out.println(m);
        m.setAccessible(true);//解除私有限定
        Object result = m.invoke(obj, 20);//需要两个参数,一个是要调用的对象(获取有反射),一个是实参
        System.out.println("返回值:" + result);


    }
}

一些问题

private修饰的方法可以通过反射访问,那么private意义何在?

答:首先java的private修饰符并不是为了安全性设计的,private并不是解决“安全”问题的。private想表达的不是“安全性”的意思,而是面向对象编程的封装概念,是一种编译器可以帮助我们在设计上的一个点。private的设计理念是对一个类的封装,而封装带来的好处是,在项目开发过程当中,修改一个类的private属性是不影响使用的,因为不存在对private代码的显式引用。反射技术主要是为实现一些开发工具以及框架服务。在实际的开发过程当中,我们应该尽量避免使用反射。而在使用反射时也要非常小心。

反射和多态的区别

  • 同为运行时获取信息,多态获取的信息仅仅在于确定方法应用所指向的实际对象。而反射在于获取一个类的所用信息。
  • 多态是一种面向对象语言的机制。而反射技术是java提供的专门用于动态获取类的信息的技术。
【Java -- 基础】多态的实现原理 java 面向对象之 多态 阅读详情

相关推荐

浅谈Java反射的实现原理

Java反射的实现原理

TellH的博客 8280

java中 instanceof 关键字详解及原理解析

需要注意的是,使用instanceof关键字检查一个对象的类型可能会降低代码的可读性和可维护性,因此应该尽可能避免在程序中过多地使用它。例如,我们可以使用instanceof关键字来检查一个对象是否是某个类或接口的实例,如果是,就可以调用相应的方法或进行相应的处理。如果object是class的实例,或者是class实现的接口的实例,或者是class数组的实例,那么instanceof关键字返回true;否则,返回false。其中,object是一个对象的引用,class可以是类、接口、数组类等类型。

兴趣是最好的老师,勤能补拙 4254

k8s 查看cpu使用率最高的pod

在 Kubernetes 中,可以使用命令查看 Pod 的资源使用情况,从而找到 CPU 使用率最高的 Pod。

u010674101的专栏 3344

Java反射和多态的一些理解

前言 最近看了几篇文章所以就总结一下自己的理解,个人理解有限,会有一些问题,仅记录一下。。。。 文章1:反射和多态的实现原理详解以及区别 文章2:java方法的虚分派和方法表 文章3:编译时多态、运行时多态 Java虚分派和方法表 虚分派 先看个例子: class A{ String msg = "A 的属性"; public void test(){ System.out.println("调用了 A 的方法"); } } class B extends A{

huiguifuhuo的博客 535

告别复杂配置!用GuidosToolbox 3.0做MSPA景观格局分析,从安装到出图全记录

本文详细介绍了如何使用GuidosToolbox 3.0进行MSPA景观格局分析,从安装配置到出图全流程。涵盖环境准备、数据预处理、参数设置、结果解读及可视化技巧,帮助用户快速掌握这一生态安全评估工具。特别针对安装教程中的常见问题提供解决方案,提升分析效率。

weixin_29248313的博客 489

【高清照片】深圳光博会看PCIe Over Fibre 实现方案

本文分析了PCIe over Fibre技术及其在数据中心的应用前景。该技术通过光纤延伸PCIe总线,解决了传统铜缆距离限制问题,支持跨机架资源池化。目前主要有两种实现方式:CDFP混合光缆方案和Retimer转接卡方案,各有优缺点。文章还探讨了CDFP接口的现状、低速信号传输解决方案,以及PCIe速率与光通信发展的对应关系。最后对比了PCIe光缆与以太网光缆的关键差异,指出PCIe光互连在协议透明度和边带信号处理上的特殊要求。随着标准推进,PCIe over Fibre将成为数据中心扩展高带宽、低时延互连

Saniffer的博客 1383

彻底了解instanceof的底层实现原理

一、作用: ①用于判断某个实例是否属于某构造函数 ②在继承关系中用来判断一个实例是否属于它的父类型或者祖先类型的实例 说白了,只要右边变量的 prototype 在左边变量的原型链上即可。因此,instanceof 在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype,如果查找失败,则会返回 false 二、语法 [对象] instanceof [构造函数] var obj = new Object() obj instanceof Object // true 三、

weixiao0111的博客 473

uniCloud云存储进阶:七牛云扩展存储从开通、绑定域名到批量上传的完整实战

本文详细介绍了uniCloud云存储进阶实践,重点讲解如何通过七牛云扩展存储实现从开通、绑定域名到批量上传的完整流程。内容涵盖成本优势分析、域名备案方案、SSL证书配置、多文件并发上传控制等实战技巧,并提供可直接复用的代码示例,帮助开发者高效构建内容社区类应用。

weixin_26985923的博客 468

Java技术——多态的实现原理

0.前言 多态在Java技术里有很重要的地位,在面试中也会经常被问到。 但是多态太抽象了,查了很多很多资料,连续几天断断续续的看,有时候看着看着就走神了。毕竟太抽象,哈哈~ 不过依然硬着头皮看下来了(也不知道看了多少遍),并且将很多资料里关于多态的知识进行了整理(添添加加删删减减了很久),便有了这篇文章。通过这篇文章相信可以帮助你更加深刻的理解多态。

关于Android开发的一些技术点总结 ╮( ̄▽ ̄”)╭ 3万+

【脑肿瘤分类与迁移学习技术】Swin UNETR:当 Swin Transformer 遇见 3D 医学图像分割——从黑盒到白盒的逐层拆解

医学图像分割的终极目标是让算法成为医生的可靠副手,而非黑箱替代品。理解 Swin UNETR 的每一层如何流动、每一个窗口如何移位、每一次拼接如何融合,不仅是为了调参,更是为了在临床场景中。

u012133341的博客 55

ComfyUI报错ModuleNotFoundError: No module named ‘comfy.options‘

好家伙,我一想我刚刚好像用了pip安装了comfy模块,不会是和ComfyUI自带的comfy模块产生冲突了吧。(3)还有的说是项目不是最新版,叫更新到最新版本的,好家伙,我报错之前根本没更新也没错,突然就报错的。(4)还有的说没有comfy.options这部分代码,叫自己去拉一个,我一看也有啊。我也不知道啥时候脑抽风去装这么个东西的,幸好我聪明机智,一眼就知道了。看把我气的,然后网上搜集各种资料,一个一个去试。

满目星辰 5156

反射和多态的实现原理详解以及区别

反射和多态事实上,反射和多态这两种技术并无直接联系,之所以把它们放在一起说,是因为,在Java技术体系中所提供的能够让我们在运行时识别对象和类的类型信息的方式,一共有两种:即反射和多态关键...

Java知音 710

AWR2243的等效相位中心与虚拟通道

在俯仰维方向上,不重合的虚拟通道有8个,排序为1:4,9:12。每个虚拟阵元之间的间隔为lambda/2。实际y轴方向虚拟阵列只跨越了8*lambda/2的距离。等效相位中心与虚拟通道类似,只是每个相位中心之间间隔为lambda/4,实际y轴方向等效相位中心只跨越了8*lambda/4=7.59mm的距离

qq_50974341的博客 1981

反射和多态的原理对比

Table of Contents 反射和多态 多态 什么是多态 java里多态的具体用法 多态的实现原理 反射 什么是反射 反射的实现原理 反射的应用 反射的弊端 反射相关类 反射应用实例 一些问题 private修饰的方法可以通过反射访问,那么private意义何在? 反射和多态的区别 反射和多态 事实上,反射和多态这两种技术并无直接联系,之所以把它们放在一起说...

程序员XW 575

Matlab 轴承信号仿真+分析

文章目录项目说明1、信号仿真1.1 仿真公式1.2 信号参数设置1.3 代码实现2、仿真信号分析2.1 小波变换2.2 快速谱峭度 项目说明 本文主要解决两个问题: 1、仿真包含周期性冲击信号、随机干扰冲击信号、调制干扰信号以及随机噪声四个成分的故障轴承信号; 2、使用小波变换以及快速谱峭度对该仿真信号进行分析。 1、信号仿真 1.1 仿真公式 这里的仿真信号公式主要参考了包文杰学者的硕士论文《加权谱峭度故障诊断方法研究与应用》,列举公式如下: 周期性冲击信号仿真 随机干扰冲击信号仿真 调制

cocofisher的博客 9267

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

反射和多态的实现原理是什么?

反射和多态 事实上,反射和多态这两种技术并无直接联系,之所以把它们放在一起说,是因为,在Java技术体系中所提供的能够让我们在运行时识别对象和类的类型信息的方式,一共有两种:即反射和多态关键技术RTTI RTTI,即run-Time Type Identification运行时类型判定,它的作用是在我们不知道某个对象的确切的类型信息时,即某个对象是哪个类的实例的时候,可以通过RTTI相关的机制帮助我们在编译时获取对象的类型信息,这其实也就是多态的实现基础。 反射机制允许我们在运行时发现和使用类的信息。

haiertadiedie的博客 210

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Java多态的底层实现原理

一.多态的前提: 1.继承 2.重写 3.向上转型(这里的向上转型即父类型的引用指向子类型的实例) 二.类的加载 首先得介绍一下JVM的大体结构: 类先被加载进来。。。。。。(类的加载过程)得到class文件 class文件载入JVM在方法区上得到并且建立储存该类的类型信息(就是一些成员变量,类变量,方法等) ...

weixin_42178281的博客 3072

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

反射的底层实现原理?

反射是 Java 编程语言中的一个强大特性,它允许程序在运行期间动态获取类和操纵类。通过反射机制,可以在运行时动态地创建对象、调用方法、访问和修改属性,以及获取类的信息。反射提供了极大的灵活性,但也带来了运行时性能损耗和安全隐患。

2401_85373732的博客 4658

多态和反射的关系

多态 什么是多态 java里多态的具体用法 多态的实现原理 反射 什么是反射 反射的实现原理 反射的应用 反射的弊端 反射相关类 反射应用实例 一些问题 private修饰的方法可以通过反射访问,那么private意义何在? 反射和多态的区别 反射和多态 事实上,反射和多态这两种技术并无直接联系,之所以把它们放在一起说,是因为,在Java技术体系中所提供的能够让我们在运行时识...

sinat_40775402的博客 710

详解反射的底层实现原理

反射在程序运行期间动态获取类和操纵类的一种技术。通过反射机制,可以在运行时动态地创建对象、调用方法、访问和修改属性,以及获取类的信息。

sosovo66的博客 2123

Java多态实现原理

##前言 多态是Java语言重要的特性之一,它允许基类的指针或引用指向派生类的对象,而在具体访问时实现方法的动态绑定。Java对于方法调用动态绑定的实现主要依赖于方法表,但通过引用调用(invokevitual)和接口引用调用(invokeinterface)的实现则有所不同。 Java多态实现原理的大致过程:首先是Java编译器将Java源代码编译成class文件。在编译过程中,会根据静态类型将调用的符号引用写到class文件中。在执行时,JVM根据class文件找到调用方法的符号引用,然后在静态类型的方

m0_57501956的博客 1365
上一篇: spring boot入门介绍及自动配置实现原理
下一篇: Class类文件详解
topEngineerr
博客等级 码龄11年 627粉丝 157原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值