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

[学习]Java反射机制

    博客分类:
  • J2SE
 
阅读更多

 

[学习]Java反射机制

 

1. 三类成员Constructor, Field, Method

java.lang.reflect.Member 是一种接口,反映有关单个成员(字段或方法)或构造函数的标识信息。

所有已知实现类: Constructor, Field, Method

 

2. 二个字段PUBLIC, DECLARED

java.lang.reflect.Member 接口有二个字段:

int java.lang.reflect.Member.PUBLIC = 0 [0x0]

Identifies the set of all public members of a class or interface, including inherited members.

说明:标识类或接口的所有公共成员(包括继承成员)的集合。

 

int java.lang.reflect.Member.DECLARED = 1 [0x1]

Identifies the set of declared members of a class or interface. Inherited members are not included.

说明:标识类或接口的所有已声明成员的集合。不包括继承成员。

 

注:接口是可以有字段的,接口中的字段必须用public static final来修饰,默认如此,可不必添加。这是与接口只能被实现有关。

 

3. 三类方法getXXXConstructorX, getXXXFieldX, getXXXMethodX

这些方法根据成员类型,成员访问权限不同可简单归为以上三类。

中间加有Declared的方法能够调用所有已声明成员的集合,但不包括继承成员。

中间没有Declared的方法能够调用所有公共成员(包括继承成员)的集合。

未尾加有s的方法返回所有对应的成员集,e.g. getConstructors()返回所有公共构造方法。

a. 调用构造函数(Constructor)的方法 - getXXXConstructorX(),包括:

    getConstructor(), getConstructors(),

    getDeclaredConstructor(), getDeclaredConstructors()

 

b. 调用字段(Field)的方法 - getXXXFieldX()

    getField(), getFields(),

    getDeclaredField(), getDeclaredFields()

 

c. 调用方法(Method)的方法 - getXXXMethodX()

    getMethod(), getMethods(),

    getDeclaredMethod(), getDeclaredMethods()

 

4. 调用构造函数的方法一般步骤

a. 返回与带有给定字符串名的类或接口相关联的 Class 对象。调用此方法等效于:

  Class.forName(className, true, currentLoader)

 其中 currentLoader 表示当前类的定义类加载器。

    public static Class<?> forName(String className)

                throws ClassNotFoundException

 

b. 返回一个 Constructor 对象,它反映此 Class 对象所表示的类的指定公共构造方法。parameterTypes 参数是 Class 对象的一个数组,这些 Class 对象按声明顺序标识构造方法的形参类型。 如果此 Class 对象表示非静态上下文中声明的内部类,则形参类型作为第一个参数包括显示封闭的实例。

无参构造函数,parameterTypes可以为空,可以为null,可以为new Class[]{}

有参构造函数,parameterTypes为各参数类型。

e.g.

基本类型:int.classlong.class...

/接口类型:String.classList.class...

数组类型:long[].classString[].class...

    public Constructor<T> getConstructor(Class<?>... parameterTypes)

        throws NoSuchMethodException, SecurityException

    public Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes)

        throws NoSuchMethodException, SecurityException

 

c. 使用此 Constructor 对象表示的构造方法来创建该构造方法的声明类的新实例,并用指定的初始化参数初始化该实例。个别参数会自动解包,以匹配基本形参,必要时,基本参数和引用参数都要进行方法调用转换。

无参构造函数,parameterTypes可以为空,可以为null,可以为new Object[]{}

    public T newInstance(Object ... initargs)

    throws InstantiationException, IllegalAccessException,

               IllegalArgumentException, InvocationTargetException

 

5. 调用字段的方法一般步骤

a. 返回与带有给定字符串名的类或接口相关联的 Class 对象。调用此方法等效于:

  Class.forName(className, true, currentLoader)

 其中 currentLoader 表示当前类的定义类加载器。

    public static Class<?> forName(String className)

                throws ClassNotFoundException

 

b. 返回一个 Field 对象,该对象反映此 Class 对象所表示的类或接口的指定已声明字段。name 参数是一个 String,它指定所需字段的简称。注意,此方法不反映数组类的 length 字段。

