广告
返回顶部
首页 > 资讯 > 精选 >Java反射机制怎么应用
  • 868
分享到

Java反射机制怎么应用

2023-06-17 03:06:27 868人浏览 八月长安
摘要

本篇内容主要讲解“Java反射机制怎么应用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java反射机制怎么应用”吧!反射基础p.s: 本文需要读者对反射机制的api有一定程度的了解,如果之前没

本篇内容主要讲解“Java反射机制怎么应用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java反射机制怎么应用”吧!

反射基础

p.s: 本文需要读者对反射机制的api有一定程度的了解,如果之前没有接触过的话,建议先看一下官方文档的Quick Start。

在应用反射机制之前,首先我们先来看一下如何获取一个对象对应的反射类Class,在Java中我们有三种方法可以获取一个对象的反射类。

通过getClass方法

在Java中,每一个Object都有一个getClass()方法,通过getClass方法我们可以获取到这个对象对应的反射类:

String s = "Http://www.ziwenxie.site";  Class<?> c = s.getClass();

通过forName方法

我们也可以调用Class类的静态方法forName():

Class<?> c = Class.forName("java.lang.String");

使用.class

或者我们也可以直接使用.class:

Class<?> c = String.class;

获取类型信息

在文章开头我们就提到反射的一大好处就是可以允许我们在运行期间获取对象的类型信息,下面我们通过一个例子来具体看一下。

首先我们在typeinfo.interfacea包下面新建一个接口A:

package typeinfo.interfacea;  public interface A { void f(); }

接着我们在typeinfo.packageaccess包下面新建一个类C,类C实现了接口A,并且我们还另外创建了几个用于测试的方法,注意下面几个方法的权限都是不同的。

package typeinfo.packageaccess;  import typeinfo.interfacea.A;  class C implements A {     public void f() { System.out.println("public C.f()"); }     public void g() { System.out.println("public C.g()"); }     protected void v () { System.out.println("protected C.v()"); }     void u() { System.out.println("package C.u()"); }     private void w() { System.out.println("private C.w()"); }  }  public class HiddenC {     public static A makeA() { return new C(); } }

在callHiddenMethod()方法中我们用到了几个新的API,其中getDeclaredMethod()根据方法名用于获取Class类指代对象自己声明的某个方法,然后我们通过调用invoke()方法就可以触发对象的相关方法:

