Java反射教程
介绍
反射,正如我们从常用术语中所知道的,是你在镜子或镜像表面上看到的你自己或其他东西的图像。Java作为一种面向对象的语言,在很大程度上借鉴了现实生活中的实例,Java的反射API也是从现实生活中得到启发的。
在Java中,分析,查看和修改运行时A类的所有内部属性,行为和函数的过程称为反射。
使用反射概念,程序员现在可以操作类的所有属性 - 均匀的方法,构造函数和字段,即使在运行时,甚至也可以调用该类的方法并获得完整的快照。
反射大量用于Java框架,如Spring,休眠,JUnit等。
“反射”包
Java中与反射相关的类和信息的核心集合被封装为java.lang.reflect 包裹。它包含几个接口和类,这些接口和类定义了用于反射其他类的方法。
让我们看看java.lang.reflect 包
字段
此类提供有关类中存在的字段的信息,这些字段的反射正在被查看。
修饰语
这个类提供关于类和其他成员的访问修饰符的信息。
代理
此类支持动态代理类
方法
此类提供有关正在反映和检查的类方法的信息。
构造函数
此类提供有关正在反映和检查的类的构造函数的信息。
数组
此类允许程序员动态创建和操作数组
除此之外,java.lang.class类是用于反射中最重要的类之一,因为类的对象可以存储我们想要调查或者反映的类的实际信息。
在Java中的反射用途
可扩展性
使用反射概念,程序员可以通过使用完全限定的名称来创建这些可扩展对象的实例来使用外部可用的用户定义类
开发IDE和Class浏览器
IDE,特别是那些能够视觉开发的人,如Eclipse或者NetBeans,以及类浏览器可以广泛使用反射。
使用这些,可视化开发环境使用户易于使用的类信息,以便它们可以编写适当的代码。
调试和测试工具
调试需要能够查看包含其私有成员的类的内部详细信息.Debugging和测试工具可以使用反射通过使用反射来对类进行系统调用,并确保测试用例覆盖。
反思的缺点
作为一个极其强大的工具,反射API及其用法的支持具有一系列缺点,如
低性能
反射API的使用可以导致高性能开销并导致性能降低。
这是因为许多函数利用动态分辨率,这可以防止某些虚拟机优化的使用。
由于它倾向于减慢处理,因此不建议使用需要高可用性和低转带的代码部分。
安全风险
反射API要求在安全受管系统下执行期间不可用的CTEAIN安全权限。
此外,安全许可要求可能对驻留在安全系统中的代码构成威胁。
曝光内部字段和属性
由于反射API访问私有成员并调用私有函数,因此类和实体的内部细节被暴露于外部世界,并击败了对象导向概念中抽象的目的,这可能被视为违反面向对象的违规编程概念。
既然我们概述了反思的基本思想,让我们通过java.lang.class类,它在Java中扮演最重要的角色。
java.lang.class - 反射的网关
该类是Java.lang包的Java的标准库中的最终类,并扩展了对象类,它在Java中形成了所有类的基础。
类类的实例用于表示正在运行的Java应用程序中的类和接口。
使用类的实例,我们可以在运行时查看,分析和修改类的属性,甚至可以调用该类的方法。
java.lang.class的重要方法
类类具有各种方法,可用于获取执行的类的反映和执行该类的广泛动作。
其中一些方法是:
forname()方法:
此方法接受类的完整限定名称或者接口作为参数,并返回与素质名称关联的类的实例,包括其所有属性和行为。
forname方法的语法如下:
static Class<?> forName(String className)
让我们查看Forname方法的示例:
class TestClass{} class ReflectionTest { public static void main(String args[]) { Class c = null; try { c = Class.forName("TestClass"); } catch (ClassNotFoundException e) { System.out.println(e.getMessage()); } System.out.println(c.getName()); } }
上面的代码生成以下输出:
TestClass
getConstructors()和getDeclaredConstructors()方法:
getConstructors()方法以java.lang.reflect.constructor对象的形式返回调用对象的已声明的对象的声明公共构造函数的数组。
getDeclaredConstructors()方法返回调用对象的所有构造函数,包括非公共成员。
getConstructors()和getDeclaredConstructors()的语法如下:
Constructor< ?>[] getConstructors(); Constructor< ?>[] getDeclaredConstructors();
让我们看到使用上述方法的示例:
package org.igi.theitroad; import java.lang.reflect.Constructor; class TestClass{ public TestClass(){} protected TestClass(Integer a){} } public class ReflectionTest { public static void main(String args[]) { try { Class c = Class.forName("org.igi.theitroad.TestClass"); System.out.println("Using getConstructors()"); Constructor< TestClass>[] ct = c.getConstructors(); for(int i=0; i< ct.length; i++) { System.out.println(ct[i]); } System.out.println("===================="); System.out.println("Using getDeclaredConstructors()"); Constructor< TestClass>[] cdt = c.getDeclaredConstructors(); for(int i=0;i< cdt.length;i++) { System.out.println(cdt[i]);} } catch(Exception e) { e.printStackTrace();} } }
上面的执行代码会产生以下输出:
Using getConstructors() public org.igi.theitroad.TestClass() ==================== Using getDeclaredConstructors() public org.igi.theitroad.TestClass() protected org.igi.theitroad.TestClass(java.lang.Integer)
getmethods()和getdeclaredmethods()
java.lang.class的getMethods()函数返回一个java.lang.reflect.method实例,它反映并返回调用对象的所有公共方法。
另一方面,GetDeclaredMethods()函数只返回程序员声明的方法。
两种函数的语法如下:
Method< ?>[] getMethods(); Method< ?>[] getDeclaredMethods();
让我们看到使用上述方法的示例:
package org.igi.theitroad; import java.lang.reflect.Method; class TestClass { public void put() { } protected int show() { return 1; } } public class ReflectionTest { public static void main(String args[]) { try { Class c = Class.forName("org.igi.theitroad.TestClass"); Method mr[] = c.getMethods(); System.out.println("=================="); System.out.println("Using getMethods()"); System.out.println("=================="); for (int i = 0; i < mr.length; i++) { System.out.println(mr[i]); } Method md[] = c.getDeclaredMethods(); System.out.println("==========================="); System.out.println("Using getDeclaredMethods()"); System.out.println("============================"); for (int i = 0; i < md.length; i++) { System.out.println(md[i]); } } catch (Exception e) { e.printStackTrace(); } } }
上面的执行代码会产生以下结果:
================== Using getMethods() ================== public void org.igi.theitroad.TestClass2.put() public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException public final void java.lang.Object.wait() throws java.lang.InterruptedException public boolean java.lang.Object.equals(java.lang.Object) public java.lang.String java.lang.Object.toString() public native int java.lang.Object.hashCode() public final native java.lang.Class java.lang.Object.getClass() public final native void java.lang.Object.notify() public final native void java.lang.Object.notifyAll() =========================== Using getDeclaredMethods() ============================ public void org.igi.theitroad.TestClass2.put() protected int org.igi.theitroad.TestClass2.show()
因此,我们可以看到getMethods()方法返回包含超类的对象的所有公共方法,而GetDeclaredMethods()仅返回的用户声明的方法。
getfields()和getDeclaredfields()方法:
getFields()方法返回由java.lang.field对象组成的数组,该对象显示调用类或者接口的所有公共属性。
另一方面,getDeclaredFields()方法返回一个字段对象数组,该对象表示调用类或者接口中的所有字段Declkared。
方法的语法如下:
Field< ?>[] getFields(); Field< ?>[] getDeclaredFields();
让我们看看上述方法的示例:
package org.igi.theitroad; import java.lang.reflect.Field; class TestClass { public int a; String b; } public class ReflectionTest { public static void main(String args[]) { try { Class c = Class.forName("org.igi.theitroad.TestClass"); Field ff[] = c.getFields(); System.out.println("Using getFields() method"); System.out.println("======================="); for (int i = 0; i < ff.length; i++) { System.out.println(ff[i]); } Field f[] = c.getDeclaredFields(); System.out.println("======================="); System.out.println("Using getDeclaredFields() method"); System.out.println("======================="); for (int i = 0; i < f.length; i++) { System.out.println(f[i]); } } catch (Exception e) { e.printStackTrace(); } } }
上面的代码在执行时产生以下结果。
Using getFields() method ======================= public int org.igi.theitroad.TestClass.a ======================= Using getDeclaredFields() method ======================= public int org.igi.theitroad.TestClass.a java.lang.String org.igi.theitroad.TestClass.b