一般JavaBean中的字段都被 private 修饰,所以使用getDeclaredField(String name)方法。

注:getField(String name)方法,会因为只能访问公有成员而出错。

    public Field getField(String name)

        throws NoSuchFieldException, SecurityException

    public Field getDeclaredField(String name)

        throws NoSuchFieldException, SecurityException

 

c. 返回指定对象上此 Field 表示的字段的值。如果该值是一个基本类型值,则自动将其包装在一个对象中。

底层字段的值是按以下方式获得的:

如果底层字段是一个静态字段,则忽略 obj 变量;它可能为 null。 否则,底层字段是一个实例字段。如果指定的 obj 变量为 null,则该方法将抛出一个 NullPointerException。如果指定对象不是声明底层字段的类或接口的实例,则该方法将抛出一个 IllegalArgumentException。如果此 Field 对象强制实施 Java 语言访问控制,并且底层字段是不可访问的,则该方法将抛出一个 IllegalAccessException

如果底层字段是静态的,并且声明该字段的类尚未初始化,则初始化这个类。否则,从底层实例字段或静态字段中获取该值。如果该字段是一个基本类型字段,则在返回前将该值包装在一个对象中,否则照原样返回。 如果字段隐藏在 obj 的类型中,则根据前面的规则获得字段的值。

除了通用的方法Object get(Object obj)外,还有int getInt(Object obj)long getLong(Object obj)等用来返回基本类型值的方法。

注:

1. Object obj 是包含有该字段的类实例

2. 调用方法用来返回某个字段值,需要遵循权限访问规则。若字段在当前方法中不可见,则无法访问,抛出异常。可见,调用字段方法一般用来获取其字段信息,而不会用来直接设置、获取其字段值。若想设置、获取其值,则可以通过getter/setter方法来完成。

    public Object get(Object obj)

        throws IllegalArgumentException, IllegalAccessException

 

6. 调用方法的方法一般步骤

a. 返回与带有给定字符串名的类或接口相关联的 Class 对象。调用此方法等效于:

  Class.forName(className, true, currentLoader)

 其中 currentLoader 表示当前类的定义类加载器。

    public static Class<?> forName(String className)

                throws ClassNotFoundException

 

b. 返回一个 Method 对象,它反映此 Class 对象所表示的类或接口的指定公共成员方法。name 参数是一个 String,用于指定所需方法的简称。parameterTypes 参数是按声明顺序标识该方法形参类型的 Class 对象的一个数组。如果 parameterTypes null,则按空数组处理。

 

    public Method getMethod(String name, Class<?>... parameterTypes)

        throws NoSuchMethodException, SecurityException

    public Method getDeclaredMethod(String name, Class<?>... parameterTypes)

        throws NoSuchMethodException, SecurityException

 

c. 对带有指定参数的指定对象调用由此 Method 对象表示的底层方法。个别参数被自动解包,以便与基本形参相匹配,基本参数和引用参数都随需服从方法调用转换。

如果底层方法是静态的,那么可以忽略指定的 obj 参数。该参数可以为 null

如果底层方法所需的形参数为 0,则所提供的 args 数组长度可以为 0 null

如果底层方法是实例方法,则使用动态方法查找来调用它,这一点记录在 Java Language Specification, Second Edition 的第 15.12.4.4 节中;在发生基于目标对象的运行时类型的重写时更应该这样做。

如果底层方法是静态的,并且尚未初始化声明此方法的类,则会将其初始化。

如果方法正常完成,则将该方法返回的值返回给调用者;如果该值为基本类型,则首先适当地将其包装在对象中。但是,如果该值的类型为一组基本类型,则数组元素不被包装在对象中;换句话说,将返回基本类型的数组。如果底层方法返回类型为 void,则该调用返回 null

注:Object obj 是包含有该字段的类实例

    public Object invoke(Object obj, Object... args)

    throws IllegalAccessException, IllegalArgumentException,

           InvocationTargetException

 

实例:

 

/**

 * Copyright (c) 2011 Trusted Software and Mobile Computing(TSMC)

 * All right reserved.

 *

 * Created on Aug 19, 2011 12:12:06 PM

 * http://jarg.iteye.com/

 * Author: Jarg Yee <yeshaoting@gmail.com>

 */

