java中的反射及其优点说明

目录
  • java反射及优点
  • java反射机制(Reflection)
    • 1.什么是反射?反射有什么作用?
    • 2.反射相关的主要API
    • 3.什么是Class类
    • 4.调用运行时类的指定结构

java反射及优点

反射是java的一大特性,而且是有些框架实现了IoC/DI的原理,本文就来探讨下java中的反射及其优点。

首先是普通的java静态类加载,java静态类是通过new实现的,在编译时刻就要加载所有可能用到的类,这样实际上存在一些缺点的,比如只要有一个类没有找到或者出现重大的问题编译便不会通过,导致其他存在的类也无法使用。另一方面,如果要加载其他的类就要重新进行编译,有的时候是非常不方便的。下面就引入反射机制来动态加载类来解决这个问题。

首先创建一个ClassInterface接口,放在com.classTest包下:

package com.classTest; 
public interface ClassInterface {
    public void start();       //接口约定start()方法
}

然后分别使用Class1Impl和Class2Impl类去实现这个接口,也放在com.classTest包下:

package com.classTest; 
public class Class1Impl implements ClassInterface {
 
    @Override
    public void start() {
        // TODO Auto-generated method stub
        System.out.println("This is Class1Impl");   //实现start()
    }
}
package com.classTest; 
public class Class2Impl implements ClassInterface {
 
    @Override
    public void start() {
        // TODO Auto-generated method stub
        System.out.println("This is Class2Impl");   //实现start()
    } 
}

下面先用正常的类加载来说明正常类加载的缺点:

package com.test; 
import java.util.Scanner; 
import com.classTest.ClassInterface;
 
public class LoadClassTest {
    ClassInterface c1 = new Class1Impl();
    ClassInterface c2 = new Class2Impl();
    c1.start();
    c2.start();
}

上面是正常的new方法生成的对象,然后调用接口里的方法,但是一旦Class1Impl类或者Class2Impl类没有,那有的哪个类也就无法使用,而且想要使用新的ClassInterface接口下的方法还是需要重新写类,重新写测试方法,重新生成测试对象,重新编译...

下面介绍利用反射机制动态加载类来解决这个问题:

package com.test; 
import java.util.Scanner; 
import com.classTest.ClassInterface;
 
public class LoadClassTest {
    public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException{
        //new 创建对象是静态加载类,在编译时刻就需要加载所有可能用到的类
        //动态记载类可以解决这个问题
        Scanner sc = new Scanner(System.in);
        String className = sc.nextLine();
        //动态加载类,在运行的时刻进行加载
        //使用类类型(class type) 通过Class这个类的forName(className)方法动态创建类对象
        Class c = Class.forName(className);
        //通过类类型 用newInstance()方法创建该类对象
        ClassInterface ci = (ClassInterface) c.newInstance();
        ci.start();//动态加载类 调用其方法
    }
}

有没有看出这其中的差异,想要加载其他类只需要输入另外的类名即可(这里的类名是包含包的),forName()方法可以通过类名动态创建类类型的对象,然后用类类型的对象的newInstance()方法创建该类类型对象(也就是一个类)的对象(调用newInstance()方法的类类型对象需要进行转化),之后就可以用生成对象调用接口下的方法了。

那这时候可能就会有人问了,要是在我们不知道接口名称为ClassInterface的情况下,我们该如何访问className这个类类型生成的c这个类对象下面的方法呢?我们来实现一下:

Class c = Class.forName("com.classTest.Foo");//创建一个类对象c
Method m1 = c.getMethod("fun1", int.class,int.class);//通过getMethod方法获取c的方法,第一个参数表示想要获取的方法名称fun1,之后的参数列表表示fun1这个函数的所有参数的类类型。
Object o = m1.invoke(foo1,new Object[]{10,20} );//通过invoke方法来调用我们前面通过getMethod()获得的方法,第一个参数表示执行我们所获得方法的对象,第二个参数表示我们所获取方法的参数,这里是两个int类型。如果没有返回值返回null,有返回值则返回具体的返回值,这里将返回结果保存在o对象里。

这样的优点是显而易见的,类无需在编译前全部加载,而且修改接口实现类的时候也不用重新编译。

这只是反射的一小部分,但是也是很重要的一部分,也是Spring中IoC/DI的实现基础。

(另外告诉大家一个小tip:所谓的泛型数据容器的数据类型(也就是HashMap<String,String>中的<String,String>)不能写入其他数据类型实际上只是存在于编译层面的,是为了防止开发者往里面误写入自己不想写入的东西,然而通过泛型可以跳过编译层面实现往这个泛型数据容器里存入和这个泛型数据容器数据类型不一样的数据,虽然这样之后用foreach遍历就会报错...)

java反射机制(Reflection)

1.什么是反射?反射有什么作用?

能够分析类能力的程序称为反射。反射机制允许程序在运行状态借助Reflection API取得任何类的内部信息,并能直接操作任意对象的内部属性及方法。

反射机制的作用

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

