当前位置: 首页 > news >正文

手机网站仿站ps培训

手机网站仿站,ps培训,望野王,中国域名注册局官网1.什么是反射机制 反射允许(在运行时动态地)对封装类的字段、方法、构造函数的信息进行编程访问 在我们的代码中#xff0c;使用构造器直接生成对象、直接访问对象、对象的成员等方式#xff0c;是清晰直观的。但在有些场景中#xff0c;需要在运行时动态地操作这些成员使用构造器直接生成对象、直接访问对象、对象的成员等方式是清晰直观的。但在有些场景中需要在运行时动态地操作这些成员比如在运行时根据数据库中提供的类名或方法名或者基于字符串变量来动态实例化对象或调用方法时直接访问的方式就不再适用了。反射机制恰好提供了解决这类需求的能力其关键在于一个特殊的对象我们称之为类对象---Class Object。 A.Class对象: 要学习反射首先要对Class对象有一个清晰的认识Class对象是什么 Class是个类java.lang.Class用来描述字节码文件的。Class对象是由Java虚拟机JVM在加载类时自动创建的用于存储类的信息。 Class对象用于存储关于类的元数据包括但不限于以下信息 1. 类的名称包括简单名称和完全限定名包含包名。 2. 访问修饰符类的访问级别public, private, protected。 3. 包信息类所属的包。 4. 父类信息该类的直接父类如果有。 5. 接口信息该类实现的所有接口。 6. 构造方法类的所有构造器信息包括它们的参数类型。 7. 字段信息类中声明的所有字段包括公有、保护、默认包访问和私有字段。 8. 方法信息类中声明的所有方法包括公有、保护、默认包访问和私有方法。 9. 注解信息类、字段、方法上的注解信息。 10. 类型参数如果类是泛型的包含泛型的类型参数信息。 11. 静态成员包括静态方法和静态字段。 12. 枚举常量如果类是一个枚举类型包含所有枚举常量的信息。 13. 是否为接口、数组、枚举或注解类型Class对象提供方法来检查被表示的类或接口是否为特定的类型如接口、数组、枚举或注解。 14. 类加载器信息加载该类的类加载器的信息。 通过Class对象我们就能访问类的结构以及对类本身和它的实例进行操作。虚拟机创建Class对象的过程是这样的当我们编写一个类并完成编译之后编译器会将其转化成字节码存储在.class后缀的文件中接下来在类的加载过程中虚拟机利用Class Loader读取这个.class文件将其中的字节码加载到内存方法区Metaspace中并基于这些信息创建相应的Class对象。由于每个类在JVM中只加载一次在这个类的生命周期内所以每个类都对应着一个唯一的Class对象。 虽然每个类只加载一次但这并不意味着它们永远不会被垃圾回收。一个类可以被卸载但这种情况相对罕见发生在类的ClassLoader被垃圾回收时。这通常意味着该类的所有实例都已经被垃圾回收并且加载该类的类加载器也没有其他引用。如果一个类被卸载其类加载器被垃圾回收然后你的应用程序再次尝试使用该类JVM将需要重新加载该类。这是因为从JVM的角度来看先前加载的类版本已经不再存在。类的重新加载通常是通过新的类加载器实例进行的这意味着即使是相同的类文件也被视为一个全新的类。 要使用反射要先获取class对象获取class对象的三种方式 Class.forName(全类名) 使用CLass 的forName静态方法这种方法用于在运行时动态加载指定的类并返回该类的Class对象实例通常用于类名在编译时不可知的场景中通过这种方法会触发类的初始化。 public static Class? toClassConfident(String name) {try {return Class.forName(name, false, getDefaultClassLoader());} catch (ClassNotFoundException e) {try {return Class.forName(name);} catch (ClassNotFoundException ex) {throw ExceptionUtils.mpe(找不到指定的class请仅在明确确定会有 class 的时候调用该方法, e);}}} 使用类字面常量也就是 类的名称.class。这也是获取CLass对象最直接的方式它在编译时就确定了具体的类属于静态引用。使用这种方式获得类的Class对象时不会立即触发类的初始化类中的静态初始化块内的代码不会被执行只有在你访问类的静态成员或者创建该类的实例的时候才会被触发。对象.getClass()如果你已经有了某个类的实例对象可以调用该对象的getClass方法来获取它的Class对象。我们在编译阶段无法准确地判断Class对象的确切类型。 B.Class类中常用的API 在java.lang.Class类中有多个方法可以用来获取类的构造器、成员方法和成员变量。这些方法允许你在运行时反射地访问类的这些成员。下面是这些方法的概览 ### 获取构造器 可以获取构造函数的修饰符---public和private等有对应的常量字段值 - getConstructor(Class?... parameterTypes)返回一个Constructor对象它反映了此Class对象所表示的类的指定公共构造器。 - getConstructors()返回包含某些Constructor对象的数组这些对象反映了此Class对象表示的类的所有公共构造器。 - getDeclaredConstructor(Class?... parameterTypes)返回一个Constructor对象它反映此Class对象表示的类或接口的指定构造器。 - getDeclaredConstructors()返回包含某些Constructor对象的数组这些对象反映了此Class对象表示的类声明的所有构造器。 ### 获取成员方法 - getMethod(String name, Class?... parameterTypes)返回一个Method对象它反映此Class对象所表示的类或接口的指定公共成员方法。 - getMethods()返回一个包含Method对象的数组这些对象反映了此Class对象所表示的类或接口的所有公共方法包括由类或接口声明的那些方法以及从超类和超接口继承的方法。 - getDeclaredMethod(String name, Class?... parameterTypes)返回一个Method对象它反映此Class对象表示的类或接口的指定声明的方法。 - getDeclaredMethods()返回包含Method对象的数组这些对象反映了此Class对象表示的类或接口声明的所有方法。 ### 获取成员变量 - getField(String name)返回一个Field对象它反映此Class对象所表示的类或接口的指定公共成员变量。 - getFields()返回一个包含Field对象的数组这些对象反映了此Class对象所表示的类或接口的所有可访问的公共字段。 - getDeclaredField(String name)返回一个Field对象它反映此Class对象表示的类或接口的指定声明的字段。 - getDeclaredFields()返回包含Field对象的数组这些对象反映此Class对象表示的类或接口声明的所有字段。 这些反射API方法使得在运行时动态地访问和操作类的构造器、方法和字段成为可能。使用这些方法时需要处理NoSuchMethodException、NoSuchFieldException等异常这些异常在请求的成员不存在时抛出。此外访问私有成员如私有构造器、方法或字段时还需要通过setAccessible(true)方法来取消Java语言访问检查。使用反射无法在编译时对错误进行检测要特别注意其中的错误处理机制 2.框架中使用反射的案例 注解和反射是所有框架的底层 JAVA EE中用到反射的地方 以下是一些典型的使用反射的Java EE功能 1. 依赖注入DI 依赖注入是Java EE平台的核心特性之一允许运行时动态地向组件提供其依赖。这通常是通过反射来实现的框架利用反射来检查组件的注解如Inject然后动态地将实例注入到组件的属性或方法中。  2. 数据持久化JPA Java 持久化 APIJPA利用注解如Entity, Column等来映射Java对象到数据库表。框架在运行时使用反射来读取这些注解从而了解如何将对象的属性映射到对应的数据库列。此外反射还被用于动态创建查询结果的实例。 3. Bean验证Bean Validation Java EE提供了一套基于注解的约束声明和验证机制允许开发者在实体类上声明约束如NotNull, Size等并在运行时自动验证这些约束。这个过程涉及到使用反射读取这些注解并根据它们来验证对象的状态。  4. Web服务JAX-RS和JAX-WS Java EE支持创建RESTful通过JAX-RS和SOAP通过JAX-WSWeb服务。这些框架使用反射来处理使用特定注解如Path, GET, WebService等标记的类和方法以动态地将HTTP请求映射到相应的服务方法上。  5. 拦截器Interceptors 拦截器允许在业务方法执行前后自动执行代码这是通过标记方法或类与特定的注解如Interceptor来实现的。Java EE容器在运行时使用反射来识别和处理这些拦截器。  6. 事件和监听器 Java EE支持基于事件的编程模型允许组件监听和响应应用程序中发生的事件。这包括使用注解如Observes标记监听方法容器将使用反射来调用相应的方法响应事件。  7. 管理和配置 Java EE平台还支持使用注解来配置和管理应用程序组件如EJB的Stateless和Singleton。容器通过反射读取这些注解来管理组件的生命周期和依赖关系。 Spring中用到反射的地方 1. 依赖注入DI Spring框架的核心功能之一是依赖注入。Spring容器通过反射来创建bean的实例并注入所需的依赖。具体来说Spring使用反射来 - 调用构造函数创建对象实例。 - 通过setter方法或直接访问字段来注入依赖。 - 调用初始化方法和销毁方法。 2. 面向切面编程AOP Spring AOP使用代理模式来实现横切关注点的模块化这通常涉及到反射。例如当使用JDK动态代理时Spring通过反射调用目标对象的方法。对于基于CGLIB的代理虽然主要通过字节码增强实现但在创建代理对象和调用方法时仍可能用到反射。 3. 事件处理 Spring的事件发布/订阅模型允许bean监听和响应应用程序事件。Spring使用反射来调用事件监听器上的处理方法。 4. 数据绑定 Spring MVC等模块通过反射支持将请求参数绑定到控制器方法的参数上以及将对象属性绑定到表单字段等。这包括使用反射来动态调用getter和setter方法以及直接访问对象的字段。 5. Bean属性的访问和操作 Spring使用BeanWrapper接口来操作bean的属性这背后也是基于反射实现的。这使得Spring能够动态地读取和修改bean的属性值无论是通过直接字段访问还是通过访问器方法。 6. 注解处理 Spring大量使用注解来提供配置信息。Spring容器在启动时使用反射来读取类、方法、字段上的注解以解析这些元数据并据此执行相应的逻辑如标注Autowired进行自动装配Transactional管理事务等。 7. 方法执行 Spring表达式语言SpEL、事务管理、JDBC模板等多个地方使用反射来动态执行方法。例如SpEL可以评估对对象属性和方法的调用这需要反射来实现。 总结 反射是Spring框架实现其灵活、动态特性的基石之一。它允许Spring在运行时动态地创建对象、注入依赖、处理注解、执行方法等大大增强了Spring的功能和灵活性。不过反射的使用也可能带来性能上的考量因此Spring在内部实现中做了大量优化以确保其性能。 其他运用到反射的idea的代码提示、EasyExcel框架等框架 Java中有许多库和框架在其内部实现中广泛使用反射机制来提供灵活、动态的功能。这些库利用反射实现了从简单的对象操作到复杂的框架功能如动态代理、依赖注入、序列化和反序列化等。以下是一些常见的Java库和框架它们在不同程度上使用了反射 1. Spring Framework Spring框架在其核心功能如依赖注入DI、面向切面编程AOP、数据访问等方面广泛使用反射。例如Spring通过反射来动态创建bean、注入依赖、以及管理bean的生命周期。 2. Hibernate / JPA Hibernate是一个对象关系映射ORM框架它允许开发者通过Java对象来操作数据库。Hibernate使用反射来动态地映射实体类到数据库表以及执行查询结果到对象实例的转换。 3. MyBatis MyBatis是另一个流行的持久层框架它提供了对象和SQL之间的映射。MyBatis使用反射来填充对象的属性值以及在执行动态SQL时处理参数。 4. Gson / Jackson Gson和Jackson是两个广泛使用的JSON处理库它们支持对象的序列化和反序列化。这些库使用反射来动态地访问对象的属性实现对象与JSON之间的转换。 5. JUnit JUnit是一个流行的单元测试框架它使用反射来动态地调用测试方法。JUnit利用反射来查找并执行标记有Test注解的方法以及处理Before和After等生命周期相关的注解。 6. Mockito Mockito是一个用于模拟对象行为的库广泛用于单元测试中。它使用反射来动态创建模拟对象mocks和存根对象stubs以及拦截对这些对象方法的调用。 7. Java Reflection API 尽管不是一个“第三方库”但值得一提的是Java自身的反射APIjava.lang.reflect包它提供了检查和修改运行时Java应用程序行为的能力。许多上述提到的框架和库底层都依赖于这个API。 总结 反射是Java编程中一个强大的工具允许运行时的动态类型查询和操作。许多流行的Java库和框架都利用了反射来提供灵活、动态的功能使得开发者能够以更简洁、高效的方式构建应用程序。然而反射也应谨慎使用因为它可能导致性能下降和安全性问题。 3.项目中使用到反射的案例 getTaoBaoFields方法 public static String getTaoBaoFields(String path) throws Exception {StringBuilder stringBuilder new StringBuilder();Class clazz Class.forName(path);for (Field field : clazz.getDeclaredFields()) {if (field.getDeclaredAnnotations().length 0) {continue;}ApiField annotation field.getAnnotation(ApiField.class);stringBuilder.append(annotation.value()).append(,);ApiListField annotationList field.getAnnotation(ApiListField.class);if (annotationList ! null) {stringBuilder.append(annotationList.value()).append(,);}}return stringBuilder.deleteCharAt(stringBuilder.length() - 1).toString();}#在调用淘宝API的时候要用到 订单相关接口 TradeFullinfoGetRequest request new TradeFullinfoGetRequest(); request.setFields(BusinessUtil.getTaoBaoFields(Trade.class.getName()));#退款相关接口RefundMessagesGetRequest req new RefundMessagesGetRequest();req.setRefundId(Long.valueOf(refundId));req.setPageNo(1L);req.setPageSize(100L);req.setFields(BusinessUtil.getTaoBaoFields(com.taobao.api.domain.RefundMessage));#业务逻辑调用淘宝不同的业务的API需要传入不同的字段通过工具类传入类名拼接不同的字段 这个getTaoBaoFields方法设计用于提取和拼接指定类中被ApiField或ApiListField注解标记的字段名称。这种方法通常用于与阿里巴巴淘宝API交互的场景其中ApiField和ApiListField可能是自定义注解用于标记字段对应的API参数或字段名称。方法的工作流程如下 ### 输入参数 - String path这是一个字符串参数代表一个完全限定的类名即包括包名的类名。方法将使用这个参数来加载对应的类。 ### 过程 1. **加载类**通过Class.forName(path)动态加载传入路径指定的类。这一步会抛出ClassNotFoundException如果给定的类路径无法找到这是由throws Exception在方法签名中声明的一部分来捕获的。 2. **遍历字段**使用clazz.getDeclaredFields()获取这个类声明的所有字段包括私有字段但不包括继承的字段。 3. **检查注解**对于每个字段首先检查它是否有声明的注解。如果一个字段没有任何注解field.getDeclaredAnnotations().length 0则跳过该字段。 4. **处理ApiField注解**如果字段被ApiField注解标记使用field.getAnnotation(ApiField.class)获取这个注解实例并将注解的value值追加到StringBuilder对象中。ApiField注解的value属性可能表示与该字段对应的API参数名。 5. **处理ApiListField注解**类似地检查字段是否被ApiListField注解标记并处理。ApiListField注解的value属性可能表示一组与该字段相关的API参数名。 6. **拼接字符串**字段名称通过注解指定的值之间用逗号,分隔。 ### 输出 - 方法返回一个字符串包含了类中所有被ApiField或ApiListField注解标记的字段名称或指定的API参数名字段名之间用逗号分隔。 ### 异常处理 - 方法签名中的throws Exception表示调用者需要处理可能发生的所有异常包括反射操作中可能抛出的异常如ClassNotFoundException。 ### 示例用途 这个方法可能用于生成请求淘宝开放平台API时需要的字段列表字符串。通过反射和注解可以动态地根据类的定义来构建这个列表而不需要硬编码这样做提高了代码的灵活性和可维护性。 反射工具类 NoArgsConstructor(access AccessLevel.PRIVATE) public final class ReflectionUtils {private static final Field[] NO_FIELDS {};/*** Cache for {link Class#getDeclaredFields()}, allowing for fast iteration.*/private static final MapClass?, Field[] declaredFieldsCache new ConcurrentReferenceHashMap(256);/*** This variant retrieves {link Class#getDeclaredFields()} from a local cache* in order to avoid the JVMs SecurityManager check and defensive array copying.** param clazz the class to introspect* return the cached array of fields* see Class#getDeclaredFields()*/public static Field[] getDeclaredFields(Class? clazz) {Assert.notNull(clazz, Class must not be null);Field[] result declaredFieldsCache.get(clazz);if (result null) {result clazz.getDeclaredFields();declaredFieldsCache.put(clazz, (result.length 0 ? NO_FIELDS : result));}return result;}/*** Make the given field accessible, explicitly setting it accessible if* necessary. The {code setAccessible(true)} method is only called* when actually necessary, to avoid unnecessary conflicts with a JVM* SecurityManager (if active).** param field the field to make accessible* see java.lang.reflect.Field#setAccessible*/public static void makeAccessible(Field field) {if ((!Modifier.isPublic(field.getModifiers()) ||!Modifier.isPublic(field.getDeclaringClass().getModifiers()) ||Modifier.isFinal(field.getModifiers())) !field.isAccessible()) {field.setAccessible(true);}}/*** 把clazz所有字段不包括内嵌对象的字段用 , 拼接起来*/public static String getDeclaredFieldsStr(Class? clazz) {Field[] fields getDeclaredFields(clazz);return Stream.of(fields).peek(ReflectionUtils::makeAccessible).map(Field::getName).collect(Collectors.joining(,));}/*** 把clazz所有字段包括内嵌对象的字段用 , 拼接起来*/public static String getAllDeclaredFieldsStr(Class? clazz) {SetField allFields getAllDeclaredFields(clazz);return allFields.stream().peek(ReflectionUtils::makeAccessible).map(Field::getName).collect(Collectors.joining(,));}/*** 获取clazz所有字段包括类属性为对象的字段*/public static SetField getAllDeclaredFields(Class? clazz) {Field[] fields getDeclaredFields(clazz);SetField allFields Sets.newHashSet(Arrays.asList(fields));Stream.of(fields).filter(v - !BASE_TYPE.test(v.getType())).forEach(v - {allFields.addAll(getBeanTypeFields(v));allFields.addAll(getCollectionTypeFields(v));});return allFields;}private static SetField getBeanTypeFields(Field field) {Class? clazz field.getType();if (BASE_TYPE.test(clazz) || COLLECTION_TYPE.test(clazz)) {return Collections.emptySet();}return getAllDeclaredFields(clazz);}private static SetField getCollectionTypeFields(Field field) {Class? clazz field.getType();if (!COLLECTION_TYPE.test(clazz)) {return Collections.emptySet();}Type genericType field.getGenericType();// fixed java 11 // if (genericType instanceof ParameterizedTypeImpl) { // ParameterizedTypeImpl parameterizedType (ParameterizedTypeImpl) genericType; // Type[] actualTypeArguments parameterizedType.getActualTypeArguments(); // Type actualTypeArgument actualTypeArguments[0]; // String typeName actualTypeArgument.getTypeName(); // if (!StringUtils.hasText(typeName)) { // return Collections.emptySet(); // } // // try { // return getAllDeclaredFields(Class.forName(typeName)); // } catch (ClassNotFoundException e) { // } // }return Collections.emptySet();}public static final SafePredicateClass? BASE_TYPE input - {if (input.equals(byte.class) || input.equals(Byte.class)) {return true;}if (input.equals(short.class) || input.equals(Short.class)) {return true;}if (input.equals(int.class) || input.equals(Integer.class)) {return true;}if (input.equals(long.class) || input.equals(Long.class)) {return true;}if (input.equals(float.class) || input.equals(Float.class)) {return true;}if (input.equals(double.class) || input.equals(Double.class)) {return true;}if (input.equals(boolean.class) || input.equals(Boolean.class)) {return true;}if (input.equals(char.class)) {return true;}if (input.equals(String.class)) {return true;}return false;};public static final SafePredicateClass? COLLECTION_TYPE input - {if (input.equals(List.class)) {return true;}if (input.equals(Set.class)) {return true;}return false;};} 这个ReflectionUtils类是一个工具类使用Java反射API为操作Java类的字段Field提供了便利方法。这个类被设计为final并且带有一个私有的构造函数通过NoArgsConstructor(access AccessLevel.PRIVATE)注解实现这样做是为了防止创建它的实例明确表明这是一个纯粹的工具类。下面是这个类提供的一些关键功能的解释 ### 缓存反射字段 - **字段缓存**使用ConcurrentReferenceHashMap来缓存类的声明字段提高了反复访问同一类字段时的性能。这避免了频繁调用Class.getDeclaredFields()方法后者可能会因为JVM的安全管理器检查和防御性数组复制而产生性能开销。 ### 字段访问 - **getDeclaredFields(Class? clazz)**获取给定类的所有声明字段不包括继承的字段结果从本地缓存获取以提高性能。 - **makeAccessible(Field field)**如果需要将给定的字段设置为可访问的即使它是私有的。这个方法在访问非公共字段时很有用同时避免了不必要的setAccessible(true)调用减少了与JVM安全管理器的冲突概率。 - **getDeclaredFieldsStr(Class? clazz)和getAllDeclaredFieldsStr(Class? clazz)**将类的所有声明字段或包括嵌套对象字段的名称用逗号分隔拼接成字符串。这可能用于生成日志、调试输出等。 ### 支持复杂类型字段 - **处理集合和自定义对象类型字段**通过检查字段类型getAllDeclaredFields(Class? clazz)方法能够递归地处理自定义对象类型的字段以及集合类型的字段。这允许深入地分析类的结构获取所有相关字段包括嵌套对象内的字段。 ### 工具方法 - **类型判断**通过BASE_TYPE和COLLECTION_TYPE这两个SafePredicate这里假定是某种自定义的或库中的断言接口来判断一个类是否为基本类型或集合类型。这对于区分应如何处理不同类型的字段很有用例如避免尝试进一步分析基本类型或字符串类型的字段。 整个ReflectionUtils类展示了如何利用Java反射API进行高级的反射操作包括字段访问、权限修改和类型分析。这类工具类在需要深入处理Java对象内部结构的场景中非常有用如框架开发、序列化/反序列化库、动态数据绑定等。
http://www.zqtcl.cn/news/970676/

