Java JDK Reflect
来源:互联网 发布:网络直播受众群体 编辑:程序博客网 时间:2024/05/16 13:44
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
1、反射的基本概念
如果正常的情况下,如果要使用一个类,则必须按照如下的步骤操作:
1)使用import导入类所在的包(类:java.lang.Class)。
2)明确的使用类名称或接口名称定义对象。
3)通过关键字new进行类对象实例化(构造方法:java.lang.reflect.Constructor).
4)产生对象可以使用”对象.属性”进行类中属性的调用(属性:java.lang.reflect.Field);
而反射的过程呢?不需要有明确类型的对象,所有的对象使用Object表示:
可以直接利用Object与反射机制的混合调用类中的方法。
下面我们来看一下反射中类的关系图:
下面就简单说一下图中每个类的功能:
AnnotatedElement:注解元素操作类
Member:提供类和接口,以获取关于类和对象的反射信息。
GenericDeclaration:声明类型变量的所有实体的公共接口
Type:返回这个类的名称(e.g. java.lang.Class)
AccessibleObject:Field,Contrutor,Method类的基本类,用于控制可访问.
Executable:Constructor,Method共享通用功能的超类
Filed:类中的属性
Contrutor:类中的构造器
Method:类中的方法
Annotation:类中的注解
Class:Class代表类的实例(类类型)
2、如何获取一个类类型(Class)
如何取得Class对象:
1. Object类提供了一个返回Class类对象的方法:public Class getClass();
2. 利用”类.class”取得,日后见得最多的就是在Hibernate上
3. 利用Class类的static方法取得:ClassforName(String className);
如果是程序设计人员,使用最多的方法一定是forName()方法,但是如果是使用者,肯定会使用”类.class”通过之前的分析可以知道,工厂设计模式最好利用反射机制来解决耦合问题
3、Object类
我们都知道在Java的世界中一切皆对象。那么我们就有必要了解一下Object类。那么我们就来了解一下Object类中的所有方法以及每一个方法使用的注解事项:
1. 对象clone:Object clone()
clone对象所在的类一定要实现java.lang.Cloneable接口,而且子类只需要调用Object.clone就可以成功
实现clone操作
2. 对象输出 : String toString();
直接输出对象时会默认调用toString()方法。
3. 对象比较:boolean equals(Object obj)
当保存set集合时,会依靠hashCode()和equals()判断是否为重复对象
4. 取得对象的hash码:int hashCode();
可以理解为每一个类对象的唯一编码,比较时会先判断编码是否相同,而后再调用equals()
5. 取得class类对象:Class getClass();
通过一个已经实例化好的对象进行对象的反射操作
6. 线程等待void wait() InterceptorException
执行到此代码时线程要等待执行,一直到执行notify(),notifyAll()方法
7. 唤醒第一个等待线程:void notify();
8. 唤醒全部等待线程:void notifyAll();
9. public void finalize() throws Throwable;
当使用gc回收无用垃圾空间时默认调用
4、Class – 利用反射实例化对象
Class类如果使用了forName()方法之后,就可以使用Class类定义的newInstance方法默认去调用类之中的无参构造方法进行操作 T newInstance.一定要记住,此泛型使用不到。
1)Class Demo类
/** * Created by Carl on 2016/8/13. */class Person{ public Person(){ System.out.println("Peson类的构造方法..."); } @Override public String toString() { return "Peson类的toString()方法..."; }}public class ReflectDemo { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("com.weimob.carl.user.reflect.Person"); Object obj = clazz.newInstance(); System.out.println(obj); }}
2)运行结果
这个时候就可以非常清楚的发现,在整个程序编写之中,即使不完全知道类的结构,即使不导入包.class,可以进行对象的实现
5、Contrutor – 操作构造方法
但是如果使用反射实例化类对象,必须要求类中存在无参构造方法。因为默认使用Class类的newInstance()
方法只能够找到无参。这个时候只能够取得类之中的构造方法,传递所需要的参数后才可以执行。
在Class类里面定义了可以取得一个类之中方法的操作:
1、取得类之中的全部构造:Constructor[?> getConstructors()
2、取得类之中指定参数的构造:Constructor[T>getConstructor(Class[?>… parameterTypes)
1)范例:取得String类之中的全部构造方法:
public class ReflectDemo { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("java.lang.String"); Constructor<?>[] constructors = clazz.getConstructors(); for (int i = 0; i < constructors.length; i++) { System.out.println(constructors[i]); } }}
运行结果:
所以如果现在要想进行指定构造方法调用,就必须将关注点放在Constructor类之中。在此类中定义了一个实例化对象方法public T newInstance(Object.. initargs)。
2)范例:实例化不含有无参的Person对象
class Person{ private String name; private Integer age; public Person(String name, Integer age){ this.name = name; this.age = age; } @Override public String toString() { return "姓名: " + this.name + ",年龄: " + this.age; }}public class ReflectDemo { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("com.weimob.carl.user.reflect.Person"); Constructor<?> constructor = clazz.getConstructor(String.class, Integer.class); Object object = constructor.newInstance("carl", 26); System.out.println(object); }}
运行结果:
正是因为如果是通过构造方法实例化对象规格不统一。所以在进行简单Java类操作的时候就明确给出了,必须有无参构造方法。
6、Method – 调用类中方法
取得了一个类的实例化对象之后,下面主要的任务就是要调用类之中可以使用的操作方法,对于一个类之中的方法实际上由两类:
1)取得父类继承而来的方法和本类方法:
取得全部方法 Methods[] getMethods();
取得指定方法 Method(String name, Class[?>… parameterType)
2)取得本类定义的方法
取得全部方法 Method[] getDeclaredMethods()
取得指定方法 Method getDeclaredMethod(String name, Class[?>… parameterType)
但是以上的操作在方法定义上区别不大,因为方法大部分都是public ,所有两种方式取得的结果是没有区别。
1)范例:取得本类中的方法
class Person{ private String name; private Integer age; public Person(String name, Integer age){ this.name = name; this.age = age; } @Override public String toString() { return "姓名: " + this.name + ",年龄: " + this.age; } public void sayHello(){ System.out.println("hello world..."); }}public class ReflectDemo { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("com.weimob.carl.user.reflect.Person"); Method[] methods = clazz.getDeclaredMethods(); for(int i = 0; i < methods.length; i++){ System.out.println(methods[i]); } }}
运行结果:
现在的程序是直接调用Method类之中的toString()方法实现的输出。如果用户有需要也可以自己去整理方法的输出,需要使用到Method类的如下方法.
2)自己去整理方法的输出
1.取得方法修饰符:public int modityiers()
程序之中找的不是public、static等关键字,而是关键字所代表的数字,但是在程序之中必须将其更换为
读懂的信息,则可以借助于Modifyer类完成,此类中可以直接利用方法将数字变为修饰字符串
转换方法:public static String toString(int mod)。
2)取得方法的返回类型:public Class[?> getReturnType();
3)取得方法的参数:public Class[?> getParameterTypes();
4)取得所有抛出的异常:public Class[?> getExceptionTypes();
代码如下:
class Person{ private String name; private Integer age; public Person(String name, Integer age){ this.name = name; this.age = age; } @Override public String toString() { return "姓名: " + this.name + ",年龄: " + this.age; } public void sayHello(){ System.out.println("hello world..."); }}public class ReflectDemo { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("com.weimob.carl.user.reflect.Person"); Method[] methods = clazz.getMethods(); for(int i = 0; i < methods.length; i++){ // 方法修饰符 System.out.print(Modifier.toString(methods[i].getModifiers())); // 方法返回参数 System.out.print(" " + methods[i].getReturnType().getSimpleName() + " "); // 方法名 System.out.print(methods[i].getName() + "("); // 方法参数 Class<?> params[] = methods[i].getParameterTypes(); if(params.length > 0){// 有方法参数 for(int j = 0; j < params.length; j++){ System.out.print(params[j].getSimpleName() + " "); if(j < params.length - 1){ System.out.print(", "); } } } System.out.print(") "); // 方法异常 Class<?> exceptions[] = methods[i].getExceptionTypes(); if (exceptions.length > 0){ System.out.print(" throws "); for(int j = 0; j < exceptions.length; j++){ System.out.print(exceptions[j].getSimpleName()); if(j < exceptions.length - 1){ System.out.print(", "); } } } System.out.println();// 换行 } }}
运行结果:
此类代码一般只会在编写开发工具的时候出现,而所谓的随笔提示功能就是依据以上的代码实现的。
开发者密切关联最紧密的一定是利用Method调用类中的方法。而且在Method调用类中的方法。
范例:反射调用类中的方法。
调用方法 – public Object invoke(Object obj, Object… args)
class Person{ private String name; public void setName(String name) { this.name = name; } public String getName() { return name; }}public class ReflectDemo { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("com.weimob.carl.user.reflect.Person"); Object object = clazz.newInstance(); Method setNameMethod = clazz.getMethod("setName", String.class); Method getNameMethod = clazz.getMethod("getName"); setNameMethod.invoke(object, "carl"); System.out.println(getNameMethod.invoke(object)); }}
运行结果:
7、Field – 调用类中的属性(尽量不要去使用)
关于类中的属性也可以直接利用反射进行操作,而支持的方法有两类:
1)取得所有继承而来的属性
取得全部属性 public Field[] getFields()
取得指定属性 public Field getField(String name)
2)取得本类定义的属性
取得本类全部属性public Field getDeclareFields()
取得本类全部属性public Field getDeclareField(String name)
范例:取得一个类之中的属性
interface Message{ String INFO = "hello world.";}class Person{ private String name; private Integer age;}class Student extends Person implements Message{ private String school; private Double price;}public class ReflectDemo { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("com.weimob.carl.user.reflect.Student"); { // 取得继承而来的全部属性 System.out.println("取得继承而来的全部属性"); Field[] fields = clazz.getFields(); for(int i = 0; i < fields.length; i++){ System.out.println(fields[i]); } } { // 取得本类定义的全部属性 System.out.println("取得本类定义的全部属性"); Field[] fields = clazz.getDeclaredFields(); for(int i = 0; i < fields.length; i++){ System.out.println(fields[i]); } } { // 取得父类属性 System.out.println("取得父类属性"); Field[] fields = clazz.getSuperclass().getDeclaredFields(); for(int i = 0; i < fields.length; i++){ System.out.println(fields[i]); } } }}
运行结果:
2)在Field类里面还定义有进行属性调用的方法:
1)设置属性内容:public void set(Object obj, Object value)
2)取得属性内容:public Object get(Object obj);
在Constructor、Method、Field三个类上有一个共同的父类 AccessibleOblect,在这个类中定义了可以取消封装操作:public void setAccessible(boolean flag)
class Person{ private String name;}public class ReflectDemo { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("com.weimob.carl.user.reflect.Person"); Object object = clazz.newInstance(); Field nameField = clazz.getDeclaredField("name"); nameField.setAccessible(true); nameField.set(object, "carl"); System.out.println(nameField.get(object)); }}
运行结果:
在开发之中,只需要灵活使用Class、Constructor、Method、Field就可以使用反射进行一系列操作
的代码实现了。
- Java JDK Reflect
- Java Reflect JDK动态代理
- JDK 动态代理类分析(java.lang.reflect.Proxy使用)
- JDK 动态代理类分析(java.lang.reflect.Proxy使用)
- java reflect
- java reflect
- java reflect
- Java Reflect
- java .reflect
- Java reflect
- java-reflect
- Reflect-Java
- JAVA Reflect
- Java Reflect
- JAVA reflect
- Java-Reflect
- Core Java:使用java.lang.reflect实现JDK动态代理的小DEMO
- 静态代理模式和JDk提供的动态代理类java.lang.reflect.Proxy
- 设置Launch Image 启动图片
- 冒泡排序算法
- 闪屏制作
- html5 常用 标签
- socket is closed异常的原因及其解决方法
- Java JDK Reflect
- RAID5/RAID0及LV制作
- poj 2975 NIM
- laravel 表单验证 (入门)
- Codeforces Round #367 (Div. 2) D. Vasiliy's Multiset (multiset)
- 简单注解实现集群同步锁(spring+redis+注解)
- 自定义View实现圆形水波进度条
- QML 中的 XMLHttpRequest 对象
- HDU 4027 Can you answer these queries?(线段树)【The 36th ACM/ICPC Asia Regional 上海站网赛】