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

Java反射概念及类的反射的实例应用

阅读更多

Java反射概念及类的反射的实例

一、反射的概念 


反射的概念是由Smith1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。这一概念的提出很快引发了计算机科学领域关于应用反射性的研究。它首先被程序语言的设计领域所采用,并在Lisp和面向对象方面取得了成绩。其中LEAD/LEAD++ OpenC++ MetaXaOpenJava等就是基于反射机制的语言。最近,反射机制也被应用到了视窗系统、操作系统和文件系统中。

反射本身并不是一个新概念,它可能会使我们联想到光学中的反射概念,尽管计算机科学赋予了反射概念新的含义,但是,从现象上来说,它们确实有某些相通之处,这些有助于我们的理解。在计算机科学领域,反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用某种机制来实现对自己行为的描述(self-representation)和监测(examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。可以看出,同一般的反射概念相比,计算机科学领域的反射不单单指反射本身,还包括对反射结果所采取的措施。所有采用反射机制的系统(即反射系统)都希望使系统的实现更开放。可以说,实现了反射机制的系统都具有开放性,但具有开放性的系统并不一定采用了反射机制,开放性是反射系统的必要条件。一般来说,反射系统除了满足开放性条件外还必须满足原因连接(Causally-connected)。所谓原因连接是指对反射系统自描述的改变能够立即反映到系统底层的实际状态和行为上的情况,反之亦然。开放性和原因连接是反射系统的两大基本要素.

Java中,反射是一种强大的工具。它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代表链接。反射允许我们在编写与执行时,使我们的程序代码能够接入装载到JVM中的类的内部信息,而不是源代码中选定的类协作的代码。这使反射成为构建灵活的应用的主要工具。但需注意的是:如果使用不当,反射的成本很高。

二、Java中的类反射及属性反射

      反射:

 *   反射:构造器的过程

 *   反射:解析成员方法的过程

 *   反射:解析成员属性的过程 

     1.1 java类反射中的主要方法

对于以下三类组件中的任何一类来说 -- 构造函数、字段和方法 -- java.lang.Class 提供四种独立的反射调用,以不同的方式来获得信息。调用都遵循一种标准格式。以下是用于查找构造函数的一组反射调用:

Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数,

Constructor[] getConstructors() -- 获得类的所有公共构造函数

Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(与接入级别无关)

Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数(与接入级别无关)

获得字段信息的Class 反射调用不同于那些用于接入构造函数的调用,在参数类型数组中使用了字段名:

Field getField(String name) -- 获得命名的公共字段

Field[] getFields() -- 获得类的所有公共字段

Field getDeclaredField(String name) -- 获得类声明的命名的字段

Field[] getDeclaredFields() -- 获得类声明的所有字段

用于获得方法信息函数:

Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法

Method[] getMethods() -- 获得类的所有公共方法

Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得类声明的命名的方法

Method[] getDeclaredMethods() -- 获得类声明的所有方法



1.开始使用 Reflection

用于 reflection 的类,如 Method,可以在 java.lang.relfect 包中找到。使用这些类的时候必须要遵循三个步骤:第一步是获得你想操作的类的 java.lang.Class 对象。在运行中的 Java 程序中,用 java.lang.Class 类来描述类和接口等。
 1,加载类

      有三种方法:

          1class.formName("");

           2,类名.getClass();

           3,类名.calss;


下面就是获得一个 Class 对象的方法之一:

Class c = Class.forName("cn.csdn.web.Student");

这条语句得到一个 String 类的类对象。

还有另一种方法,如下面的语句:

Class c = int.class;

或者

Class c = Integer.TYPE;

2,创建实例对象

Student stu=(Student)cls.newInstance();

3,解析类

 Method md=cls.getMethod("getSum",null);//(方法名,参数名)

4.,执行

  Object obj=md.invoke(stu,null);//赋值

 源代码:

  

public void test(){

     //1加载类

Class cls = Class.forName("cn.csdn.web.test.Student");

//2,创建实例对象

Student stu=(Student)cls.newInstance();

//3,解析类

Method md=cls.getMethod("getSum",null);//(方法名,参数名)

//4,执行

Object obj=md.invoke(stu,null);//赋值

System.out.println(obj);



}

 

注意:

 在解析类的过程可以分为以下几种:

    1,解析无参数的构造器

    2,解析有参数的构造器 

    3,解析有数组参数的构造器

    4,解析private修饰的方法

    5,解析含有两个参数的构造器

1,解析无参数的构造器

 

  

public void test(){

        //1加载类

Class cls = Class.forName("cn.csdn.web.test.Student");

    //2,创建实例对象

Student stu=(Student)cls.newInstance();

    //3,解析类无参数的构造器 

Method md=cls.getMethod("getSum",null);//(方法名,参数名)

     //4,执行

Object obj=md.invoke(stu,null);//赋值

System.out.println(obj);



}

 

   2,解析有参数的构造器

       

   3,解析有数组参数的构造器
 //加载类

     Class cls = Class.forName("cn.csdn.web.test.Student");

  //通过带有参数的构造器解析

 Constructor constructor = cls.getConstructor(String.class);

//创建类的实例

 Student entity = (Student) constructor.newInstance("wangli");

         //对象调用方法

 entity.stady();

     System.out.println(entity.getName());

     System.out.println(entity.getAge());

 

     

//加载类

     Class cls = Class.forName("cn.csdn.web.test.Student");    

 //通过带有数组参数的构造器解析

 Constructor constructor =cls.getConstructor(String[].class);

 String[] stu=new String[]{"11","22"};

 Student entity = (Student) constructor.newInstance((Object)stu);

  entity.stady();

         

   4,解析两个参数的构造器

      

   5,解析用private修饰的构造器
 Class cls = Class.forName("cn.csdn.web.test.Student");

  //通过带有参数的构造器解析

 Constructor constructor = cls.getConstructor(String.class, int.class);

//创建类的实例

 Student entity = (Student) constructor.newInstance("wangli", 23);

         //对象调用方法

 entity.stady();

     System.out.println(entity.getName());

     System.out.println(entity.getAge());

 

     

//加载类

     Class cls = Class.forName("cn.csdn.web.test.Student");   

        //通过private修饰的构造器解析 

 Constructor constructor =cls.getDeclaredConstructor(List.class);

 *constructor.setAccessible(true);  //暴力反射

 Student entity = (Student) constructor.newInstance(new List());

  entity.stady();

          

  2.2 属性反射

       属性反射源代码1

       

 public void test()throws Exception{

 //1、加载类

    Class cls =Class.forName("cn.csdn.reflect.Student");

//2、创建类的实例

Student entity = (Student)cls.newInstance();


//3、解析属性

Field fds[] = cls.getDeclaredFields(); //字段


System.out.println("=========="+fds.length);


for(Field fd:fds){

fd.setAccessible(true);

System.out.println(fd.getName());

}

}

     

       属性反射源代码2

           

public void test2()throws Exception{

 //1、加载类

Class cls =Class.forName("cn.csdn.reflect.Student");

//2、创建类的实例

Student entity = (Student)cls.newInstance();


Field fd = cls.getDeclaredField("name"); //获取字段的值 private

fd.setAccessible(true);  //强制执行


fd.set(entity, "redarmy"); //set 赋值(entity,"")


System.out.println(entity.getName());


    String value = (String)fd.get(entity); //get(entity)


System.out.println(value);



}

 




三、安全性和反射


在处理反射时安全性是一个较复杂的问题。反射经常由框架型代码使用,由于这一点,我们可能希望框架能够全面接入代码,无需考虑常规的接入限制。但是,在其它情况下,不受控制的接入会带来严重的安全性风险,例如当代码在不值得信任的代码共享的环境中运行时。

由于这些互相矛盾的需求,Java编程语言定义一种多级别方法来处理反射的安全性。基本模式是对反射实施与应用于源代码接入相同的限制:

从任意位置到类公共组件的接入

类自身外部无任何到私有组件的接入

受保护和打包(缺省接入)组件的有限接入

不过至少有些时候,围绕这些限制还有一种简单的方法。我们可以在我们所写的类中,扩展一个普通的基本类java.lang.reflect.AccessibleObject 类。这个类定义了一种setAccessible方法,使我们能够启动或关闭对这些类中其中一个类的实例的接入检测。唯一的问题在于如果使用了安全性管理器,它将检测正在关闭接入检测的代码是否许可了这样做。如果未许可,安全性管理器抛出一个例外。

下面是一段程序,在TwoString 类的一个实例上使用反射来显示安全性正在运行:
   如果我们编译这一程序时,不使用任何特定参数直接从命令行运行,它将在field .get(inst)调用中抛出一个IllegalAcces***ception异常。如果我们不注释field.setAccessible(true)代码行,那么重新编译并重新运行该代码,它将编译成功。最后,如果我们在命令行添加了JVM参数-Djava.security.manager以实现安全性管理器,它仍然将不能通过编译,除非我们定义了ReflectSecurity类的许可权限。

四、反射性能
反射是一种强大的工具,但也存在一些不足。一个主要的缺点是对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。

下面的程序是字段接入性能测试的一个例子,包括基本的测试方法。每种方法测试字段接入的一种形式 -- accessSame 与同一对象的成员字段协作,accessOther 使用可直接接入的另一对象的字段,accessReflection 使用可通过反射接入的另一对象的字段。在每种情况下,方法执行相同的计算 -- 循环中简单的加/乘顺序。

程序如下:
 在上面的例子中,测试程序重复调用每种方法,使用一个大循环数,从而平均多次调用的时间衡量结果。平均值中不包括每种方法第一次调用的时间,因此初始化时间不是结果中的一个因素。

public class ReflectSecurity {

public static void main(String[] args) {

try {

TwoString ts = new TwoString("a", "b");

Field field = clas.getDeclaredField("m_s1");

// field.setAccessible(true);

System.out.println("Retrieved value is " +

field.get(inst));

} catch (Exception ex) {

ex.printStackTrace(System.out);

}

}

}

 

public int accessSame(int loops) {

m_value = 0;

for (int index = 0; index < loops; index++) {

m_value = (m_value + ADDITIVE_VALUE) *

MULTIPLIER_VALUE;

}

return m_value;

}



public int accessReference(int loops) {

TimingClass timing = new TimingClass();

for (int index = 0; index < loops; index++) {

timing.m_value = (timing.m_value + ADDITIVE_VALUE) *

MULTIPLIER_VALUE;

}

return timing.m_value;

}



public int accessReflection(int loops) throw* **ception {

TimingClass timing = new TimingClass();

try {

Field field = TimingClass.class.

getDeclaredField("m_value");

for (int index = 0; index < loops; index++) {

int value = (field.getInt(timing) +

ADDITIVE_VALUE) * MULTIPLIER_VALUE;

field.setInt(timing, value);

}

return timing.m_value;

} catch (Exception ex) {

System.out.println("Error using reflection");

throw ex;

}

}

 


结束语
Java语言反射提供一种动态链接程序组件的多功能方法。它允许程序创建和控制任何类的对象(根据安全性限制),无需提前硬编码目标类。这些特性使得反射特别适用于创建以非常普通的方式与对象协作的库。

  

<!--EndFragment-->
分享到:
评论

相关推荐

    java 通过反射获取枚举类,及枚举类的值,枚举类枚举实例名

    在Java编程语言中,反射(Reflection)是一种强大的工具,它允许程序在运行时检查和操作类、接口、字段和方法等对象。枚举(Enumeration)是Java中的一个特殊类类型,用于定义一组常量。本项目"test-enum-demo-...

    JAVA反射机制的入门代码

    总的来说,"JAVA反射机制的入门代码"是初学者理解Java反射机制的好教材,通过它,你可以学习如何动态地操作Java类,提高代码的灵活性,并掌握处理`properties`文件的基础方法。在深入学习和实践中,你将进一步理解...

    Java反射动态加载实例类

    通过本示例,我们不仅理解了Java反射的基本概念和用途,还学会了如何利用反射动态加载并操作实例类。反射提供了一种灵活的方式来处理类和对象,尤其是在编写框架和插件系统时,能够根据运行时的条件动态地加载和执行...

    Java反射应用实例

    代码主要实现了Java反射应用实例, 包含利用反射方法创建对象(使用默认构造函数和自定义构造函数),访问对应对象的方法(包括带参数的和不带参数的),访问对应对象的域(Field). 从这里可以看到代码的详细解说:...

    Java反射机制经典案例

    Java反射机制是Java编程语言中的一个强大...通过以上介绍,我们了解了Java反射机制的基本概念、使用方法、应用场景以及需要注意的问题。在实际编程中,合理利用反射可以提高代码的灵活性,但同时也需注意其潜在的风险。

    Java反射经典实例

    本实例将深入探讨Java反射的应用及其重要性。 一、什么是Java反射 Java反射机制允许我们动态地获取类的信息,并在运行时创建和调用对象的方法。这种能力使得Java具有高度的灵活性和动态性,特别是在处理跨版本兼容...

    Java反射概念及例子

    Java 反射机制是一种高级技术,它允许程序在运行时获得关于类的信息并动态操作这些类。这种能力对于需要在运行时根据字符串形式的信息来调用对象属性和方法的框架编程尤其有用。框架技术在当前的软件开发中占据着...

    反射实例-JAVA反射机制

    ### 反射实例—JAVA反射机制 #### 一、反射概念及原理 反射在计算机科学领域,特别是程序设计中,是指程序有能力访问、检测和修改其自身的结构和行为。这一概念最早由Smith于1982年提出,并迅速应用于各种编程语言...

    Java反射机制的详细讲解及实例,有助于java深度开发

    下面将详细阐述Java反射机制的基本概念、应用场景以及如何使用。 一、反射机制基本概念 1. 类加载:Java程序在运行时,JVM会将.class文件加载到内存中,形成类的Class对象,这个过程称为类加载。 2. 类的Class对象...

    java反射经典实例

    通过上述实例,我们可以看到Java反射机制在许多实际场景中的应用,它扩展了Java代码的灵活性和可扩展性。然而,也应注意,过度使用反射可能会引入复杂性和潜在的安全风险,因此在设计和实现时需权衡利弊。在理解了...

    Java反射调用工具类

    以上就是关于“Java反射调用工具类”的一些核心概念和知识点。通过理解并熟练运用这些,开发者可以编写出更灵活、更强大的代码,以应对各种复杂的场景。在实际开发中,应根据具体需求合理使用反射,避免滥用导致的...

    JAVA 反射机制应用

    Java反射机制是Java语言提供的一种强大功能,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。在Java中,反射机制的核心类是java.lang.Class,它代表了运行时的类信息。通过Class对象,我们...

    java反射实例代码

    在提供的"java反射实例代码"中,应该包含了如何使用上述方法的实际示例,这些示例有助于加深对Java反射机制的理解。通过阅读和运行这些代码,开发者可以更直观地学习如何在程序运行时动态地操作类、方法和字段,从而...

    java反射 java反射 java反射java反射

    Java反射是Java编程语言中的一个重要特性,它允许程序在运行时动态地获取类的信息并操作类的对象。在Java中,反射机制提供了强大的能力,包括在运行时检查类的结构、创建对象实例、调用方法以及访问和修改字段值。...

    java 利用反射获取内部类静态成员变量的值操作.docx

    ### Java 利用反射获取内部类静态成员变量的值操作 #### 一、引言 在Java编程中,反射是一个非常强大的工具,它允许程序在运行时检查类、接口、字段和方法...希望本文能帮助大家更好地理解和掌握Java反射技术的应用。

    Java反射机制总结

    - **运行时装配**:Java反射允许程序在运行时动态地加载类和创建对象,这对于构建可扩展的应用程序非常有用。 - **元数据查询**:开发人员可以利用反射来查询类的元数据,如字段名、方法签名等。 - **动态调用方法**...

    java反射机制应用

    #### 二、Java反射机制的应用场景及示例 ##### 1. 判断一个类是否是某个类的实例或子类 ```java Class&lt;?&gt; cls = Class.forName("com.example.Jdk"); boolean isInstance = cls.isInstance(new Jdk()); System.out....

    java反射例子,封装了一个反射帮助类

    Java反射是Java编程语言中的一个重要特性,它允许运行时访问和操作类、接口、字段和方法等信息。在Java中,反射提供了动态类型的能力,使我们可以在程序运行时检查类的信息,创建和调用对象的方法,甚至修改对象的...

    java 反射得到某个方法

    首先,我们需要了解Java反射的基本概念。`java.lang.Class`类是反射的核心,它代表了Java中的每一个类。我们可以通过以下方式获取到一个Class对象: ```java Class&lt;?&gt; clazz = Class.forName("全限定类名"); ``` ...

Global site tag (gtag.js) - Google Analytics