`
QING____
  • 浏览: 2251768 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JAVA反射机制API简述

    博客分类:
  • JAVA
 
阅读更多

一.Annotation,java.lang.annotation.ElementType枚举

ElementType表示程序元素的类型,和@Target元注释类型一起使用,以指定在什么情况下使用注释类型合法的.

1)CONSTRUCTOR:构造方法声明

2)FIELD:字段声明

3)LOCAL_VARIABLE:局部变量声明

4)METHOD:方法声明

5)PACKAGE:包声明

6)PARAMETER:参数声明

7)TYPE:类/接口(包括注释)或者枚举声明.

8)ANNOTATION_TYPE:注释类型声明

 

二.RetentionPolicy枚举:

注释保留策略,他们与@Retention元注释类型一起使用,以指定保留注释的场景.

1)CLASS:编译器将把注释记录在类文件中,但在运行时VM不需要保留注释.

2)RUNTIME:编译器将把注释记录在类文件中,在运行时可以被VM保留,并可以被反射机制所获取.

3)SOURCE:注释只保留在原文件中.

 

@Documented:指定某一类型的注释将通过javadoc工具进行文档化.将成为API文档的一部分.

@Inherited:指定此注释类型可以被自动继承.如果注释类型声明中存在Inherited元注释,那么此元素将会自动继承父类/接口的注释类型.

@Retention:指定注释类型的注释保留策略,默认为RetentionPolicy.CLASS.

@Target:指示注释类型所适用的元素种类.如果注释类型声明中不存在Target元注释,则此注释可以被声明在任意元素类型上.Target允许指定多个ElementType作为其value.它和

ElementType枚举配合使用.

三.AnnotatedElement接口:

表示目前正在VM中运行的程序的一个已注释元素.该接口允许反射性的读取注释.

其中实现类有AccessibleObject(AccessibleObject子类有Constructor,Field,Method),Class和Package

方法列表:

 

1)public boolean isAnnotationPresent(Class<? extends Annotation> annotation):

如果指定的注释存在于此元素上,则返回true.

2)public Annotation[] getAnnotations():

返回此元素上存在的所有注释.如果没有注释,则返回长度为0的数组.

3)public Annotation getDeclaredAnnotation():

返回直接存在于此元素上的所有注释。与此接口中的其他方法不同,该方法将忽略继承的注释。

(如果没有注释直接存在于此元素上,则返回长度为零的一个数组。)

该方法的调用者可以随意修改返回的数组;这不会对其他调用者返回的数组产生任何影响。

 

四.Member接口:

成员是一种接口,反映有关单个成员(字段或方法)或者构造方法的标识信息.

其实现类有Constructor,Field,Method.

 

1) public Class<?> getDeclaringClass():

返回表示声明此Member表示的成员的Class对象,即此成员所属的原声明类对象.

2) public String getName():

返回此成员或者构造方法的简单命名.

3) public int getModifiers():

返回整数,表示此Member的修饰符信息.可以通过Modifier类的辅助方法来检测.

4) public boolean isSynthetic():

如果此成员是编译器引入的,则返回 true.

 

 

五.几种特殊的类型(Type接口的子接口)

GenericArrayType:泛型化数组类型.例如: <T> T[];

ParameterizedType:参数化类型.例如Collection<String>..方法列表:

WildcardType:表示一个通配符类型表达式,例如:?,? extends Number

 

六.AccessibleObject类

AccessibleObject类是Field,Method和Constructor对象的基类,它提供了将反射的对象标记为在使用时取消默认java语言访问控制检测的能力.对于公共成员/默认访问成员

/受保护成员和私有成员,在分别使用Filed/Method/Constructor对象来设置或者获取字段值/调用方法以获取执行结果时/创建或初始化类的新实例时,均会执行访问检测.

此类实现了AnnotatedElement接口.

 

1)public void setAccessible(boolean flag) throws SecurityException:

将对象的accessible标记设置为指定的值.如果值为true,则指示反射的对象在使用时应取消java语言的访问检测.

例如:private Date date;

此属性为private,如果在类的外部,是不能直接访问其值的.但是通过如下方式却可以.

DateTest test = new DateTest();

Field[] fields = test.getDeclareFields();

try{

for(Field f: fields){

f.setAccessible(true);

Date d = (Date)f.get(test);

System.out.print(d.toString());

}

}

七.Array类:

Array类提供了动态创建和访问java数据的能力.

1) static Object get(Object array,int index):

获取指定数组的相应索引的值.

2) static void set(Object array,int index,Object value):

设置数组的值.

3) static Object newInstance(Class<?> type,int length):

创建一个指定长度和数据类型的数组.

 

八.Constructor类:

Constructor提供了类的单个构造方法的信息以及对它的访问权限.

1) public T newInstance(Object...args):

使用此Constructor对象表示的构造方法来创建该构造方法声明类的实例.个别参数会自动解包,以匹配基本形参,必要时,基本参数和引用参数都要进行方法调用转换.如果构造器的参数列表为0,可以传递null或者空数组.

如果所需的访问检查和参数检查获得成功并且实例化继续进行,这是构造方法的声明类尚未初始化,则初始化此类.

会执行访问权限校验.如果setAccessible(true),那么在反射机制下,私有构造函数也可以创建实例.(打破单例设计的一个潜在可能)

 

九.Filed类:

提供了对类的成员属性进行操作的能力,以及对它的动态访问权限.反射的字段可能是一个类的静态字段或者实例字段.

1) public boolean isEnumConstant():

如果此字段表示枚举类型的元素,则返回true.

2) public Type getType():

返回一个Type对象,表示此Field对象所表示字段的声明类型.

3) public Object get(Object obj):

返回指定对象上此Field的值.如果该值为基本类型,将会被包装成类.

如果此属性为static,则忽略obj变量,即使obj为null.

此方法将会被安全访问权限检测.

4) public void set(Object obj,Object value) throws ..:

对obj对象上此属性进行赋值.

如果此属性为静态,则忽略obj值,即使obj为null.

此方法执行会被访问权限检测.

如果此属性为final,则抛出异常.

 

十.Method类:

此类提供了反射下访问类方法以及执行方法的能力,方法可以是static的.

 

1) public Class<?> getReturnType():

获取此方法的返回值类型.

2) public Type getGenericReturnType():

获取此方法的正式返回类型的type对象,Type可能是参数化type等.(泛型化返回结果)

3) public Class<?>[] getParameterTypes():

获得此方法的参数列表数组,如果无参,将返回尺寸为0的空数组.

4) public Object invoke(Object obj,Object...args) throws ...:

调用指定对象的此方法,并获得结果,此方法将会检测访问权限.(setAccessible(true)).如果底层方法是静态的,此时如果类没有实例化,则执行类初始化.如果方法是void类型,则返回null.

 

 

Class类可以获得所有对Constructor,Filed,Method列表的方法.这是类反射的引导类.

十一.Modifier类

Modifier类是一个辅助类,大量的静态方法,可以通过检测Member.getModifier()的值来获得成员的修饰符信息.

例如:Modifier.isAbstract(int)来检测成员是否为被abstract修饰.

 

十二.动态代理

InvocationHandler接口:代理实例的调用处理程序,每个代理实例(Proxy instance)都需要一个invocationHandler来执行调用时的代理过程.

此接口只有一个方法:

  • Object invoke(Object proxy,Method method,Object[] args) throws....

在代理实例上处理方法调用并返回结果;proxy参数为代理实例,Method为执行的方法,args为方法需要的参数列表.

 

Proxy类:动态代理:

静态代理即为代理类和实际类需要具有相同的接口列表,如果一个类需要有多种代理方式,就需要创建多个代理类,形成子类的数量巨多.动态代理类就避免了此问题,它允许在运行时指定需要代理的接口列表,动态创建代理实例.

可以通过如下方式获取代理实例:

Foo f = (Foo)Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[]{Foo.class},new FooInvocationHandler());

 

代理类(Proxy代理所创建的子类)具有如下属性:

1) 代理类为公共的/最终的/而不是抽象的.即不可被继承性.

2) 代理类扩展java.lang.reflect.Proxy.

3) 代理类会按同一顺序准确的实现其创建时指定的接口.

4) 对代理类class实例进行getInterfaces将返回一个包含相同接口列表的数组(按其创建时指定的顺序).

5) 可以通过Proxy.isProxyClass(Class proxy)来检测一个实例的类是否为代理类,通过Proxy.newInstance创建的类都是代理类.

6) 代理类是由底层字节码重构技术创建而来.代理类是一种特殊的存在于运行时的类.

 

代理实例proxy与实际类的类型匹配关系:

  • proxy instanceOf Foo将返回true.
  • (Foo)proxy强制类型转换成功.

 

对于代理类调用方法,将会指派到invocationHandler.invoke()方法上.

代理实例上的java.lang.Object中声明的hashCode,equals,toString方法的调用将按照与编码和指派接口方法调用相同的方式进行编码,也将指派到invocationHandler.invoke上.即使是Object的方法调用,也会分配给handler执行.

 

////////////////////////////////////////////////ProxyDemo:

public class ProxyTestMain {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		DateOper oper = new DateOperImpl();
		DateOper proxyInstance = (DateOper)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class[]{DateOper.class}, new Invocation(oper));
		proxyInstance.setDate(new Date());
		System.out.println(proxyInstance.getDate().getTime());
		System.out.println(proxyInstance.toString());
	}
	
	interface DateOper{
		public void setDate(Date date);
		
		public Date getDate();
	}
	
	static class DateOperImpl implements DateOper{
		
		private Date date;
		@Override
		public void setDate(Date date) {
			this.date = date;
			System.out.println("SetDate invoked!");
		}

		@Override
		public Date getDate() {
			System.out.println("GetDate invoked!");
			return date;
		}
		
		public String toString(){
			System.out.println("ToString invoked!");
			return super.toString();
		}
		
		public int hashCode(){
			System.out.println("HashCode invoked!");
			return super.hashCode();
		}
		
	}
	static class Invocation implements InvocationHandler{
		private Object obj;//被代理实例
		public Invocation(Object obj){
			this.obj = obj;
		}
		@Override
		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			System.out.println("proxy:" + proxy.getClass() + "//" + Proxy.isProxyClass(proxy.getClass()));
			System.out.println("method:" + method.getName());
			return method.invoke(obj, args);
		}
		
	}

}

 

分享到:
评论

相关推荐

    java反射机制原理和反射机制总结

    Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、字段以及方法等对象。这一机制的核心在于`java.lang.Class`类和相关的API,它们提供了对类元数据的访问,使得我们能够在运行时...

    JAVA API文档

    10. **反射和动态代理**:`java.lang.reflect`包提供了反射API,允许程序在运行时检查和操作类、接口、字段和方法。动态代理机制则允许在运行时创建实现一组指定接口的新类。 通过`jdk-6u10-api-en`这个压缩包,你...

    Java各个包简述.pdf

    22. **java.lang.reflect**:反射机制的类和接口,用于获取类和对象的信息。 23. **java.math**:提供大整数(BigInteger)和高精度小数(BigDecimal)计算的类。 24. **java.net**:网络编程的类,包括Socket、...

    java学习笔记markdown

    8. **反射机制**:探讨Java反射API的使用,包括动态获取类信息、创建对象、调用方法等功能,这对于理解和调试程序有很大的帮助。 9. **JVM内部机制**:简述Java虚拟机的工作原理,包括类加载、内存管理、垃圾回收...

    java高级练习题 java 高级

    7. **反射机制**:Java反射机制允许在运行时动态访问类的信息,如创建对象、调用方法、修改字段等。这在插件系统、元编程和单元测试等领域非常有用。 8. **JVM内存管理**:了解堆内存、栈内存、方法区以及垃圾回收...

    清华大学Java教程

    8. **反射机制**:讨论Java的反射机制,如何在运行时动态获取类的信息并调用方法。 9. **Java Swing与JavaFX**:介绍用于创建桌面应用的图形用户界面(GUI)工具包,如Swing组件和JavaFX框架。 10. **Java Applet*...

    JAVA思维导图9张!

    8. **Java标准库API**:这部分可能会简述Java的主要包,如java.util、java.io、java.net和java.awt,以及它们包含的重要类和接口。 9. **Java高级特性**:最后,思维导图可能涉及Java的最新特性,如lambda表达式、...

    JAVA技术手册(第5版).pdf

    7. **反射机制**:介绍Java反射API,用于在运行时检查类、接口、字段和方法的信息,以及动态创建对象和调用方法。 8. **JNI与JVM**:简述Java本地接口(JNI)的使用,允许Java代码调用C/C++函数,以及对Java虚拟机...

    《Java从入门到精通(第4版)》随书PPT

    12. **反射与注解**:讲解Java反射机制,如何动态访问和修改类、接口、方法,以及注解的使用和自定义注解的创建。 13. **Java高级特性**:如模块化系统(Project Jigsaw)、Optional类、并发工具类(如...

    PDF--java咖啡馆

    8. **反射机制**:解释Java的反射API,如何在运行时动态获取类的信息,以及动态创建和调用对象的方法。 9. **泛型**:介绍泛型的使用,如何提高代码的类型安全性和重用性,以及通配符的运用。 10. **JVM原理**:...

    Java 北京大学讲义

    12. **Java API**:讲解常用的Java类库,如Math、Date、Calendar、Collections等。 13. **设计模式**:介绍常见的设计模式,如工厂模式、单例模式、观察者模式等,提升代码的可读性和可维护性。 14. **Java Swing...

    北大java讲义ppt

    14. **反射机制**:解释Java反射API的使用,如何在运行时动态获取类的信息和调用方法。 15. **Java标准库**:简述Java API中一些常用的类库,如IO、集合、网络编程和日期时间API等。 通过学习这份北大Java讲义,...

    java语言学习资料

    10. **JVM与内存管理**:简述Java虚拟机的工作原理,包括垃圾回收机制和内存区域,这对优化程序性能至关重要。 在学习过程中,读者需要通过编写代码实践来加深理解,逐步提升编程技能。同时,书中可能还提供了各种...

    JAVA之SUN公司培训教程

    8. **反射机制**:介绍Java反射API,用于在运行时检查类、接口、字段和方法的信息,以及动态创建对象。 9. **JVM内部机制**:简述Java虚拟机的工作原理,包括类加载、内存管理和垃圾回收。 10. **Java SE和Java EE...

    (小鱼)sun公司java培训资料

    六、Java反射与注解 16. 反射:掌握Class类的使用,动态获取类信息,创建对象,调用方法和访问字段。 17. 注解:了解注解的元数据功能,以及自定义注解和使用反射处理注解。 七、Java虚拟机(JVM) 18. 内存管理:...

    Java核心技术电子书原版

    6. **Java EE**:简述Java企业版技术,如Servlet、JSP和EJB。 7. **Java并发编程**:深入讨论并发API,如ExecutorService、Future、Callable和并发集合。 8. **Java 8新特性**:介绍Lambda表达式、Stream API和...

    Java程序设计技巧与开发实例PDF电子书

    10. **Java标准库和API**:书中会介绍Java SE标准库中的重要类和接口,如Math类、Date/Time API、反射机制,以及如何通过API文档查找和使用类库。 通过阅读和实践《Java程序设计技巧与开发实例》中的内容,读者不仅...

    《Java核心技术 卷2 高级特性 原书第8版》 PDF+高清+影印+全书签.rar

    4. **反射与动态代理**:Java的反射机制允许程序在运行时检查和操作类、接口、方法和字段。动态代理则允许创建代理类以实现运行时的拦截和增强。这两部分内容对于框架设计和元编程非常重要。 5. **枚举与注解**:...

    The Java Programming Language 4th Edition

    9. **反射与注解**:讨论Java反射机制,允许在运行时检查类、接口、字段和方法的信息,以及注解的使用,用于元数据注解和编译时或运行时的处理。 10. **JVM与内存管理**:简述Java虚拟机的工作原理,包括类加载机制...

    Java核心技术 11版 卷1 卷2 英文版

    5. **Java反射与注解**:介绍反射API,允许在运行时检查和修改类,以及注解的使用和自定义。 6. **模块系统**:讲解Java 9引入的模块系统,如何组织和打包应用程序,提高可维护性和可升级性。 7. **数据库编程**:...

Global site tag (gtag.js) - Google Analytics