`

[转]Reflection on Tiger

阅读更多
Reflection on Tigerby Michael Nascimento Santos
03/08/2004
from http://today.java.net/lpt/a/46



Much has been written about the new language features in J2SE 1.5, Tiger. Many, such as the introduction of enums, generics, and metadata, involve changing bytecode. These additions to the language require modifications to existing APIs. One of the APIs most radically affected by these changes is the Reflection API. Reflection has existed since JDK 1.1, and many frameworks, libraries, and utilities have been built upon it. This article examines the modifications to the Reflection API that are now available to the public as part of JDK 1.5 beta 1, and shows how you can take advantage of them in your code.

New Kids on the Hierarchy
A few interfaces and exceptions have been added to java.lang.reflect, as well as to java.lang. Some "old classes" -- such as Class, Method, Constructor, and others -- have been retrofitted to implement them. In this section we will look at these added interfaces.

Reflections on Metadata
The AnnotatedElement interface is implemented by any class that represents an element that may contain annotations (also known as metadata), as specified by JSR-175. The Class, Constructor, Field, Method, and Package each have been modified to implement AnnotatedElement. The interface specifies methods to retrieve all annotations, annotations by type, annotations declared only in a particular class (i.e., not including superclasses), and also a method to query whether or not a class contains an annotation of a specific type. The following code snippets demonstrate the use of these methods. Note that you must have some knowledge about how annotations work to fully understand this example.

First, create a custom annotation that we will later examine with reflection.


package net.java.reflection;

import java.lang.annotation.Retention;
import static java.lang.annotation.RetentionPolicy.*;

@Retention(RUNTIME)
public @interface SampleAnnotation {
   public String value();
}

Next, create a class AnnotatedElementTest and mark it and an instance method aMethod() as being annotated with the SampleAnnotation class you just created:
@SampleAnnotation("AnnotatedElementTest") 

public class AnnotatedElementTest { 
   @SampleAnnotation("aMethod") 
   @Deprecated 

   public void aMethod() { 
   } 
//... 
} 

You can detect and get a handle to the Class annotations by creating a Class object and invoking the methods is AnnotationPresent() and getAnnotations(). You can repeat the process for the annotated method. The getAnnotations() method is used to retrieve all of the annotations this method has that are retained until runtime. When you compile and run AnnotatedElementTest, you will notice that @Deprecated is not shown. That is because it's only part of the source code and it's not present, even in the class file. Here's the listing for AnnotatedElementTest.

package net.java.reflection; 

import java.lang.annotation.Annotation; 
import java.lang.reflect.Method; 

@SampleAnnotation("AnnotatedElementTest") 

public class AnnotatedElementTest { 

   @SampleAnnotation("aMethod") 
   @Deprecated 

   public void aMethod() { 
   } 

   public static void main(String[] args) throws Exception { 
      Class clazz = AnnotatedElementTest.class; 
      System.out.println(clazz.isAnnotationPresent(SampleAnnotation.class)); 
      System.out.println(clazz.getAnnotation(SampleAnnotation.class)); 
      Method method = clazz.getMethod("aMethod"); 
      for (Annotation a : method.getAnnotations()) { 
         System.out.println(a); 
      } 
   } 
} 
Working with Generics
The following additions to the Reflection APIs allow you to obtain information about generics.





    Type: This new marker interface was introduced in order to represent all of the types that can be used in Java. These include raw types; i.e., Classes, parameterized types, array types, type variables, and primitive types. java.lang.Class, for example, has been retrofitted to implement this new interface.



    TypeVariable: This interface represents type variables of all kinds. For example, in Class, T is a type variable. There are methods for obtaining the name of the variable, its bounds (superclasses) and its GenericDeclaration -- the last one is explained below.



    GenericDeclaration: This interface, implemented by Class, Constructor and Method, indicates they might declare TypeVariables. It defines a sole method, getTypeParameters(), returning an array containing all of the TypeVariables in the order in which they were originally declared.



    ParameterizedType: Represents a parameter type with a generic type, such as Class. It has methods that allow retrieval of the actual type arguments (T, in the previous example), to get the enclosing class of this type, if any, and to retrieve the raw type declared (Class, in this case).



    GenericArrayType: Represents an array of a generic type, such as T[]. It has a method that allows one to retrieve the component type of the array (in this case, T).



    WildcardType: Represents a type that uses wildcards, such as ? or ? extends T. The methods provided return the lower bounds of the type (in T super Integer, Integer would be a lower bound) and the upper bounds (for ?, Object is the upper bound).



    MalformedParameterizedTypeException: This exception is thrown if the parameterized type cannot be instantiated at runtime for some reason. It is a RuntimeException.



    GenericSignatureFormatError: This exception indicates a low-level bytecode error and it should be rare. However, using JDK 1.5 beta 1, is possible to get this error when you try to call getTypeParameters() in an instance of a system class that defines a non-trivial type variable, such as >. An example of such a class instance is TypeVariable.class.



    TypeNotPresentException: This exception can occur when some code tries to access a type using its name, but it cannot be found. It is the only new exception related to reflection that is not defined in the expected package, but in java.lang.





Here is an example of how to use some of these classes and interfaces related to generics.

package net.java.reflection; 

import java.lang.reflect.GenericArrayType; 
import java.lang.reflect.Method; 
import java.lang.reflect.ParameterizedType; 
import java.lang.reflect.Type; 
import java.lang.reflect.TypeVariable; 
import java.lang.reflect.WildcardType; 
import java.util.Map; 

// This class declaration defines a type variable T 
public class GenericsTest { 

   // This method is used in the reflection example below 
   public void aMethod(Class<? extends T> clazz1, 
                       Class clazz2, T[] ts) { 
   } 

   // Prints information about a type variable 

   private static void print(TypeVariable v) { 
      System.out.println("Type variable"); 
      System.out.println("Name: " + v.getName()); 
      System.out.println("Declaration: " + 
                         v.getGenericDeclaration()); 
      System.out.println("Bounds:"); 
      for (Type t : v.getBounds()) { 
         print(t); 
      } 
   } 
   // Prints information about a wildcard type 
   private static void print(WildcardType wt) { 
      System.out.println("Wildcard type"); 
      System.out.println("Lower bounds:"); 
      for (Type b : wt.getLowerBounds()) { 
         print(b); 
      } 

      System.out.println("Upper bounds:"); 
      for (Type b : wt.getUpperBounds()) { 
         print(b); 
      } 
   } 

   // Prints information about a parameterized type 
   private static void print(ParameterizedType pt) { 
      System.out.println("Parameterized type"); 
      System.out.println("Owner: " + pt.getOwnerType()); 
      System.out.println("Raw type: " + pt.getRawType()); 
      
      for (Type actualType : pt.getActualTypeArguments()) { 
         print(actualType); 
      } 
   } 

   // Prints information about a generic array type 
   private static void print(GenericArrayType gat) { 
      System.out.println("Generic array type"); 
      System.out.println("Type of array: "); 
      print(gat.getGenericComponentType()); 
   } 

   /** 
    * Prints information about a type. The nested 
    * if/else-if chain calls the 
    * appropriate overloaded print method for the 
    * type. If t is just a Class, 
    * we print it directly. 
    */ 

   private static void print(Type t) { 
      if (t instanceof TypeVariable) { 
         print((TypeVariable)t); 
      } else if (t instanceof WildcardType) { 
         print((WildcardType)t); 
      } else if (t instanceof ParameterizedType) { 
         print((ParameterizedType)t); 
      } else if (t instanceof GenericArrayType) { 
         print((GenericArrayType)t); 
      } else { 
         System.out.println(t); 
      } 
   } 

   public static void main(String[] args) throws Exception { 
      // Some classes we are going to play with 
      Class[] classes = new Class[] {Class.class, Map.class, 
                                     GenericsTest.class}; 

      // Iterate the array for each class instance... 
      for (Class clazz : classes) { 
         // Prints its name and ... 
         System.out.println("Class: " + clazz); 

         // Iterate for each type variable defined by this class 
         for (TypeVariable v : clazz.getTypeParameters()) { 
            print(v); 
         } 

         System.out.println(); 
      } 
      System.out.println("Reflective information " + 
                         "about the parameters of aMethod"); 
      // Iterate for each method... 
      for (Method method : GenericsTest.class.getDeclaredMethods()) { 
         // Until we find aMethod 
         if (method.getName().equals("aMethod")) { 
            // Then, go over all parameters ... 
            for (Type t : method.getGenericParameterTypes()) { 
               System.out.println("Parameter:"); 
               // And print reflexive information about them 
               print(t); 
               System.out.println(); 
            } 
            break; 
         } 
      } 
   } 
} 
Changes to the "Old" API
One thing most people erroneously assume is that they will be able to extract information about the actual binding of a type variable once they have a variable of a parameterized type. For example, if there is a method that accepts as a parameter that is declared as Collection, inside of the method it is impossible to know what type actually is being used for E. That happens because generics are implemented in Java using erasure, which means that the actual type information is lost. There is no way to find what type was actually used to represent a type variable, even if you think that intentionally adding a method with this information would be possible. An example is shown below:

public class GenericClass { 
   // some code 
   public Class getElementType() { 
      return E.class; 
   } 
   //more code 
} 

This code doesn't compile, since information about E is defined in runtime and erasured, while a reference to .class is statically resolved. That said, let's consider which changes have been made to the "old classes" that have been part of the API before Tiger:


[list]


Member: This interface, which is implemented by Class, Field and Method, now defines a new method, isSynthetic(). According to its Javadoc, it "Returns true if this member was introduced by the compiler and returns false otherwise".



Proxy: getProxyClass() had its signature changed to accept a varargs Class parameter for interfaces instead of the original array one.



Class: java.lang.Class now looks scarier than ever if you don't have a clue about generics. Even its declaration has changed to include a type variable, T, for the actual class it represents. This allows some interesting reflexive constructions and methods to appear, such as the new cast(Object) method. This method takes an object and returns an instance of T. In code, it works like this:

Class cs = Serializable.class; 
// more code ... 
Object o = ...; 
Serializable s = cs.cast(o); 

Several methods that accepted arrays of Class have been retrofitted to support varargs, such as getConstructor, getDeclaredConstructor, getDeclaredMethod, and getMethod. This makes it easier to call these methods, as shown below:
// This now works for no-args methods: 
// It is equivalent to getMethod("aMethod", new Class[] {}); 
    
Method m1 = clazz.getMethod("aMethod"); 

// And this for methods that takes many arguments. 

// It is equivalent to 
//getMethod("aMethod", new Class[] {String.class, Object.class}); 
    
Method m2 = clazz.getMethod("aMethod", String.class, Object.class); 
Also, getEnclosingConstructor() and getEnclosingMethod() are useful for retrieving the instance of the constructor or method where a local class or an anonymous inner class have been defined inside. They only return meaningful values if called in Class instances representing these two types of classes; otherwise, they return null.

The getEnumConstants() method returns a generic array type -- T[] -- with all of the declared enum instances, given that this instance represents an Enum (i.e., returns true for the also new isEnum() method).

The getGenericInterfaces() and getGenericSuperclass() methods are useful if you implement or extend a parameterized type, such as List. These methods return arrays of Type and Type, respectively, allowing access to the generic declaration of a superclass or superinterface. However, as the example in GenericsTest shows, dealing with different subclasses of Type requires some ugly code, since it is only a marker interface (i.e., it does not define any methods).

A minor change has been made to getSuperclass(). Now it returns Class<? super T> instead of the raw type. Most developers will not find it particularly useful, but it is an example of better type safety added by generics.

The newInstance() method now returns a type variable, T. This eliminates the need for a cast in some common uses, such as in:
// Supposing E represents an interface ... 
// If we get an instance of an implementation class such as: 
Class clazz; 

// We now can simply do: 
E e = clazz.newInstance(); 

Field: Trivial changes have been made to this class. A new getter method has been added -- isEnumConstant() -- as well as getGenericType(), which is useful if the field's type is a type variable or a parameterized type.



Constructor and Method: Constructor's changes are a subset of the ones made to Method, so they are grouped for brevity. getGenericExceptionTypes() and getGenericParameterTypes() return arrays of Type, allowing access to parameterized types that might be part of the method/constructor signature.

The getParameterAnnotations() method return a bi-dimensional array of Annotations present in each parameter type. The first dimension represents each parameter, and the second one its annotations.

The isVarArgs() method indicates if this constructor/method takes a varargs parameter. These are the methods both have in common.

One method in Constructor, newInstance, has been changed to accept varargs as its parameter type. Again, this change is intended to make easier to call this method.

Changes exclusive to Method include the addition of getGenericReturnType(), for return types involving generics, and a isBridge() method, which has this puzzling Javadoc description: "Returns true if and only if this method is a bridge method as defined by the Java Language Specification." A new version of invoke that takes its args parameter as varargs instead of an array of Object is also provided in order to make the API simpler.



[/list]

Conclusion
Significant changes have been made to Java in order to make it more powerful and expressive. However, the side effect is the increased difficulty in using some Java APIs, especially Reflection, which must provide support for nearly all enhancements that require changes to bytecode. Luckily, as developers use the new API and have more resources available about the changes, such as this article, there will be more pros than cons.

Michael Nascimento Santos is a seasoned developer with more than 8 years of experience with the Java platform, from J2ME to J2EE, and over 14 years of pratical programming experience.

分享到:
评论

相关推荐

    清华大学DeepSeek从入门到精通(视频课程+PDF)

    【清华大学】DeepSeek从入门到精通(视频课程+PDF)

    更新-“双高计划”专业群完整申报书与建设方案/中期评估报告

    自2019年以来,教育部启动实施“双高计划”,遴选确定首批“双高计划”建设单位197所,其中高水平学校建设单位56所,高水平专业群建设单位141所,河南省有黄河水利职业技术学院、河南工业职业技术学院等6所职业学校入选。2022年,教育部开展国家“双高计划”中期绩效评价,从评价结果看,国家“双高计划”任务进展顺利,建设成效突出,形成了一批先进经验做法和典型案例,在引领职业教育改革、服务国家战略和支撑区域发展方面形成示范势头。 今天,我们给大家分享一些“双高计划”专业群完整申报书与建设方案和中期评估报告。 ## 一、专业群完整申报书与建设方案 ## 二、“双高计划”中期报告 (100多份)

    电子商务平台秒杀系统减库存设计的核心逻辑与优化策略解析

    内容概要:本文详细探讨了电商平台上秒杀系统中减库存的设计逻辑和技术优化方法。首先,文中阐述了‘下单减库存’、‘付款减库存’和‘预扣库存’三种常见方式及其各自面临的问题和局限性,尤其是面对高并发流量冲击下的系统稳定性与数据准确性保障挑战。接着讨论了适用于大规模促销活动中快速而精准地扣除存货的方法,提出了诸如应用本地缓存(Local Cache)、引入高性能持久化键值存储(如Redis),甚至修改数据库引擎源代码(InnoDB 层面排队机制)等一系列先进解决方案来确保交易流程顺畅。此外,还提到了在极端情况发生(例如超卖)时如何借助补救措施挽回损失的具体实例。 适合人群:电商平台开发运维技术人员;有兴趣深入了解电商业务架构和技术优化的开发者和IT管理人员。 使用场景及目标:①帮助设计师理解不同减库存策略的应用时机及其利弊;②指导程序员针对特定业务需求选择最适合的技术路径进行项目构建;③提供给运维专家关于改善在线交易平台响应速度和服务质量的专业见解。 其他说明:本篇文章对于构建高效的电子商贸系统有着极高的参考价值,尤其是那些准备应对瞬息万变市场环境下的企业来说尤为重要。它不仅限于理论探讨层面,

    动态表单,VUE动态表单 基于vue+elementplus实现动态表单组件,通过拖拽组件到面板即可实现一个表单 支持各个组件的动态隐藏显示,动态表格弹窗式维护

    动态表单,VUE动态表单。基于vue+elementplus实现动态表单组件,通过拖拽组件到面板即可实现一个表单。支持各个组件的动态隐藏显示,动态表格弹窗式维护。

    【毕业设计】java-springboot-vue家居日用小百货交易网站实现源码(完整前后端+mysql+说明文档+LunW).zip

    【毕业设计】java-springboot-vue家居日用小百货交易网站实现源码(完整前后端+mysql+说明文档+LunW).zip

    【毕业设计】java-springboot+vue火锅店管理系统源码(完整前后端+mysql+说明文档+LunW).zip

    【毕业设计】java-springboot+vue火锅店管理系统源码(完整前后端+mysql+说明文档+LunW).zip

    基于springboot+vue的在线教育系统设计与实现(LW+PPT).zip

    随着信息技术在管理上越来越深入而广泛的应用,管理信息系统的实施在技术上已逐步成熟。本文介绍了微服务在线教育系统的开发全过程。通过分析微服务在线教育系统管理的不足,创建了一个计算机管理微服务在线教育系统的方案。文章介绍了微服务在线教育系统的系统分析部分,包括可行性分析等,系统设计部分主要介绍了系统功能设计和数据库设计。 本微服务在线教育系统有管理员,用户两个角色。管理员功能有个人中心,用户管理,课程信息管理,课程类型管理,学科管理,购买的课程管理,职业规划管理,视频点播管理,我的笔记管理,我的课程管理,消息通知管理,学习交流,试卷管理,留言板管理,试题管理,系统管理,考试管理。用户功能有个人中心,用户管理,购买的课程管理,我的笔记管理,我的课程管理,消息通知管理。因而具有一定的实用性。 本站是一个B/S模式系统,采用SSM框架,MYSQL数据库设计开发,充分保证系统的稳定性。系统具有界面清晰、操作简单,功能齐全的特点,使得微服务在线教育系统管理工作系统化、规范化。本系统的使用使管理人员从繁重的工作中解脱出来,实现无纸化办公,能够有效的提高微服务在线教育系统管理效率。 关键词:微服务在线教育系统;SSM框架;MYSQL数据库;Spring Boot

    基于Javascript实现,强化学习QLearning的一个贪吃蛇实例

    javascript 基于Javascript实现,强化学习QLearning的一个贪吃蛇实例.

    编程挑战_Chef卡牌游戏_学习资源_技能提升_1741399339.zip

    python教程学习

    基于springboot+vueIT技术交流和分享平台的设计与实现(LW).zip

    我国科学技术的不断发展,计算机的应用日渐成熟,其强大的功能给人们留下深刻的印象,它已经应用到了人类社会的各个层次的领域,发挥着重要的不可替换的作用。信息管理作为计算机应用的一部分,使用计算机进行管理,具有非常明显的优点,利用网络的优势特开发了本基于Spring Boot的IT技术交流和分享平台。 本IT技术交流和分享平台是基于Spring Boot框架,采用Java技术,MYSQL数据库进行开发的。系统具有灵活的一体化设计方式,圆满完成了整个系统的界面设计。本系统实现了用户功能模块和管理员功能模块两大部分,通过该系统用户可以快速进行IT技术交流和分享,管理员可登录系统后台对系统进行全面管理,确保系统正常稳定的运行。系统功能齐全,符合用户IT技术交流和分享的需求。 本文主要首先介绍了课题背景、设计原则和研究内容,系统采用的相关技术及开发平台,接着对本基于Spring Boot的IT技术交流和分享平台进行系统需求分析和设计,包括系统的功能模块,数据库的设计,系统结构以及系统界面设计等,最后对进行系统测试,完成本篇论文。 关键词:IT技术交流, Spring Boot框架, Java技术,MYSQL数据库

    疲劳检测yawn图片数据集

    疲劳检测yawn图片数据集

    JDK7通过java-jwt验证

    JDK7通过java-jwt验证

    【毕业设计】java-springboot+vue会议管理系统实现源码(完整前后端+mysql+说明文档+LunW).zip

    【毕业设计】java-springboot+vue会议管理系统实现源码(完整前后端+mysql+说明文档+LunW).zip

    sksalahuddin2828_Python_1741398999.zip

    python学习资源

    51CTO 1、技术解析篇-DeepSeek入门宝典 2、开发实战篇-DeepSeek入门宝典 3、行业应用篇-DeepSeek入门宝典 4、个人使用篇-DeepSeek入门宝典

    51CTO 1、技术解析篇-DeepSeek入门宝典 2、开发实战篇-DeepSeek入门宝典 3、行业应用篇-DeepSeek入门宝典 4、个人使用篇-DeepSeek入门宝典

    机器学习与模式识别领域的PRML习题解析手册

    内容概要:本文档是由高正奇编辑的针对模式识别和机器学习(PRML)教科书的一份详细的解答手册。文档覆盖了从基本概念如误差函数求导、贝叶斯定理应用到多元高斯分布计算、Gamma函数积分及其性质等一系列复杂问题的解决方案,以及涉及线性模型分类的基础练习题、条件概率和联合概率计算等入门级习题。每一题都经过细致推导,帮助学生加深对机器学习相关概念的理解并掌握具体的数学方法。 适合人群:主要适用于正在攻读机器学习、模式识别相关课程的学生,以及从事数据科学工作的专业人士作为深入理解和实践指南。 使用场景及目标:本手册旨在辅助教学过程中遇到的具体难题解析,在研究和实践中作为参考资料进行理论验证和技术难点突破,尤其有助于准备考试或者项目实施时需要巩固知识的应用场合。 其他说明:书中题目涵盖广泛,既有直观的概率论应用,也有复杂的积分变换技巧和最优化思路展示,对于希望提高自身计算能力和解决实际问题能力的学习者非常有价值。但要注意的是,部分内容较为深奥,可能不适合初学者自学使用,最好配合课堂讲解或其他教材一起学习效果更佳。

    编程语言_Python_入门之旅_教程_1741403040.zip

    python学习资源

    RFID-MATLAB的高等数学-CH06.rar

    RFID-MATLAB的高等数学-CH06.rar

    spaceX Ship Flight Test 8

    spaceX 动力学分析

    基于springboot+vue的美容院管理系统(LW).zip

    如今的信息时代,对信息的共享性,信息的流通性有着较高要求,因此传统管理方式就不适合。为了让美容院信息的管理模式进行升级,也为了更好的维护美容院信息,美容院管理系统的开发运用就显得很有必要。并且通过开发美容院管理系统,不仅可以让所学的SpringBoot框架得到实际运用,也可以掌握MySQL的使用方法,对自身编程能力也有一个检验和提升的过程。尤其是通过实践,可以对系统的开发流程加深印象,无论是前期的分析与设计,还是后期的编码测试等环节,都可以有一个深刻的了解。 美容院管理系统根据调研,确定其实现的功能主要包括美容用品管理,美容项目管理,美容部位管理,销量信息管理,订单管理,美容项目预约信息管理等功能。 借助于美容院管理系统这样的工具,让信息系统化,流程化,规范化是最终的发展结果,让其遵循实际操作流程的情况下,对美容院信息实施规范化处理,让美容院信息通过电子的方式进行保存,无论是管理人员检索美容院信息,维护美容院信息都可以便利化操作,真正缩短信息处理时间,节省人力和信息管理的成本。 关键字:美容院管理系统,SpringBoot框架,MySQL

Global site tag (gtag.js) - Google Analytics