反射

1.概念对象的反向处理,根据对象倒退类的组成。1.1反射核心类:Class类(专门描述其他类的组成)1.2Object类中取得对象的class对象:public final native Class<?> getClass( );Class类描述接口与类的组成,Class对象由JVM在第一次加载类时产生,并且全局唯一。1.3取得任意类Class对象的方法Ⅰ.调用对象....
摘要由CSDN通过智能技术生成

一、Java反射机制概述

  • 反射是被视为动态语言的关键,反射机制允许程序在执行期借助于反射API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法
  • 加载完类之后,在堆内存的方法区中就产生了一个Class类型的对象(一个类只有一个Class对象),这个对象就包含了完整的类的结构信息。我们可以通过这个对象看到类的结构。这个对象就像一面镜子,透过这个镜子看到类的结构,所以我们形象称之为:反射

在这里插入图片描述

1.反射机制提供的功能

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时获取泛型信息
  • 在运行时调用任意一个对象的成员变量和方法
  • 在运行时处理注解
  • 生成动态代理
  • 可以解耦,提高程序的可扩展性

2.动态语言 vs 静态语言

  • 动态语言是一类在运行时可以改变其结构的语言:例如新的函数、对象、甚至代码可以被引进,已有的函数可以被删除或是其他结构上的变化。通俗点说就是在运行时代码可以根据某些条件改变自身结构。主要动态语言:Object-C、C#、JavaScript、PHP、Python、Erlang。
  • 静态语言与动态语言相对应的,运行时结构不可变的语言就是静态语言。如Java、C、C++。Java不是动态语言,但Java可以称之为“准动态语言”。即Java有一定的动态性,我们可以利用反射机制、字节码操作获得类似动态语言的特性。Java的动态性让编程的时候更加灵活!

3.关于java.lang.Class类的理解

  1. 类的加载过程:
    程序经过Javac.exe命令后会生成一个或多个字节码文件(.class结尾)
    接着我们使用java.exe命令对某个字节码文件进行解释运行。相当于某个字节码文件加载到内存中,此过程就称为类的加载
    加载到内存中的类,我们就称为运行时类,此运行时类就作为Class的一个实例

  2. 换句话说,Class的实例就对应着一个运行时类

  3. 加载到内存中的运行时类,会缓存一定时间,在此时间内,我们可以通过不同的方式来获取此运行时类

4.获取Class实例的四种方式

  • 源代码阶段,class.forName(“类的路径”),将字节码文件加载进内存,返回Class对象。(多用于配置文件,将类名定义在配置文件中。读取文件,加载类)【最常使用】
  • Class类对象阶段,类名.class,通过类名的属性class获取。(多用于参数的传递,编译的时候已经写死了类名,而我们想的是在运行时想取得哪个类的对象就取得哪个类的对象,所以体现不出动态性)
  • Runtime运行时阶段,对象.getClass(),getClass( )方法在Object类中定义着。(多用于对象的获取字节码的方式,也就是看看这个对象是哪个类造的)
  • 使用类的加载器:ClassLoader【了解】
package 反射;

/**
 * @BelongsProject: untitled
 * @BelongsPackage: 反射
 * @Author: mcc
 * @CreateTime: 2020-11-29 14:18
 * @Description:获取Class实例的四种方式
 */
public class Person {
   
    private String name;
    private int age;

    public Person() {
   
    }

    public Person(String name, int age) {
   
        this.name = name;
        this.age = age;
    }

    public String getName() {
   
        return name;
    }

    public void setName(String name) {
   
        this.name = name;
    }

    public int getAge() {
   
        return age;
    }

    public void setAge(int age) {
   
        this.age = age;
    }

    @Override
    public String toString() {
   
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package 反射;

import org.junit.Test;

/**
 * @BelongsProject: untitled
 * @BelongsPackage: 反射
 * @Author: mcc
 * @CreateTime: 2020-11-29 14:21
 * @Description:
 */
public class ReflectionTest {
   
    @Test
    public void test1() throws Exception{
   
        //1.class.forName(“类的路径”)
        Class cls1 = Class.forName("反射.Person");
        System.out.println(cls1);
        //2.类名.class
        Class cls2 = Person.class;
        System.out.println(cls2);
        //3.对象.getClass()
        Person p = new Person();
        Class cls3 = p.getClass();
        System.out.println(cls3);
        //4.比较同一个类的Class对象是否相同
        System.out.println(cls1 == cls2);
        System.out.println(cls1 == cls3);
        //5.使用类的加载器:ClassLoader
        ClassLoader classLoader = ReflectionTest.class.getClassLoader();
        Class cls4 = classLoader.loadClass("反射.Person");
        System.out.println(cls4);
        System.out.println(cls1 == cls4);
    }
}

在这里插入图片描述

同一个字节码在一次程序运行过程中,只会被加载一次,不论通过哪一种方法获取的Class对象都是同一个

5.哪些类可以有Class对象

  1. class:外部类,成员(成员内部类、静态内部类),局部内部类,匿名内部类
  2. interface:接口
  3. []:数组
  4. enum:枚举
  5. annotation:注解@interface
  6. primitive type:基本数据类型
  7. void
@Test
public void test2(){
   
    Class c1 = Object.class;
    Class c2 = Comparable.class;
    Class c3 = String[].class;
    Class c4 = int[][].class;
    Class c5 = ElementType.class;
    Class c6 = Override.
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值