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

目录
  • Java中的反射机制基本运用
  • 1、什么是反射(reflect)
  • 2、反射机制提供的功能
  • 3、反射->获取类对象
  • 4、反射->利用无参构造实例化对象
  • 5、反射->利用有参构造实例化对象
  • 6、反射->调用无参方法
  • 7、反射->调用有参方法
  • 8、反射->访问私有方法
  • 9、反射->类加载路径
  • 总结

Java中的反射机制基本运用

看完反射可以了解一下注解

注解annotation://www.jb51.net/article/221276.htm

1、什么是反射(reflect)

反射是java的动态机制,它允许将对象的实例化,方案的调用,属性的操作等从编码期确定转移到程序运行期确定。

反射能大大提高代码的灵活度。但同时也带来了更多的系统开销和较慢的运行效率,因此程序不能过度依赖反射。

2、反射机制提供的功能

  • 在运行时判断任意一个对象所属的类
  • 在运行时构造任意一个类的对象(实例化)
  • 在运行时判断任意一个类所具有的成员变量和方法
  • 在运行时调用任意一个对象的方法——动态代理

3、反射->获取类对象

在开始之前创建一个实体类,用于测试反射机制

package reflect_text;
/**
 * 用于测试反射机制
 *
 * @author Akio
 * @Create 2021/8/14 10:37
 */
