Java中的反射机制示例详解

目录
  • 反射
  • 什么是Class类
  • 获取Class实例的三种方式
  • 通过反射创建类对象
  • 通过反射获取类属性、方法、构造器
  • 更改访问权限和实例赋值
  • 运用场景

反射

反射就是把Java类中的各个成分映射成一个个的Java对象。即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法;对于任意一个对象,都能调用它的任意一个方法和属性。这种动态获取信息及动态调用对象方法的功能叫Java的反射机制

每一个Java程序执行必须通过编译、加载、链接和初始化四个阶段

1.编译:将.java.文件编译成字节码.class文件

2.加载:查找并加载类的二进制数据

3.链接:

  • 验证:确保被加载类的正确性
  • 为类的静态变量分配内存,并将其初始化为默认值
  • 将类中的符号转换为直接引用

4.初始化:为类的静态变量赋予正确的初始值

什么是Class类

在Java中,每个class都有一个相应的Class对象。也就是说,当我们编写一个类,编译完成后,在生成的.class文件中,就会产生一个Class对象,用于表示这个类的类型信息

也就是说,无论你是什么对象,总会有有一个隐藏的Class对象与你相对应,而Class的实例表示正在运行的 Java 应用程序中的类和接口。借此,实现了我们Java的反射机制。

获取Class实例的三种方式

实例化对象调用getClass()方法

使用Class类的静态方法forName(),用类的名字获取一个Class实例

运用.class的方式来获取Class实例,对于基本数据类型的封装类,还可以采用.TYPE来获取相对应的基本数据类型的Class实例

用代码来看一看:

public class reflect {

    public static void main(String[] args) throws ClassNotFoundException {

        Apple apple = new Apple();

        // 使用对象的getClass()方法
        Class a1 = apple.getClass();

        // 使用Class类的静态方法forName()
        Class a2 = Class.forName("p1.apple");

        // 运用.class的方式来获取Class实例
        Class a3 = Apple.class;

        System.out.printf("a1: %s\na2: %s\na3: %s", a1, a2, a3);

    }

}

class Apple {

    private Integer weight;

    private String color;

}

打印结果:

a1: class p1.apple
a2: class p1.apple
a3: class p1.apple
进程已结束,退出代码0

通过反射创建类对象

通过反射创建类对象主要有两种方式:通过 Class 对象的 newInstance() 方法、通过 Constructor 对象的 newInstance() 方法。

public class reflect {

    public static void main(String[] args) throws InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {

        // 通过 Class 对象的 newInstance() 方法
        Class temp1 = Apple.class;
        Apple apple1 = (Apple) temp1.newInstance();

        // 通过 Constructor 对象的 newInstance() 方法
        Class temp2 = Apple.class;
        Constructor constructor1 = temp2.getConstructor();
        Apple apple2 = (Apple)constructor1.newInstance();

        // 通过 Constructor 对象创建类对象可以选择特定构造方法,而通过 Class 对象则只能使用默认的无参数构造方法。
        Class temp3 = Apple.class;
        Constructor constructor2 = temp3.getConstructor(Integer.class,String.class);
        Apple apple = (Apple)constructor2.newInstance(2, "Red");
        System.out.println(apple);

    }

}

class Apple {

    private Integer weight;

    private String color;

    // 无参构造器
    public Apple() {
        System.out.println("我是无参构造!");
    }

    // 有参构造器
    public Apple(Integer weight,String color) {
        this.weight = weight;
        this.color = color;
    }

    // 重写方法 方便打印显示对象内容
    @Override
    public String toString() {
        return "Apple{" +
                "weight=" + weight +
                ", color='" + color + '\'' +
                '}';
    }

}

打印结果:

我是无参构造!
我是无参构造!
Apple{weight=2, color='Red'}

进程已结束,退出代码0

通过反射获取类属性、方法、构造器

public class reflect {

