一、Java中的反射机制

一、静态语言与动态语言

静态类型语言:是指在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型,某些具有类型推导能力的现代语言可能能够部分减轻这个要求。强类型

动态类型语言:是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。弱类型

静态:C#,Java,C,C++

动态:JavaScript,python,perl,ruby,php

静态类型语言因为类型强制声明,所以IDE可以做到很好的代码感知能力,因为有IDE的撑腰,所以开发大型系统,复杂系统比较有保障。

静态语言相对比较封闭的特点,使得第三方开发包对代码的侵害性可以降到很低。动态语言在这点上表现的就比较差,我想大家都有过从网上下载某个JS包,然后放到项目代码里发生冲突的经历。

二、反射概要

2.1、概念

反射就是可以在运行时加载类信息,并可以创建其对象访问其属性和方法。这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

通俗说:运行时获得并使用类的信息的方法叫反射

2.2、功能

  • 在运行时判断任意一个对象所属的类;
  • 在运行时构造任意一个类的对象;
  • 在运行时判断任意一个类所具有的成员变量和方法;
  • 在运行时调用任意一个对象的方法;生成动态代理。
  • 动态获得类型信息(方法,字段,属性…)
  • 动态时创建对象(根据字符串创建对象)
  • 动态调用对象或成员(动态调用方法)

2.3、反射的优点与缺点

优点:

可以实现动态创建对象和编译,体现出很大的灵活性

缺点:

对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它 满足我们的要求。这类操作总是慢于只直接执行相同的操作。

三、Class

 Class 类十分特殊。它和一般类一样继承自Object,其实体用以表达Java程序运行时的classes和interfaces,也用来表达enum、array、primitive Java types(boolean, byte, char, short, int, long, float, double)以及关键词void。当一个class被加载,或当加载器(class loader)的defineClass()被JVM调用,JVM 便自动产生一个Class 对象。因为Class并没有公共的构造方法,只有一个私有的无参构造方法,也就是说 Class 的对象创建只有 JVM 可以完成。

JAVA 使用 Class 对象来执行运行时类型信息(RunTime Type Information,RTTI)。每个类都有一个 Class 对象,它用来创建这个类的所有对象,反过来说,每个类的所有对象都会关联同一个Class 对象(对于数组来说,维数、类型一致的数组的 Class 对象才是相同的),每个对象的创建都依赖于Class 对象的是否创建,Class 对象的创建发生在类加载(java.lang.ClassLoader)的时候。

理解RTTI在Java中的工作原理,首先需要知道类型信息在运行时是如何表示的,这是由Class对象来完成的,它包含了与类有关的信息。Class对象就是用来创建所有“常规”对象的,Java使用Class对象来执行RTTI,即使你正在执行的是类似类型转换这样的操作。

每个类都会产生一个对应的Class对象,也就是保存在.class文件。所有类都是在对其第一次使用时,动态加载到JVM的,当程序创建一个对类的静态成员的引用时,就会加载这个类。Class对象仅在需要的时候才会加载,static初始化是在类加载时进行的。

获得Class对象的办法:

package com.store;

public class Fruit {
    public String name;
    
    public static void main(String[] args) throws ClassNotFoundException {
        Fruit fruit=new Apple();
        System.out.println("今天吃:"+fruit.name);
        
        //  public final native java.lang.Class getClass();
        //获得Class办法一,通过对象获得
        Class clazz1=fruit.getClass();
        //获得Class办法二,通过字符串获得(包名+类名)
        Class clazz2=Class.forName("com.store.Orange");
        //获得Class办法三,(通过类的静态成员class获得)
        Class clazz3=Fruit.class;
        //获得Class办法四,(只针对内置的基本数据类型)
        Class clazz4=Integer.TYPE;
        
        //获得父类类型
        Class clazz5=clazz2.getSuperclass();
        
        System.out.println("类名:"+clazz1.getName());
        System.out.println("类名:"+clazz2.getName());
        System.out.println("类名:"+clazz3.getName());
        System.out.println("类名:"+clazz4.getName());
        
        System.out.println("com.store.Orange的父类类名:"+clazz5.getName());
    }
    
}

class Apple extends Fruit{
    public Apple() {
        this.name="苹果";
    }
}

class Orange extends Fruit{
    public Orange() {
        this.name="橙子";
    }
}

猜你喜欢

转载自www.cnblogs.com/hxw6/p/9373826.html