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

本文详细介绍了Java中的反射和多态。反射机制允许我们在运行时获取类的信息,而多态是面向对象编程的重要概念,允许接口的多种不同实现。两者在运行时都能获取程序信息,但多态主要涉及方法调用,而反射则能获取类的全部详情。文章讲解了多态的实现原理RTTI,以及反射的Class类和相关API的使用,并探讨了反射的优缺点及其在框架中的应用。
摘要由CSDN通过智能技术生成

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;
    }
}

cla
  • 19
    点赞
  • 67
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值