package com.iteye.jarg.test;

 

import java.lang.reflect.Constructor;

import java.lang.reflect.Field;

import java.lang.reflect.Method;

 

/**

 * TODO [学习]Java反射机制

 */

public class ReflectEx

{

    public static void main(String[] args) throws Exception

    {

       Class<?> clazz = Class.forName("com.iteye.jarg.test.ReflectBean");

      

       //无参构造函数参数数组可不写,可用new Class[]{},可用null

       Constructor<?> constructor = clazz.getConstructor();

      

       //无参构造函数参数数组可不写,可用new Object[]{},可用null

       Object obj = constructor.newInstance();  

       ReflectBean bean = (ReflectBean)obj;

       bean.display("1");

      

       constructor = clazz.getConstructor(String.class);

       obj = constructor.newInstance("字段 name 参数值");

       bean = (ReflectBean)obj;

       bean.display("2");

      

        //虽然getDeclaredField能查看字段相关信息,但是获取字段值还得遵循权限访问规则

       //若使用getField("name"),则会因为它只能访问公共成员而出错

       Field field = clazz.getDeclaredField("name");

      

       //获取实例相应字段值,而不是字段初始值

       System.out.println("3. name:\t" + field.get(bean));

      

       System.out.println("-------------------------------");

       Object obj2 = clazz.newInstance();

       Method method = clazz.getMethod("setName", String.class);

       method.invoke(obj2, "字段 name 全新值");

       bean = (ReflectBean)obj2;

       bean.display("4");

      

       obj2 = clazz.newInstance();

       method = clazz.getMethod("setValue", int[].class);

       method.invoke(obj2, new int[]{1,2,3,4});

       bean = (ReflectBean)obj2;

       System.out.println("5. value:\t" + bean.getValue()[2]);

      

      

    }

}

 

class ReflectBean

{

    int[] value = new int[4];

 

    String name = "字段 name 初始值";

   

    public ReflectBean(String name)

    {

       this.name = name;

       System.out.println("测试 \"\" 参构造函数");

    }

   

    public ReflectBean()

    {

       System.out.println("测试 \"\" 参构造函数");

    }

 

    public String getName()

    {

       return name;

    }

 

    public void setName(String name)

    {

       this.name = name;

    }

   

    public int[] getValue()

    {

       return value;

    }

 

    public void setValue(int[] value)

    {

       this.value = value;

    }

   

    public void display(String id)

    {

       System.out.println(id + ". name:\t" + name);

       System.out.println("-------------------------------");

    }

}

 

 

输出结果:

 

测试 "" 参构造函数

1. name:   字段 name 初始值

-------------------------------

测试 "" 参构造函数

2. name:   字段 name 参数值

-------------------------------

3. name:   字段 name 参数值

-------------------------------

测试 "" 参构造函数

4. name:   字段 name 全新值

-------------------------------

测试 "" 参构造函数

5. value:  3

 

 

0
4
分享到:
评论