package typeinfo;  import typeinfo.interfacea.A; import typeinfo.packageaccess.HiddenC;  import java.lang.reflect.Method;  public class HiddenImplementation {     public static void main(String[] args) throws Exception {         A a = HiddenC.makeA();         a.f();         System.out.println(a.getClass().getName());         // Oops! Reflection still allows us to call g():         callHiddenMethod(a, "g");         // And even methods that are less accessible!         callHiddenMethod(a, "u");         callHiddenMethod(a, "v");         callHiddenMethod(a, "w");     }      static void callHiddenMethod(Object a, String methodName) throws Exception {         Method g = a.getClass().getDeclaredMethod(methodName);         g.setAccessible(true);         g.invoke(a);     } }

从输出结果我们可以看出来,不管是public,default,protect还是private方法,通过反射类我们都可以自由调用。当然这里我们只是为了显示反射的强大威力,在实际开发中这种技巧还是不提倡。

public C.f() typeinfo.packageaccess.C public C.g() package C.u() protected C.v() private C.w()

上面我们只是测试了Method对象,感兴趣的读者在熟悉了反射的API之后,不妨测试一下Filed,这里我们就不重复了。

利用动态代理实现面向切面编程

aopspring提供的一个强大特性之一,AOP的意思是面向切面编程,就是说要分离和业务不相关的代码,当我们需要新增相关的事务的时候,我们不想对业务本身做修改。面向切面编程和面向对象变成相比到底有什么好处呢,我们通过一个例子来看一下,对于新手来说,常常会写出下面这样的代码:

public class Example1 {     public void execute() {         // 记录日志         Logger logger = Logger.getLog(...);         // 进行性能统计         PerfORManceUtil.startTimer(...);         // 权限检查         if (!user.hasPrevilege()) {             // 抛出异常         }         // 执行真正的业务         executeTransaction();         PerformanceUtil.endTimer();     } }

虽然我们上面真正要执行的业务只有executeTransaction(),但是日志,性能,权限相关的代码差不多要将真正的业务代码掩盖了。而且以后如果我们还有一个Example2,它同样需要实现相同的日志,性能,权限代码。这样当以后我们需要新增相关的逻辑检查的时候,我们需要所有Example进行重构,这显然不符合面向对象的一个基本原则-封装变化。

上面这个场景利用模板方法和装饰器模式都可以解决,在Spring中是通过动态代理来实现的,下面我们通过一个例子来模拟一下Spring中的AOP实现。

我们要实现的业务是,统计员工工资的时候程序所执行的时间以及检查用户的权限。首先我们先来实现Salary类,它里面包含一些实现统计员工工资的业务逻辑:

public interface SalaryInterface {     public void doSalary(); }  public class Salary implements SalaryInterface {     public void doSalary() {         ...     } }

通过InvocationHandler我们来实现动态代理,以后当我们调用obj的相关方法之前,都会通过invoke方法进行代理,而不会直接调用obj方法。

public class SimpleProxy implements InvocationHandler {     private Object obj;     private Object advice;      // 绑定代理对象     public Object bind(Object obj, Advice advice) {         this.obj = obj;         this.advice = advice;         return Proxy.newProxyInstance(obj.getClass().getClassLoader(),             obj.getClass().getInterfaces(), this)     }      // 实现代理     public Object invoke(Object proxy, Method method, Object[] args) throws Throwalbe {         Object result = null;         try {             advice.before();             result = method.invoke(obj, args);             advice.after();         } catch(Exception e) {             e.printStackTrace();         }         return result     } }

模拟Spring中的Advice接口:

public interface Advice {     public void before();     public void after(); }

实现TimeAdvice用于统计程序的执行时间:

public class TimeAdvice implements Advice {     long startTime;     long endTime;      @Override     public void before() {         startTime = System.nanoTime(); // 获取开始时间     }      @Override     public void after() {         endTime = System.nanoTime(); // 获取结束时间     } }

客户端调用代码如下:

public class Client {     public static void main(String[] args) {         SimpleProxy = new SimpleProxy();         SalaryInterface salaryInterface =             (SalaryInterface) simpleProxy.bind(new Salary(), new TimeAdvice());         salaryInterface.doSalary();     } }

如果我们现在需要新增权限控制,我们来实现ControlAdvie类:

public class ControlAdvice implements Advice {     @Override     public void before() {         if (...) {             ...         } else {             ...         }     }      @Override     public void after() {         ...     } }

而我们客户端的代码只需要改成simpleProxy.bind(new Salary(), new  ControlAdvie)就行了,而SimpleProxy本身不需要做任何的修改。

与注解相结合

在单元测试框架比如Junit中反射机制也得到了广泛的应用,即通过注解的方式。下面我们简单地来了解一下如何通过反射机制来获取相关方法的注解信息,比如说我们有下面这样一个业务场景,当用户在修改自己密码的时候,为了保证密码的安全性,我们要求用户的新密码要满足一些条件,比如说至少要包含一个非数字字符,不能与以前的密码相同之类的条件等。

import java.lang.annotation.*  @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface UserCase {     public int id();     public String description() default "no description"; }

下面是我们检测密码的工具类的实现:

public class PassWordUtils {     @UserCase(id=47, description="Password must contain at least one numeric")     public boolean validatePassword(String password) {         return (password.matches("\\w*\\d\\w*"));     }      @UserCase(id=48)     public String encryptPassword(String password) {         return new StringBuilder(password).reverse().toString();     }      @UserCase(id=49, description="New passwords can't equal previously used ones")     public boolean checkForNewPassword(List<String> prevPasswords, String password) {         return !prevPasswords.contains(password);     } }

利用反射我们可以写出更加清晰的测试代码,其中getDeclaredMethods()方法可以获取相关对象自己声明的相关方法,而getAnnotation()则可以获取Method对象的指定注解。

public class UseCaseTracker {     public static void trackUseCases(List<Integer> useCases, Class<?> cl) {         for(Method m : cl.getDeclaredMethods()) {             UseCase uc = m.getAnnotation(UseCase.class);             if(uc != null) {                 System.out.println("Found Use Case: " + uc.id() + " " + uc.description());                 useCases.remove(new Integer(uc.id()));             }         }          for(int i : useCases) {             System.out.println("Warning: Missing use case-" + i);         }     }      public static void main(String[] args) {         List<Integer> useCases = new ArrayList<Integer>();         Collections.addAll(useCases, 47, 48, 49, 50);         trackUseCases(userCases, PasswordUtils.class);     } }

解决泛型擦除

现在有下面这样一个业务场景,我们有一个泛型集合类List<Class<? extends  Pet>>,我们需要统计出这个集合类中每种具体的Pet有多少个。由于Java的泛型擦除,注意类似List<? extends  Pet>的做法肯定是不行的,因为编译器做了静态类型检查之后,到了运行期间JVM会将集合中的对象都视为Pet,但是并不会知道Pet代表的究竟是Cat还是Dog,所以到了运行期间对象的类型信息其实全部丢失了。p.s:  关于泛型擦除,我在上一篇文章里面有详细解释,感兴趣的朋友可以看一看。

为了实现我们上面的例子,我们先来定义几个类:

public class Pet extends Individual {     public Pet(String name) { super(name); }     public Pet() { super(); } }  public class Cat extends Pet {     public Cat(String name) { super(name); }     public Cat() { super(); } }  public class Dog extends Pet {     public Dog(String name) { super(name); }     public Dog() { super(); } }  public class EgyptianMau extends Cat {     public EgyptianMau(String name) { super(name); }     public EgyptianMau() { super(); } }  public class Mutt extends Dog {     public Mutt(String name) { super(name); }     public Mutt() { super(); } }

上面的Pet类继承自Individual,Individual类的的实现稍微复杂一点,我们实现了Comparable接口,重新自定义了类的比较规则,如果不是很明白的话,也没有关系,我们已经将它抽象出来了,所以不理解实现原理也没有关系。

public class Individual implements Comparable<Individual> {     private static long counter = 0;     private final long id = counter++;     private String name; // name is optional      public Individual(String name) { this.name = name; }      public Individual() {}      public String toString() {         return getClass().getSimpleName() + (name == null ? "" : " " + name);     }      public long id() { return id; }      public boolean equals(Object o) {         return o instanceof Individual && id == ((Individual)o).id;     }      public int hashCode() {         int result = 17;         if (name != null) {             result = 37 * result + name.hashCode();         }         result = 37 * result + (int) id;         return result;     }      public int compareTo(Individual arg) {         // Compare by class name first:         String first = getClass().getSimpleName();         String argFirst = arg.getClass().getSimpleName();         int firstCompare = first.compareTo(argFirst);         if (firstCompare != 0) {             return firstCompare;         }          if (name != null && arg.name != null) {             int secendCompare = name.compareTo(arg.name);             if (secendCompare != 0) {                 return secendCompare;             }         }          return (arg.id < id ? -1 : (arg.id == id ? 0 : 1));     } }

下面创建了一个抽象类PetCreator,以后我们通过调用arrayList()方法便可以直接获取相关Pet类的集合。这里使用到了我们上面没有提及的newInstance()方法,它会返回Class类所真正指代的类的实例,这是什么意思呢?比如说声明new  Dog().getClass().newInstance()和直接new Dog()是等价的。

public abstract class PetCreator {     private Random rand = new Random(47);      // The List of the different getTypes of Pet to create:     public abstract List<Class<? extends Pet>> getTypes();      public Pet randomPet() {         // Create one random Pet         int n = rand.nextInt(getTypes().size());          try {             return getTypes().get(n).newInstance();         } catch (InstantiationException e) {             throw new RuntimeException(e);         } catch (IllegalAccessException e) {             throw new RuntimeException(e);         }     }      public Pet[] createArray(int size) {         Pet[] result = new Pet[size];          for (int i = 0; i < size; i++) {            result[i] = randomPet();         }         return result;     }      public ArrayList<Pet> arrayList(int size) {         ArrayList<Pet> result = new ArrayList<Pet>();         Collections.addAll(result, createArray(size));         return result;     } }

接下来我们来实现上面这一个抽象类,解释一下下面的代码,在下面的代码中,我们声明了两个集合类,allTypes和types,其中allTypes中包含了我们呢上面所声明的所有类,但是我们具体的类型实际上只有两种即Mutt和EgypianMau,所以我们真正需要new出来的宠物只是types中所包含的类型,以后我们通过调用getTypes()便可以得到types中所包含的所有类型。

public class LiteralPetCreator extends PetCreator {     @SuppressWarnings("unchecked")     public static final List<Class<? extends Pet>> allTypes = Collections.unmodifiableList(         Arrays.asList(Pet.class, Dog.class, Cat.class, Mutt.class, EgyptianMau.class));      private static final List<Class<? extends Pet>> types = allTypes.subList(         allTypes.indexOf(Mutt.class), allTypes.size());      public List<Class<? extends Pet>> getTypes() {         return types;     } }

总体的逻辑已经完成了,***我们实现用来统计集合中相关Pet类个数的TypeCounter类。解释一下isAssignalbeFrom()方法,它可以判断一个反射类是某个反射类的子类或者间接子类。而getSuperclass()顾名思义就是得到某个反射类的父类了。

public class TypeCounter extends HashMap<Class<?>, Integer> {     private Class<?> baseType;      public TypeCounter(Class<?> baseType) {         this.baseType = baseType;     }      public void count(Object obj) {         Class<?> type = obj.getClass();         if (!baseType.isAssignableFrom(type)) {             throw new RuntimeException(                 obj + " incorrect type " + type + ", should be type or subtype of " + baseType);         }         countClass(type);     }      private void countClass(Class<?> type) {         Integer quantity = get(type);         put(type, quantity == null ? 1 : quantity + 1);         Class<?> superClass = type.getSuperclass();         if (superClass != null && baseType.isAssignableFrom(superClass)) {             countClass(superClass);         }     }      @Override     public String toString() {         StringBuilder result = new StringBuilder("{");          for (Map.Entry<Class<?>, Integer> pair : entrySet()) {             result.append(pair.geTKEy().getSimpleName());             result.append("=");             result.append(pair.getValue());             result.append(", ");         }          result.delete(result.length() - 2, result.length());         result.append("} ");         return result.toString();     } }

测试代码如下:

public static void main(String[] args) {     TypeCounter counter = new TypeCounter(Pet.class);     for (Pet pet : Pets.createArray(20)) {         System.out.println(pet.getClass().getSimpleName() + " ");         counter.count(pet);     }     System.out.println(counter); }

到此,相信大家对“Java反射机制怎么应用”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: Java反射机制怎么应用

本文链接: https://www.lsjlt.com/news/287052.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java反射机制怎么应用
    本篇内容主要讲解“Java反射机制怎么应用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java反射机制怎么应用”吧!反射基础p.s: 本文需要读者对反射机制的API有一定程度的了解,如果之前没...
    99+
    2023-06-17
  • java中的反射机制怎么应用
    Java中的反射机制可以应用于以下场景: 动态加载类:可以在运行时加载指定的类,而不是在编译时就确定类的类型。 创建对象:可...
    99+
    2023-10-23
    java
  • Java反射机制怎么使用
    今天小编给大家分享一下Java反射机制怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。反射的概述JAVA反射机制是在运...
    99+
    2023-06-30
  • Python反射机制怎么应用
    本文小编为大家详细介绍“Python反射机制怎么应用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Python反射机制怎么应用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。什么是反射在Python中,反射是指通...
    99+
    2023-07-05
  • Java 反射机制
    简介: Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个...
    99+
    2022-11-12
  • Java反射机制怎么理解
    本篇内容主要讲解“Java反射机制怎么理解”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Java反射机制怎么理解”吧! 简介定义:Java语言中 一种动态(运行时)访问、检测 & 修改它...
    99+
    2023-06-03
  • JAVA中怎么实现反射机制
    这期内容当中小编将会给大家带来有关JAVA中怎么实现反射机制,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。JAVA反射机制定义:  JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属...
    99+
    2023-06-17
  • 什么是java反射机制
    java:“一切即对象”,感觉java语言本身在不断践行着这句话。java反射机制的基础来源于一个Class类,我们可以通过这个类里面的方法来对每一个类进行读取、实例化等。对象表示或封装一些数据。一个类被加载后,jvm会创建一个对应该类的C...
    99+
    2019-08-24
    java入门 java 反射机制
  • java反射机制是什么
    这篇文章主要介绍了java反射机制是什么,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。Java的特点有哪些Java的特点有哪些1.Java语言作为静态面向对象编程语言的代表,...
    99+
    2023-06-14
  • Java中反射机制有什么用
    这篇文章主要为大家展示了“Java中反射机制有什么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Java中反射机制有什么用”这篇文章吧。反射:可以动态的获取指定类中的成员,以及建立类对象。好处...
    99+
    2023-06-17
  • java反射机制有什么作用
    本篇内容介绍了“java反射机制有什么作用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!本教程操作环境:windows7系统、java10版...
    99+
    2023-06-30
  • java反射机制的代码怎么写
    这篇文章主要介绍“java反射机制的代码怎么写”,在日常操作中,相信很多人在java反射机制的代码怎么写问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java反射机制的代码怎么写”的疑惑有所帮助!接下来,请跟...
    99+
    2023-07-06
  • Java反射机制详解
    目录类的声明周期不同阶段都可以获取类对象获取Class类对象的方式的场景class类对象的功能如何获取私有变量的值根据有无主方法判断进程和线程反射出现的背景(记住)反射出现的背景类的...
    99+
    2022-11-13
  • Java反射机制介绍
    1.通过反射,我们可以构建实例,得到成员变量的值,得到方法并调用。 还可以获得定义在成员变量、方法、方法参数上的注解。 接下来看代码实现,然后讲原理。 1)构建无参实例:通过反射调用...
    99+
    2022-11-13
  • java 反射机制初探
    最近再看书时,书中使用了java的动态代理机制,随即在网上搜了些文章看了一下,既然有动态代理那就有静态代理,所谓静态代理,就是在你些的代理类中需要使用到具体的被代理类。而所谓动态代理,则不需要在代理类中使用到被代理类,根本不知道起要代理那个...
    99+
    2023-06-03
  • java反射机制及常用应用场景是什么
    这篇文章主要介绍“java反射机制及常用应用场景是什么”,在日常操作中,相信很多人在java反射机制及常用应用场景是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”java反射机制及常用应用场景是什么”的疑...
    99+
    2023-06-29
  • Golang反射机制怎么使用
    本文小编为大家详细介绍“Golang反射机制怎么使用”,内容详细,步骤清晰,细节处理妥当,希望这篇“Golang反射机制怎么使用”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。介绍反射的本质就是在程序运行的时候,获...
    99+
    2023-06-30
  • 如何使用Java反射机制
    这篇文章主要介绍“如何使用Java反射机制”,在日常操作中,相信很多人在如何使用Java反射机制问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何使用Java反射机制”的疑惑有所帮助!接下来,请跟着小编一起来...
    99+
    2023-06-15
  • JAVA中怎么实现反射机制功能
    本篇文章为大家展示了JAVA中怎么实现反射机制功能,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。JAVA基础--JAVA反射机制详解   JAVA反射机制是在运行状态中...
    99+
    2023-06-17
  • java反射机制最详解
    目录java反射机制什么是反射?反射的功能:反射常用类:1.Class枚举类2.Constructor构造器3.Method方法类4.Field变量类反射运行指示图通过反射获取对象总结java反射机制 什么是反射? 在java开发中有一个...
    99+
    2020-08-07
    java java反射机制
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作