    public static void main(String[] args) throws NoSuchFieldException {

        // 返回一个类中所有可访问的公共字段,包括该类的公共字段和其继承的类的公共字段
        Field[] fields1 = Apple.class.getFields();
        System.out.println("getFields结果");
        Arrays.stream(fields1).forEach(System.out::println);

        // 返回一个类中全部字段,但只包括该类的字段
        Field[] fields2 = Apple.class.getDeclaredFields();
        System.out.println("getDeclaredFields结果");
        Arrays.stream(fields2).forEach(System.out::println);

        // 根据字段名返回一个公开字段
        Field field1 = Apple.class.getField("noThing");
        System.out.println("getField结果");
        System.out.println(field1);

        // 根据字段名返回一个字段
        Field field2 = Apple.class.getDeclaredField("color");
        System.out.println("getDeclaredField结果");
        System.out.println(field2);

        // 同Field Method也有四种获取方式
        // 这里举其中一个例子
        Method[] methods = Apple.class.getDeclaredMethods();
        System.out.println("getDeclaredMethods结果");
        Arrays.stream(methods).forEach(System.out::println);

        // 同上 举一个获取构造器的例子
        Constructor[] constructors = Apple.class.getDeclaredConstructors();
        System.out.println("getDeclaredConstructors结果");
        Arrays.stream(constructors).forEach(System.out::println);

    }

}

class Apple {

    private Integer weight;

    private String color;

    public String noThing;

    public Apple() {

    }

    public Apple(Integer weight, String color) {
        this.weight = weight;
        this.color = color;
    }

    @Override
    public String toString() {
        return "Apple{" +
                "weight=" + weight +
                ", color='" + color + '\'' +
                '}';
    }

}

打印结果:

getFields结果
public java.lang.String p1.Apple.noThing
getDeclaredFields结果
private java.lang.Integer p1.Apple.weight
private java.lang.String p1.Apple.color
public java.lang.String p1.Apple.noThing
getField结果
public java.lang.String p1.Apple.noThing
getDeclaredField结果
private java.lang.String p1.Apple.color
getDeclaredMethods结果
public java.lang.String p1.Apple.toString()
getDeclaredConstructors结果
public p1.Apple()
public p1.Apple(java.lang.Integer,java.lang.String)

更改访问权限和实例赋值

首先,通过field.setAccessible()可更改属性的访问权限

public class reflect {