2.反射相关的主要API

  • java.lang.Class:代表一个类
  • java.lang.reflect.Method:代表类的方法
  • java.lang.reflect. Field:代表类的成员变量
  • java.lang.reflect.Constructor:代表类的构造器

3.什么是Class类

对Class类的深入理解

  • Class本身也是一个类
  • Class 对象只能由系统建立对象(Class 对象是在加载类时由Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的)
  • 一个类在 JVM 中只会有一个Class实例
  • 一个Class对象对应的是一个加载到JVM中的一个.class文件
  • 每个类的实例都会记得自己是由哪个 Class 实例所生成
  • 通过Class可以完整地得到一个类中的完整结构

类的加载过程:

程序经过javac.exe命令以后,会生成一 个或多个字节码文件(.class结尾)。

接着我们使用java.exe命令对某个字节码文件进行解释运行。相当于将某个字节码文件加载到内存中。此过程就称为类的加载。加载到内存中的类,我们就称为运行时类,此运行时类,就作为CLass的一个实例。

java.Lang.Class实例的获取(四种方式)

package package03;
import org.junit.Test;
public class ReflectiveTeat01 {
    //获取 Class 类的实例
    @Test
    public void test01() throws Exception {
        //方式一:通过调用运行时类得属性:.class
        Class clazz1 = Person.class;
        System.out.println(clazz1);//class package03.Person
        //方式二:通过运行时类的对象,调用 getClass() 方法
        Person p1 = new Person();
        Class clazz2 = p1.getClass();
        System.out.println(clazz2);//class package03.Person
        //方式三:调用 Class 的静态方法:forName(String classPath)
        Class clazz3 = Class.forName("package03.Person");
        System.out.println(clazz3);//class package03.Person
        //方法四:使用类的加载器:ClassLoader
        ClassLoader classLoader = ReflectiveTeat01.class.getClassLoader();
        Class clazz4 = classLoader. loadClass("package03.Person") ;
        System. out . println(clazz4);//class package03.Person
    }
}

4.调用运行时类的指定结构

如何操作运行时类中指定的属性

@Test
    public void testField() throws Exception {
        Class clazz = Person.class;
        //创建运行时类的对象 P
        Person p = (Person) clazz.newInstance();
        //获取指定的属性
        Field fieldName = clazz.getDeclaredField("id");
        //fieldName 要操作的属性名赋值给 fieldName 变量名

        //保证当前属性是可访问的
        fieldName .setAccessible(true);
        /*
        设置当前属性的值
        set():参数1:指明设置哪个对象的属性
              参数2:将此属性值设置为多少
         */
        fieldName.set(p,1001);
        /*
        获取当前属性的值
        get():参数1:获取哪个对象的当前属性值
         */
        int intName = (int) fieldName.get(p);
        System.out.println(intName );
    }

操作运行时类的方法

已调用 show 方法例子:该方法有 注解,参数,返回值,权限小(private)

@MyAnonotation//自定义注解
    private String show(String nation) {
        System.out.println("我的国籍是:" + nation);
        return nation;
    }
 @Test
    public void testMethod() throws Exception {
        Class clazz = Person.class;
        //创建运行时类对象
        Person p = (Person) clazz.newInstance();
       /* 1.获取指定的某个方法
       getDeclaredMethod():参数1:指明获取的方法的名称
                           参数2:指明获取的方法的形参列表
       * */
        Method show = clazz.getDeclaredMethod("show", String.class);
        //2.保证当前方法时可访问的
        show.setAccessible(true);
        /*
        3.调用方法的invoke():参数1:方法的调用者
                            参数2:给方法形参赋值的实参
          invoke()方法的返回值即为对应类中调用的方法的返回值
         */
        show.invoke(p, "CHN");

        //调用静态方法时:
        //private static void showDesc()
        Method showDesc = clazz.getDeclaredMethod("showDesc");
        showDesc.setAccessible(true);
        //如果调用的运行时类中的方法没有返回值,则 invoke() 返回 null
        Object invoke = showDesc.invoke(Person.class);
        System.out.println(invoke);
    }

上面代码用到的 Person 类