相关文章:

  • 做精美得ppt网站知乎厦门官网建设公司
  • 做一个中型网站需要多少钱网站建设的费用是不是含税的
  • 网站上的广告是怎么做的连云港 网站 建设
  • 济南做网站的好公司有哪些怎么做自己的app软件
  • 淄博网站建设团队企业门户网站有哪些
  • 东莞网站建设 织梦建设茶叶网站的目的
  • 做网站的背景图片要多大做房产网站
  • 洛阳做网站公司在哪无锡网络营销推广软件
  • 医疗机械网站怎么做无锡短视频seo
  • 做网站建设哪家公司好如何营销推广
  • 陕西百威建设监理有限司网站做吉祥物设计看什么网站
  • 网络营销站点推广的方法高端网站开发价格
  • 内部优惠券网站怎么做最新国际新闻事件今天
  • 辽宁大学网站怎么做app开发用什么编程语言
  • 3d建模在线制作网站阿里云域名注册官网
  • 创建网站大约多少钱网站建设排序题
  • 大庆做网站找谁机构编制网站建设
  • 网站标题特效网站弹出的对话框怎么做
  • 找深圳网站建设wordpress 页面背景
  • 企业网站怎么维护上海注册建网站
  • 四川省建设工程造价信息网站便宜做网站价格
  • 医院网站优化策划网站开发的项目需求
  • 网站优化公司服务直播软件怎么开发
  • 网站建设 有道翻译织梦修改网站后备份
  • 苏州网联盛网站建设做最好的在线看片网站
  • 一个空间怎么放2个网站陕西城乡住房建设部网站
  • 如何购买虚拟主机做网站企业查名
  • 动易网站默认密码网站怎么做 吸引人
  • 站长工具国产2023二级建造师证书查询官方网站
  • 微信小程序联盟网站北京网站建设华大