    public static void main(String[] args) throws NoSuchFieldException {

        // 实例化一个Apple
        Apple apple = new Apple();

        // 获取所有字段 并统一设定为公有属性
        Field[] fields = Apple.class.getDeclaredFields();
        Arrays.stream(fields).forEach( field -> {
            field.setAccessible(true);
            // 打印结果
            System.out.println(field);
            try {
                if (field.getType() == Integer.class) {
                    field.set(apple, 5);
                } else if (field.getType() == String.class) {
                    field.set(apple, "Red");
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        });
        // 查看apple结果
        System.out.println(apple);

    }

}

class Apple {

    private Integer weight;

    private String color;

    @Override
    public String toString() {
        return "Apple{" +
                "weight=" + weight +
                ", color='" + color + '\'' +
                '}';
    }

}

打印结果:

private java.lang.Integer p1.Apple.weight
private java.lang.String p1.Apple.color
Apple{weight=5, color='Red'}

进程已结束,退出代码0

通过源码文档和打印结果,可见setAccessable()方法并没有改变类字段的访问权限,而是作为一个标志,使得我们反射获取实例过程中可以对其进行操作

运用场景

在我看来,反射机制实际上就是上帝模式,如果说方法的调用是 Java 正确的打开方式,那反射机制就是上帝偷偷开的后门,只要存在对应的class,一切都能够被调用。

众所周知,语言有静态语言和动态语言两大分类,静态语言例如C/C++、Java、C#等,动态语言有Python、PHP、JavaScript等。为了让Java语言也有动态语言的特性,有了反射机制,解耦以及提高代码的灵活性。

反射在开发过中或许并不常见,可我们使用的框架工具底层都有反射的存在。动态代理设计模式、JDBC 的数据库的连接、Spring 框架的使用等都应用到了反射机制。

以上就是Java中的反射机制示例详解的详细内容,更多关于Java反射机制的资料请关注我们其它相关文章!

(0)

相关推荐

  • Java反射机制基础详解

    目录 1.什么是Java反射机制? 2.反射机制原理 3.Class类介绍 3.1.Class类基本介绍 3.2.Class类对象的获取方法 Class.forname() 3.3 .可以获取Class对象的类型 4.java反射的作用? 5.反射API主要类 6.Java反射的优缺点 7.反射调用的优化方法 8.反射的基本使用例子 9.反射开放权限操作 总结 1.什么是Java反射机制? 在程序运行中动态地获取类的相关属性,同时调用对象的方法和获取属性,这种机制被称之为Java反射机制 下面给

  • Java基础篇之反射机制详解

    目录 1.反射概述 1.1什么是反射 1.2.反射能干什么 2.解剖类 2.1反射构造方法 2.1.1反射无参的构造函数 2.1.2反射“一个参数”的构造函数 2.1.3反射“多个参数”的构造函数 2.1.4反射“私有”的构造函数 2.1.5反射得到类中所有的构造函数 2.2反射类中的方法 2.3反射类中的属性字段 思考:在讲反射之前,先思考一个问题,java中如何创建一个对象,有哪几种方式? Java中创建对象大概有这几种方式: 1.使用new关键字:这是我们最常见的也是最简单的创建对象的方式

  • Java基础篇之反射机制示例详解

    目录 一.什么是反射: 二.反射的原理: 三.反射的优缺点: 四.反射的用途: 五.反射机制常用的类: 六.反射的基本使用: 1.获得Class:主要有三种方法: 2.判断是否为某个类的示例: 3.创建实例:通过反射来生成对象主要有两种方法: 4.通过反射获取构造方法并使用: 5.获取成员变量并调用: 6.获取成员方法并调用: 7.反射main方法: 8.利用反射创建数值: 9.反射方法的其他使用--通过反射运行配置文件内容: 10.反射方法的其他使用--通过反射越过泛型检查: 总结 一.什么是

  • Java反射机制的简单讲解

    🌱1. 什么是反射机制? 首先大家应该先了解两个概念,编译期和运行期,编译期就是编译器帮你把源代码翻译成机器能识别的代码,比如编译器把java代码编译成jvm识别的字节码文件,而运行期指的是将可执行文件交给操作系统去执行,JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意方法和属性:这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制 简单说,反射机制值得是程序在运行时能够获取自身的信息.在java中,只要给定类的名字,那么就可以通过反射机制来获得类的所有信息. 🌱2. java反射机制提供了什么功能? 在运行时能够判断任意一个对象所属的类 在运行时构造任意一个类的对象 在运行时判断任意一个类所具有的成员变量和方法 在运行时调用任一对象的方法 在运行时创建新类对象 🌱3.new和反射创建有什么区别呢? ne

  • java反射机制最详解

    目录 java反射机制 什么是反射? 反射的功能: 反射常用类: 1.Class枚举类 2.Constructor构造器 3.Method方法类 4.Field变量类 反射运行指示图 通过反射获取对象 总结 java反射机制 什么是反射? 在java开发中有一个非常重要的概念就是java反射机制,也是java的重要特征之一.反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问.检测和修改它本身状态或行为的一种能力,通过反射可以调用私有方法和私有属性,大部分框架也都是运用反射原理的

  • Java中的反射机制示例详解

    目录 反射 什么是Class类 获取Class实例的三种方式 通过反射创建类对象 通过反射获取类属性.方法.构造器 更改访问权限和实例赋值 运用场景 反射 反射就是把Java类中的各个成分映射成一个个的Java对象.即在运行状态中,对于任意一个类,都能够知道这个类的所以属性和方法:对于任意一个对象,都能调用它的任意一个方法和属性.这种动态获取信息及动态调用对象方法的功能叫Java的反射机制 每一个Java程序执行必须通过编译.加载.链接和初始化四个阶段 1.编译:将.java.文件编译成字节码.

  • Java中随机函数变换的示例详解

    目录 说明 解决的问题 问题1 问题2 问题3 问题4 说明 本示例中基于 Java ,其他语言也有类似的 API 解决的问题 问题1 Java 中 Math.random()函数是等概率返回区间[0,1)中的任意一个小数.即x < 1情况下,[0,x)中的数出现的的概率是x,如果我们要将x < 1情况下,[0,x)中的数出现的的概率调整成x^2,应该如何做? 问题1思路 由于[0,x)的概率是x,那么调用两次Math.random(),如果较大的那个值也要在[0,x)区间内,那么两次调用都必

  • Java中的RASP机制实现详解

    RSAP RASP是Gartner公司提出的一个概念,称:程序不应该依赖于外部组件进行运行时保护,而应该自身拥有运行时环境保护机制: RASP就是运行时应用自我保护(Runtime application self-protection)的缩写,正如RASP字面意思一样,这是运行在运行时的一种防护技能:也就是说RASP能够在程序运行期间实施自我保护,监控与过滤有害信息,还能够拥结合程序的当前上下文实施精确.实时的防护: Java中的RASP 不严格来说Java是半编译.半解释型语言,我们也都知道

  • java中final关键字使用示例详解

    final经常和static一起使用来声明常量,你也会看到final是如何改善应用性能的.final关键字的含义?final在Java中是一个保留的关键字,可以声明成员变量.方法.类以及本地变量.一旦你将引用声明作final,你将不能改变这个引用了,编译器会检查代码,如果你试图将变量再次初始化的话,编译器会报编译错误.什么是final变量?凡是对成员变量或者本地变量(在方法中的或者代码块中的变量称为本地变量)声明为final的都叫作final变量.final变量经常和static关键字一起使用,

  • java反射机制示例详解

    1.什么是反射?一个类有多个组成部分,例如:成员变量,方法,构造方法等.反射就是加载类,并解剖出类的各个组成部分. 2.加载类java中有一个Class类用于代表某一个类的字节码.Class类既然代表某个类的字节码,那就要提供加载某个类字节码的方法:forName().   此方法用于加载某个类的字节码到内存中,并使用class对象进行封装.另外2种得到class对象的方式:类名.class对象.getClass() 先创建一个简单的Person类 复制代码 代码如下: public class

  • JavaScript中变量提升机制示例详解

    变量提升 JavaScript的变量提升有两种,用var声明的变量以及用function声明的变量. 用var声明的变量 我们先来看下面这段代码,a的值是多少 代码1 console.log(a); var a; 按照以往编程语言的思路来看,代码自上而下运行,按这种思路,会报错,因为执行到第2行时,变量a还没有定义,所以会报错a is not defined 然而事实上答案是undefined 好,抱着疑惑,我们看下面的代码 var a; console.log(a); 我们发现,这两段代码是一

  • Java中的反射机制详解

    Java中的反射机制详解 反射,当时经常听他们说,自己也看过一些资料,也可能在设计模式中使用过,但是感觉对它没有一个较深入的了解,这次重新学习了一下,感觉还行吧! 一,先看一下反射的概念: 主要是指程序可以访问,检测和修改它本身状态或行为的一种能力,并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义. 反射是Java中一种强大的工具,能够使我们很方便的创建灵活的代码,这些代码可以再运行时装配,无需在组件之间进行源代码链接.但是反射使用不当会成本很高! 看概念很晕的,继续往下

  • 详解Java中的反射机制和动态代理

    一.反射概述 反射机制指的是Java在运行时候有一种自观的能力,能够了解自身的情况为下一步做准备,其想表达的意思就是:在运行状态中,对于任意一个类,都能够获取到这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性(包括私有的方法和属性),这种动态获取的信息以及动态调用对象的方法的功能就称为java语言的反射机制.通俗点讲,通过反射,该类对我们来说是完全透明的,想要获取任何东西都可以,这是一种动态获取类的信息以及动态调用对象方法的能力. 想要使用反射机制,就必须要先获取到该类

  • Java中的反射机制基本运用详解

    目录 Java中的反射机制基本运用 1.什么是反射(reflect) 2.反射机制提供的功能 3.反射->获取类对象 4.反射->利用无参构造实例化对象 5.反射->利用有参构造实例化对象 6.反射->调用无参方法 7.反射->调用有参方法 8.反射->访问私有方法 9.反射->类加载路径 总结 Java中的反射机制基本运用 看完反射可以了解一下注解 注解annotation://www.jb51.net/article/221276.htm 1.什么是反射(re

随机推荐