public class Person {
    private String name = "刘瑜澄";//设置初始值
    private int age = 22;
    public Person() {//无参构造
    }
    public Person(String name, int age) {//有参构造
        this.name = name;
        this.age = age;
    }
    public void sayHello() {//无参方法
        System.out.println(name + ":使用sayHello方法");
    }
    public void sayGoodBye() {//无参方法
        System.out.println(name + ":使用sayGoodBye方法");
    }
    public void say(String info) {//有参方法
        System.out.println(name + ":" + info);
    }
    public void say(String info, int sum) {//有参方法(重载say方法)
        for (int i = 0; i < sum; i++) {
            System.out.println(name + ":" + info);
        }
    }
    private void privateMethod() {//私有方法
        System.out.println(name + ":这是一个私有方法");
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

以上这个用于测试反射的实体类创建成功后,先学习反射中是如何获取类对象的。

反射的第一步就是要获取操作类的类对象,即一个Class的实例,JVM中每个被加载的类有且只有一个类对象与之对应,获取到这个类对象后我们就可以通过这个类对象来了解该类的一切信息(类名、有哪些方法、属性等等) 以便在程序运行期间通过反射机制进行相关操作

这里介绍三种获取类对象的方式:

  • (包名.)类名.class
Class personClass = reflect_text.Person.class;
Class intClass = int.class;

这种方式最直接,但是由于是靠硬编码形式写死(编译期间已经确定),因此不够灵活。但是需要注意,基本类型(int\double等)只能通过这种方式获取类对象

  • Class.forName(String className)
Class personClass = Class.forName("reflect_text.Person");
Class stringClass = Class.forName("java.lang.String");

这种方式较为常用,遵循运行期绑定。

  • 类加载器ClassLoader
Class stringClass = ClassLoader.getSystemClassLoader().loadClass("java.lang.String");
Class personClass = ClassLoader.getSystemClassLoader().loadClass("reflect_text.Person");

在这一节中介绍几个简单的方法:

getName()
获取类的完全限定名:包名.类名
getSimpleName()
仅仅获取类名
getMethods()
返回一个Method数组,获取class所表示的类的所有公开方法(包含从超类中继承的方法)

例子:

		Scanner scanner = new Scanner(System.in);
		Class cls = Class.forName(scanner.nextLine());//运行期绑定
        String name = cls.getName();//获取类的完全限定名:包名.类名
        System.out.println("完全限定名 = " + name);
        name = cls.getSimpleName();//仅获取类名
        System.out.println("仅类名 = " + name);
        Method[] methods = cls.getMethods();
        for (Method m : methods) {
            System.out.print(m.getName()+"\t");
        }

4、反射->利用无参构造实例化对象

Class类中提供了一个方法newInstance()来实例化,该方法要求此类必须具有无参构造器,它是通过无参构造器实例化对象的。

		Person person = new Person();
        //1获取要实例化的类的类对象
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入类名:");
        Class cls = Class.forName(scanner.nextLine());
        /*
            通过Class提供的方法newInstance()来实例化
           	该方法要求此类必须具有无参构造器,它是通过无参构造器实例化对象的
         */
        Object obj = cls.newInstance();
        System.out.println("obj = " + obj);

5、反射->利用有参构造实例化对象

getConstructor()
//获取无参构造器,可以利用无参构造器实例化对象,但这个方法对于使用无参构造器实例化对象可有可无
getConstructor(类对象)
//通过类对象获取特定的构造器,该参数列表是根据特定构造器的参数列表类型来决定的,如
		getConstructor(String.class, int.class)
		即为调用Person类中两个参数的有参构造器
		public Person(String name, int age) {//有参构造
    		this.name = name;
    		this.age = age;
		}

举例

		//加载类对象
        Class cls = Class.forName("reflect.Person");
        //通过类对象获取特定的构造器
        Constructor c = cls.getConstructor(String.class, int.class);
        Object o = c.newInstance("流年", 21);//实例化
        System.out.println(o);

结果可知初始值已经被修改

6、反射->调用无参方法

getMethod(String MethodName)
获取类对象的MethodName方法,返回值类型为Method
invoke(Object object)
执行object对象的某方法

举例

		//一般调用方法的做法-------------------
        Person p = new Person();//实例化对象
        p.sayHello();//调用该对象方法
        //反射机制调用方法-----------------------
        //1、实例化对象
        Class cls = Class.forName("reflect_text.Person");
        Object o = cls.newInstance();
        //2、调用o的sayHello方案
        //2.1通过Class获取Person的sayHello方法
        Method method = cls.getMethod("sayHello");
        //2.2调用o的该方法
        method.invoke(o);//等效于一般方法中的o.sayHello()

可见两种操作均能达到一样的效果

7、反射->调用有参方法

getMethod(String MethodName, 类对象)
获取类对象的MethodName有参方法,并传入对应参数类型的类对象,返回值类型为Method

举例

		//一般调用有参方法------------------------
        Person p = new Person();
        p.say("七夕快乐~");
        p.say("七夕快乐~",3);
        //反射机制调用有参方法---------------------
        Class cls = Class.forName("reflect_text.Person");
        Object o = cls.newInstance();
        //调用say(String info)方法
        Method m1 = cls.getMethod("say", String.class);
        m1.invoke(o, "春节快乐~");
        //调用say(String info, int sum)
        Method m2 = cls.getMethod("say", String.class, int.class);
        m2.invoke(o,"春节快乐~",3);

通过结果可以看到,效果都是一样的

8、反射->访问私有方法

注意:反射访问私有的方法,但是会破坏类的封装性

getDeclaredMethod(String MethodName)
可以仅获取此类定义的所有方法,包含私有方法
setAccessible(boolean flag)
开启私有方法的访问权限

举例

		//正常情况下,在本类中不可以访问外部的私有方法
		//但在反射机制中可行
		Class cls = Class.forName("reflect_text.Person");
        Object o = cls.newInstance();
        Method method = cls.getDeclaredMethod("privateMethod");
        method.setAccessible(true);//打开访问权限
        method.invoke(o);

9、反射->类加载路径

加载资源时常用相对路径,之前学习的相对路径./由于运行环境不同,位置并非固定,因此实际开发中使用较少。
接下来介绍,在开发中常用的类加载路径

常用的路径通常为类的加载路径,有两个:

1:类对象.getResource()与当前类所处同一目录

2:类加载器.getResource()类加载路径,类的package定义中根包位置。

例如:有一个类:
package reflect_text;
public class WebServer{
     ……
}
在WebServer类中,当我们使用上述两种方式获取路径时他们的对应位置为:
WebServer.class.getResource()
当前WebServer所在的目录(编译后的class文件所在目录)
WebServer.class.getClassLoader().getResource()
则是在WebServer的包的最上级,即com包的上一级
package reflect_text;
public class ReflectDemo {
		File dir = new File(ReflectDemo.class.getResource(".").toURI());
        System.out.println("dir = " + dir);
        //dir = D:\ClassCode\JavaSE_API\out\production\JavaSE_API\reflect
        File dir2 = new File(ReflectDemo.class.getClassLoader().getResource(".").toURI());
        System.out.println("dir2 = " + dir2);
        //dir2 = D:\ClassCode\JavaSE_API\out\production\JavaSE_API
}

总结

本片文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • Java反射(JDK)与动态代理(CGLIB)详解

    目录 一.反射 二.动态代理 1.JDK代理 2.CGLIB代理 3.JDK代理与CGLIB代理对比 总结 一.反射 概念:在运行状态中,对于任意的一个类,都能够知道这个类的所有字段和方法,对任意一个对象都能够通过反射机制调用一个类的任意方法 实现方法:JVM在第一次加载某个类时会生成一个Class对象,里面记录了这个类的信息 链接:类加载机制(留坑) 二.动态代理 动态代理的作用:在不改变原代码的基础上增加新的功能,如日志.权限检验等 反射在动态代理中的应用:由于知道原类的字段.方法等信息,才

  • Java反射(Class类,Class对象获取)

    目录 Java反射超详解 1.反射基础 1.1Class类 1.2类加载 2.反射的使用 2.1Class对象的获取 2.2Constructor类及其用法 2.3Field类及其用法 Java反射超详解 1.反射基础 Java反射机制是在程序的运行过程中,对于任何一个类,都能够知道它的所有属性和方法:对于任意一个对象,都能够知道它的任意属性和方法,这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制. Java反射机制主要提供以下这几个功能: 在运行时判断任意一个对象所属的类

  • java反射超详细讲解

    目录 Java反射超详解✌ 1.反射基础 1.1Class类 1.2类加载 2.反射的使用 2.1Class对象的获取 2.2Constructor类及其用法 2.4Method类及其用法 Java反射超详解✌ 1.反射基础 Java反射机制是在程序的运行过程中,对于任何一个类,都能够知道它的所有属性和方法:对于任意一个对象,都能够知道它的任意属性和方法,这种动态获取信息以及动态调用对象方法的功能称为Java语言的反射机制. Java反射机制主要提供以下这几个功能: 在运行时判断任意一个对象所属

  • java 反射调用Service导致Spring注入Dao失效的解决方案

    目录 java 反射调用Service导致Spring注入Dao失效 问题发生背景: 1.错误方法:通过反射执行service的方法 2.解决方法:通过获取Spring容器取得对象 反射调用导致Spring特性失效 1.抛出问题 1.1.编写TestAspectController类 1.2.编写ModuleService类 1.3.编写TestKey注解 1.4.编写TestAspectService 1.5.编写TestAspect切面 2.解决问题 2.1.编写SpringContextU

  • java反射机制最详解

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

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

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

  • java中静态导入机制用法实例详解

    java中静态导入机制用法实例详解 这里主要讲解了如何使用Java中静态机制的用法,这里提供了简单实例大家可以参考下. 静态常量类 在java开发中,我们会经常用到一些静态常量用于状态判断等操作.为了能够在多个地方复用这些常量,通常每个模块都会加一个常量类,举个简单的列子: import com.sky.OrderMouleConsstants; /** * Created by gantianxing on 2017/4/21. */ public class Test { public vo

  • Java中的反射机制详解

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

  • Java中反射机制和作用详解

    前言 很多刚学Java反射的同学可能对反射技术一头雾水,为什么要学习反射,学习反射有什么作用,不用反射,通过new也能创建用户对象. 那么接下来大师就带你们了解一下反射是什么,为什么要学习反射? 下面我们首先通过一个实例来说明反射的好处: 方法1.不用反射技术,创建用户对象,调用sayHello方法 1.1 我们首先创建一个User类 package com.dashi; /** * Author:Java大师 * User对象,包含用户的id和姓名以及sayHello方法 */ public

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

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

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

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

  • Java 反射机制的实例详解

    Java 反射机制的实例详解 前言 今天介绍下Java的反射机制,以前我们获取一个类的实例都是使用new一个实例出来.那样太low了,今天跟我一起来学习学习一种更加高大上的方式来实现. 正文 Java反射机制定义 Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 用一句话总结就是反射可以实现在运行时可以知道任意一个类的属性和方法. 反射

  • 一文搞懂Java中的反射机制

    前一段时间一直忙,所以没什么时间写博客,拖了这么久,也该更新更新了.最近看到各种知识付费的推出,感觉是好事,也是坏事,好事是对知识沉淀的认可与推动,坏事是感觉很多人忙于把自己的知识变现,相对的在沉淀上做的实际还不够,我对此暂时还没有什么想法,总觉得,慢慢来,会更快一点,自己掌握好节奏就好. 好了,言归正传. 反射机制是Java中的一个很强大的特性,可以在运行时获取类的信息,比如说类的父类,接口,全部方法名及参数,全部常量和变量,可以说类在反射面前已经衣不遮体了(咳咳,这是正规车).先举一个小栗子

  • java中Executor,ExecutorService,ThreadPoolExecutor详解

    java中Executor,ExecutorService,ThreadPoolExecutor详解 1.Excutor 源码非常简单,只有一个execute(Runnable command)回调接口 public interface Executor { /** * Executes the given command at some time in the future. The command * may execute in a new thread, in a pooled thre

  • java 中maven pom.xml文件教程详解

    maven pom.xml文件教程详解,具体内容如下所示: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.x

随机推荐