相关推荐

    java面试题--反射机制

    通过本文的学习,我们深入了解了Java反射机制的基本概念、原理以及应用。Java反射机制为Java程序提供了一种强大的动态处理能力,使得Java不仅仅局限于静态类型语言的功能限制。掌握Java反射机制对于开发者来说是非常...

    java反射机制详解及Method.invoke解释.pdf

    Java 反射机制详解及 Method.invoke 解释 Java 反射机制是 Java 语言中的一种功能,允许程序在运行时访问和修改...通过学习 Java 反射机制,可以更好地理解 Java 语言的机理,并且可以更好地开发出高效、灵活的程序。

    Java反射机制学习(二)

    这篇博文"Java反射机制学习(二)"可能深入探讨了如何利用反射进行动态类型处理、访问私有成员以及创建对象等核心概念。在这里,我们将详细讨论Java反射的基本用法及其在实际开发中的应用。 1. **什么是反射**: ...

    Java反射机制视频教程

    Java反射机制是Java编程语言中的一个强大工具,它允许程序在运行时检查并操作类、接口、对象等...虽然视频质量可能不高,但它仍然是学习Java反射机制的重要资源,可以帮助开发者提升编程的灵活性和应对复杂场景的能力。

    Java反射机制的使用和学习方法

    Java反射机制是Java编程语言中的一个强大特性,它允许程序在运行时检查和操作类、接口、对象等的内部信息。这一机制对于理解和实现高级框架、动态代理、元数据处理等场景至关重要。以下是对Java反射机制的详细说明:...

    java反射机制讲解与应用举例

    关于java反射机制的很好的讲解,包括Java的反射机制(Reflection)、Class类、如何获得类的相关信息和运用,并且还有相应的练习,有助于更好地学习java反射机制

    Java反射机制的学习

    Java反射机制是Java编程语言中的一项核心特性,它允许程序在运行时动态地获取类的信息并进行操作。这使得Java能够在编译后仍然能够灵活地处理类和对象,增强了代码的动态性。在Android应用开发中,反射机制尤其重要...

    pdf反射机制-java

    学习Java反射机制的重要性体现在以下几个方面: 1. 动态类型:反射机制允许我们在运行时检查对象的类型,这对于编写通用代码和处理未知类型的对象非常有用。 2. 插件化开发:在插件化系统中,反射可以用于加载和...

    北大青鸟java反射机制

    在"北大青鸟java反射机制"的学习资料中,我们将会深入探讨这一核心特性。 首先,我们要理解反射的核心概念:在程序运行时,通过Class对象获取类的信息,包括类名、属性、方法等,并能够动态地创建对象和调用方法。...

    JAVA反射机制的入门代码

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

    一个例子让你了解Java反射机制

    Java反射机制是Java编程语言中的一个重要特性,它允许运行中的Java程序对自身进行检查并且可以直接操作程序的内部属性。在Java中,反射机制的核心类集中...在实践中学习,你会更好地理解Java反射机制的威力和应用场景。

    Java 反射机制 代码的实例

    Java反射机制是Java编程语言中的一个强大特性,...通过学习和实践Java反射机制,你可以更深入地理解Java的运行机制,并在需要动态性、灵活性的场景中发挥其强大的功能。不过,使用反射时也应注意潜在的风险和性能影响。

    Java反射机制学习总结

    Java反射机制是Java编程语言中一个强大的工具,它允许程序在运行时动态地获取类的信息并操作类的对象。反射机制的核心在于java.lang.reflect包中的API,主要包括Class类、Constructor类、Method类和Field类。以下是...

    java学习笔记(java 反射机制 流 内存管理)

    本笔记主要涵盖了四个核心知识点:Java反射机制、流(I/O流)、内存管理和Java学习的基础。以下是对这些主题的详细阐述: 一、Java反射机制 Java反射机制是Java语言的一个强大特性,允许程序在运行时检查类、接口、...

    java学习笔记java反射机制

    java学习笔记java反射机制

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

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

    利用java反射机制的建议计算器源码

    通过这个例子,新手可以学习到如何使用Java反射机制来增强代码的动态性,以及如何设计可扩展的系统。反射在很多场景下都很有用,例如在插件系统、序列化、动态代理等领域都有广泛应用。然而,需要注意的是,反射也...

    java反射机制.xmind

    自己总结的java反射机制的笔记,绘制了详细的思维导图,每个思维导图中均有详细的博文解释,方便大家学习和理解,免费分享给大家。适合java的爱好者和学习者

    Java SE完整版精品优质课件 自学入门必看的优秀Java基础知识培训教案 第13章_Java反射机制(共44页).rar

    学习Java反射机制,你需要理解并掌握这些类的使用,同时要明白,虽然反射提供很大的灵活性,但也带来了性能开销和安全风险,因此在实际开发中应谨慎使用。在自学或教学过程中,第13章的Java反射机制课件会深入讲解...

    Reflection_in_Java.zip_in_java 反射_java 反射机制_java反射_反射机制

    Java反射机制是Java编程语言中一个强大的特性,它允许运行时的程序动态地获取类的信息并操作类的对象。在Java中,反射主要涉及到`java.lang.Class`类、`java.lang.reflect`包下的类如`Constructor`、`Method`和`...

Global site tag (gtag.js) - Google Analytics