public class Person {
    private String name;
    private int age;
    public int id;
    //空参构造器
    public Person() {
    }
    //全参构造器
    public Person(String name, int age, int id) {
        this.name = name;
        this.age = age;
        this.id = id;
    }
    @MyAnonotation
    private String show(String nation) {
        System.out.println("我的国籍是:" + nation);
        return nation;
    }
    //静态方法
    private static void showDesc(){
        System.out.println("我是一个可爱的人");
    }
    // get、set 方法
    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;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
}

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Java十分钟精通反射机制原理

    什么是反射? 反射机制是在运行状态中,它为Java提供一种"操作对象"的能力,在运行状态下,通过Class文件对象,可以调用到任何类里面的属性.方法.以及构造方法,包括私有的,所有的类在反射机制面前都是透明的 自己的概括:通过Class文件对象可以看到这个类里面的所有东西,并且可以使用和修改 反射的前提是获取Class文件对象((字节码对象),那么一共有三种方式获取: Class.forName("全类名") ----通过Class类的静态方法(最常用) 类名.cl

  • Java的反射机制一起来看看

    目录 一.什么是反射机制? 获得Class类对象的三种方式: 二.Class类 三.Package类 四.Field类 五.Method类 六.Constructor类 总结 一.什么是反射机制? 反射就是运行时识别类的能力,在运行时可以获得当前对象的类结构,动态创建类的实例,调用对象的方法等: 获得Class类对象的三种方式: 方式一 :Class.forName(“类名”); Class类的一个静态方法forName 加载类获得类对象 运行的类库中没有Person类,程序依然可以编译. Cl

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

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

  • Java反射机制原理、Class获取方式以及应用场景详解

    目录 学习背景 一.Java反射机制是什么? 1.1 反射原理 1.2 反射例子 二.Java反射机制中获取Class的三种方式及区别? 2.1 Class的几种获取方式 2.2 代码演示几种方式的区别 三.Java反射机制的应用场景有哪些? 3.1 应用场景 3.2 简单工厂模式优化 3.2.1 什么是简单工厂模式? 3.2.2 简单工厂模式有什么用? 3.2.3 如何实现简单工程模式? 3.2.4 简单工厂模式优化 3.2.5 简单工厂模式再次优化 3.3 代理模式中的动态代理实现 3.3.

  • Java使用反射和动态代理实现一个View注解绑定库

    目录 支持的功能 代码 注解类 实现类 使用 使用反射结合动态代理实现一个View注解绑定库,支持View和事件绑定,代码简洁,使用简单,扩展性强. 支持的功能 @ContentView 绑定layout 替代setContentView() @BindView 绑定View 替代findViewById() @OnClick 绑定点击事件 替代setOnClickListener() @OnLongClick 绑定长按事件 替代setOnLongClickListener() 代码 注解类 @

  • Java利用反射对list对象做过滤

    目录 1.对象结构 2.根据字段名获取value 3.对list过滤 4.精确匹配 5.模糊匹配 ​反射对效率有影响 慎用!!!​ 1.对象结构 public class BusinessDept { private String year;//年 private String month;//月 private String deptName;//部门名称 private String deptLeader;//部门负责人 private Double jyz; //经营值 private D

  • java中的反射及其优点说明

    目录 java反射及优点 java反射机制(Reflection) 1.什么是反射?反射有什么作用? 2.反射相关的主要API 3.什么是Class类 4.调用运行时类的指定结构 java反射及优点 反射是java的一大特性,而且是有些框架实现了IoC/DI的原理,本文就来探讨下java中的反射及其优点. 首先是普通的java静态类加载,java静态类是通过new实现的,在编译时刻就要加载所有可能用到的类,这样实际上存在一些缺点的,比如只要有一个类没有找到或者出现重大的问题编译便不会通过,导致其

  • Java中的反射机制详解

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

  • java中利用反射调用另一类的private方法的简单实例

    我们知道,Java应用程序不能访问持久化类的private方法,但Hibernate没有这个限制,它能够访问各种级别的方法,如private, default, protected, public. Hibernate是如何实现该功能的呢?答案是利用JAVA的反射机制,如下: import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class ReflectDemo {

  • java中如何反射获取一个类

    反射说白了就是可以获得一个类的所有信息,主要包括方法和属性两部分. 1.获得方法包括获得方法的名称,方法的返回类型,方法的访问修饰符,以及通过反射执行这个方法. 2.获得属性包括属性的名称,类型,访问修饰符,以及这个属性的值. 这些获得都有相应的API提供操作. 代码如下: package poi; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Meth

  • 一文搞懂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

  • Java中的反射,枚举及lambda表达式的使用详解

    目录 一.反射 1.1定义 1.2用途 1.3反射基本信息 1.4与反射相关的类 1.5Class类(反射机制的起源) 1.6Class类中的相关方法 1.7获得Class对象的三种方式 1.8反射的使用 1.9反射优点和缺点 二.枚举 2.1Enum类的常用方法 2.2枚举的优点和缺点 三.Lambda表达式 3.1Lambda表达式的语法及基本使用 3.2函数式接口 3.3变量捕获 总结 一.反射 1.1 定义 Java的反射(reflection)机制是在运行状态中,对于任意一个类,都能够

  • 10分钟带你理解Java中的反射

    一.简介 Java 反射是可以让我们在运行时获取类的方法.属性.父类.接口等类的内部信息的机制.也就是说,反射本质上是一个"反着来"的过程.我们通过new创建一个类的实例时,实际上是由Java虚拟机根据这个类的Class对象在运行时构建出来的,而反射是通过一个类的Class对象来获取它的定义信息,从而我们可以访问到它的属性.方法,知道这个类的父类.实现了哪些接口等信息. 二.Class类 我们知道使用javac能够将.java文件编译为.class文件,这个.class文件包含了我们对

随机推荐