精华内容
下载资源
问答
  • 反射机制:所谓的反射机制就是java语言在运行时拥有一项自观的能力。通过这种能力可以彻底的了解自身的情况为下一步的动作做准备。下面具体介绍一下java反射机制。这里你将颠覆原来对java的理解。Java反射机制的...

    反射机制:所谓的反射机制就是java语言在运行时拥有一项自观的能力。通过这种能力可以彻底的了解自身的情况为下一步的动作做准备。下面具体介绍一下java的反射机制。这里你将颠覆原来对java的理解。

    Java的反射机制的实现要借助于4个类:class,Constructor,Field,Method;其中class代表的时类对

    象,Constructor-类的构造器对象,Field-类的属性对象,Method-类的方法对象。通过这四个对象我们可以粗略的看到一个类的各个组

    成部分。

    Class:程序运行时,java运行时系统会对所有的对象进行运行时类型的处理。这项信息记录了每个对象所属的类,虚拟机通常使用运行时类型信息选择正

    确的方法来执行(摘自:白皮书)。但是这些信息我们怎么得到啊,就要借助于class类对象了啊。在Object类中定义了getClass()方法。我

    们可以通过这个方法获得指定对象的类对象。然后我们通过分析这个对象就可以得到我们要的信息了。

    比如:ArrayList arrayList;

    Class clazz = arrayList.getClass();

    然后我来处理这个对象clazz。

    当然了Class类具有很多的方法,这里重点将和Constructor,Field,Method类有关系的方法。

    Reflection 是 Java 程序开发语言的特征之一,它允许运行中的 Java

    程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性。Java

    的这一能力在实际应用中也许用得不是很多,但是个人认为要想对java有个更加深入的了解还是应该掌握的。

    1.检测类:

    reflection的工作机制

    考虑下面这个简单的例子,让我们看看 reflection 是如何工作的。

    import java.lang.reflect.*;

    public class DumpMethods {

    public static void main(String args[]) {

    try {

    Class c = Class.forName(args[0]);

    Method m[] = c.getDeclaredMethods();

    for (int i = 0; i < m.length; i++)

    System.out.println(m[i].toString());

    } catch (Throwable e) {

    System.err.println(e);

    }

    }

    }

    按如下语句执行:

    java DumpMethods java.util.ArrayList

    这个程序使用 Class.forName 载入指定的类,然后调用 getDeclaredMethods

    来获取这个类中定义了的方法列表。java.lang.reflect.Methods 是用来描述某个类中单个方法的一个类。

    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() -- 获得类声明的所有方法

    使用 Reflection:

    用于 reflection 的类,如 Method,可以在 java.lang.relfect

    包中找到。使用这些类的时候必须要遵循三个步骤:第一步是获得你想操作的类的 java.lang.Class 对象。在运行中的 Java

    程序中,用 java.lang.Class 类来描述类和接口等。

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

    Class c = Class.forName("java.lang.String");

    这条语句得到一个 String 类的类对象。还有另一种方法,如下面的语句:

    Class c = int.class;

    或者

    Class c = Integer.TYPE;

    它们可获得基本类型的类信息。其中后一种方法中访问的是基本类型的封装类 (如 Intege ) 中预先定义好的 TYPE

    字段。

    第二步是调用诸如 getDeclaredMethods 的方法,以取得该类中定义的所有方法的列表。

    一旦取得这个信息,就可以进行第三步了——使用 reflection API 来操作这些信息,如下面这段代码:

    Class c = Class.forName("java.lang.String");

    Method m[] = c.getDeclaredMethods();

    System.out.println(m[0].toString());

    它将以文本方式打印出 String 中定义的第一个方法的原型。

    处理对象:

    a.创建一个Class对象

    b.通过getField 创建一个Field对象

    c.调用Field.getXXX(Object)方法(XXX是Int,Float等,如果是对象就省略;Object是指实例).

    例如:

    import java.lang.reflect.*;

    import java.awt.*;

    class SampleGet {

    public static void main(String[] args) {

    Rectangle r = new Rectangle(100, 325);

    printHeight(r);

    }

    static void printHeight(Rectangle r) {

    Field heightField;

    Integer heightValue;

    Class c = r.getClass();

    try {

    heightField = c.getField("height");

    heightValue = (Integer) heightField.get(r);

    System.out.println("Height: " + heightValue.toString());

    } catch (NoSuchFieldException e) {

    System.out.println(e);

    } catch (SecurityException e) {

    System.out.println(e);

    } catch (IllegalAccessException e) {

    System.out.println(e);

    }

    }

    }

    安全性和反射:

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

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

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

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

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

    不过至少有些时候,围绕这些限制还有一种简单的方法。我们可以在我们所写的类中,扩展一个普通的基本类

    java.lang.reflect.AccessibleObject

    类。这个类定义了一种setAccessible方法,使我们能够启动或关闭对这些类中其中一个类的实例的接入检测。唯一的问题在于如果使用了安全性管理

    器,它将检测正在关闭接入检测的代码是否许可了这样做。如果未许可,安全性管理器抛出一个例外。

    下面是一段程序,在TwoString 类的一个实例上使用反射来显示安全性正在运行:

    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);

    }

    }

    }

    如果我们编译这一程序时,不使用任何特定参数直接从命令行运行,它将在field

    .get(inst)调用中抛出一个IllegalAccessException异常。如果我们不注释

    field.setAccessible(true)代码行,那么重新编译并重新运行该代码,它将编译成功。最后,如果我们在命令行添加了JVM参数

    -Djava.security.manager以实现安全性管理器,它仍然将不能通过编译,除非我们定义了ReflectSecurity类的许可权

    限。

    反射性能:(转录别人的啊)

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

    下面的程序是字段接入性能测试的一个例子,包括基本的测试方法。每种方法测试字段接入的一种形式 -- accessSame

    与同一对象的成员字段协作,accessOther 使用可直接接入的另一对象的字段,accessReflection

    使用可通过反射接入的另一对象的字段。在每种情况下,方法执行相同的计算 -- 循环中简单的加/乘顺序。

    程序如下:

    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 acces

    sReference(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) throws Exception {

    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;

    }

    }

    在上面的例子中,测试程序重复调用每种方法,使用一个大循环数,从而平均多次调用的时间衡量结果。平均值中不包括每种方法第一次调用的时间,因此初始化时间不是结果中的一个因素。下面的图清楚的向我们展示了每种方法字段接入的时间:

    图 1:字段接入时间 :

    我们可以看出:在前两副图中(Sun JVM),使用反射的执行时间超过使用直接接入的1000倍以上。通过比较,IBM

    JVM可能稍好一些,但反射方法仍旧需要比其它方法长700倍以上的时间。任何JVM上其它两种方法之间时间方面无任何显著差异,但IBM

    JVM几乎比Sun JVM快一倍。最有可能的是这种差异反映了Sun Hot Spot

    JVM的专业优化,它在简单基准方面表现得很糟糕。反射性能是Sun开发1.4

    JVM时关注的一个方面,它在反射方法调用结果中显示。在这类操作的性能方面,Sun 1.4.1

    JVM显示了比1.3.1版本很大的改进。

    如果为为创建使用反射的对象编写了类似的计时测试程序,我们会发现这种情况下的差异不象字段和方法调用情况下那么显著。使用newInstance()调

    用创建一个简单的java.lang.Object实例耗用的时间大约是在Sun 1.3.1 JVM上使用new

    Object()的12倍,是在IBM 1.4.0 JVM的四倍,只是Sun 1.4.1

    JVM上的两部。使用Array.newInstance(type, size)创建一个数组耗用的时间是任何测试的JVM上使用new

    type[size]的两倍,随着数组大小的增加,差异逐步缩小。随着jdk6.0的推出,反射机制的性能也有了很大的提升。期待中….

    总结:

    Java语言反射提供一种动态链接程序组件的多功能方法。它允许程序创建和控制任何类的对象(根据安全性限制),无需提前硬编码目标类。这些特性使得反射

    特别适用于创建以非常普通的方式与对象协作的库。例如,反射经常在持续存储对象为数据库、XML或其它外部格式的框架中使用。Java

    reflection 非常有用,它使类和数据结构能按名称动态检索相关信息,并允许在运行着的程序中操作这些信息。Java

    的这一特性非常强大,并且是其它一些常用语言,如 C、C++、Fortran 或者 Pascal 等都不具备的。

    但反射有两个缺点。第一个是性能问题。用于字段和方法接入时反射要远慢于直接代码。性能问题的程度取决于程序中是如何使用反射的。如果它作为程序运行中相

    对很少涉及的部分,缓慢的性能将不会是一个问题。即使测试中最坏情况下的计时图显示的反射操作只耗用几微秒。仅反射在性能关键的应用的核心逻辑中使用时性

    能问题才变得至关重要。

    许多应用中更严重的一个缺点是使用反射会模糊程序内部实际要发生的事情。程序人员希望在源代码中看到程序的逻辑,反射等绕过了源代码的技术会带来维护问

    题。反射代码比相应的直接代码更复杂,正如性能比较的代码实例中看到的一样。解决这些问题的最佳方案是保守地使用反射——仅在它可以真正增加灵活性的地方

    ——记录其在目标类中的使用。

    一下是对应各个部分的例子:

    具体的应用:

    1、 模仿instanceof 运算符号

    class A {}

    public class instance1 {

    public static void main(String args[])

    {

    try {

    Class cls = Class.forName("A");

    boolean b1

    = cls.isInstance(new Integer(37));

    System.out.println(b1);

    boolean b2 = cls.isInstance(new A());

    System.out.println(b2);

    }

    catch (Throwable e) {

    System.err.println(e);

    }

    }

    }

    2、 在类中寻找指定的方法,同时获取该方法的参数列表,例外和返回值

    import java.lang.reflect.*;

    public class method1 {

    private int f1(

    Object p, int x) throws NullPointerException

    {

    if (p == null)

    throw new NullPointerException();

    return x;

    }

    public static void main(String args[])

    {

    try {

    Class cls = Class.forName("method1");

    Method methlist[]

    = cls.getDeclaredMethods();

    for (int i = 0; i < methlist.length;

    i++)

    Method m = methlist[i];

    System.out.println("name

    = " + m.getName());

    System.out.println("decl class = " +

    m.getDeclaringClass());

    Class pvec[] = m.getParameterTypes();

    for (int j = 0; j < pvec.length; j++)

    System.out.println("

    param #" + j + " " + pvec[j]);

    Class evec[] = m.getExceptionTypes();

    for (int j = 0; j < evec.length; j++)

    System.out.println("exc #" + j

    + " " + evec[j]);

    System.out.println("return type = " +

    m.getReturnType());

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

    }

    }

    catch (Throwable e) {

    System.err.println(e);

    }

    }

    }

    3、 获取类的构造函数信息,基本上与获取方法的方式相同

    import java.lang.reflect.*;

    public class constructor1 {

    public constructor1()

    {

    }

    protected constructor1(int i, double d)

    {

    }

    public static void main(String args[])

    {

    try {

    Class cls = Class.forName("constructor1");

    Constructor ctorlist[]

    = cls.getDeclaredConstructors();

    for (int i = 0; i < ctorlist.length; i++) {

    Constructor ct = ctorlist[i];

    System.out.println("name

    = " + ct.getName());

    System.out.println("decl class = " +

    ct.getDeclaringClass());

    Class pvec[] = ct.getParameterTypes();

    for (int j = 0; j < pvec.length; j++)

    System.out.println("param #"

    + j + " " + pvec[j]);

    Class evec[] = ct.getExceptionTypes();

    for (int j = 0; j < evec.length; j++)

    System.out.println(

    "exc #" + j + " " + evec[j]);

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

    }

    }

    catch (Throwable e) {

    System.err.println(e);

    }

    }

    }

    4、 获取类中的各个数据成员对象,包括名称。类型和访问修饰符号

    import java.lang.reflect.*;

    public class field1 {

    private double d;

    public static final int i = 37;

    String s = "testing";

    public static void main(String args[])

    {

    try {

    Class cls = Class.forName("field1");

    Field fieldlist[]

    = cls.getDeclaredFields();

    for (int i

    = 0; i < fieldlist.length; i++) {

    Field fld = fieldlist[i];

    System.out.println("name

    = " + fld.getName());

    System.out.println("decl class = " +

    fld.getDeclaringClass());

    System.out.println("type

    = " + fld.getType());

    int mod = fld.getModifiers();

    System.out.println("modifiers = " +

    Modifier.toString(mod));

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

    }

    }

    catch (Throwable e) {

    System.err.println(e);

    }

    }

    }

    5、 通过使用方法的名字调用方法

    import java.lang.reflect.*;

    public class method2 {

    public int add(int a, int b)

    {

    return a + b;

    }

    public static void main(String args[])

    {

    try {

    Class cls = Class.forName("method2");

    Class partypes[] = new Class[2];

    partypes[0] = Integer.TYPE;

    partypes[1] = Integer.TYPE;

    Method meth = cls.getMethod(

    "add", partypes);

    method2 methobj = new method2();

    Object arglist[] = new Object[2];

    arglist[0] = new Integer(37);

    arglist[1] = new Integer(47);

    Object retobj

    = meth.invoke(methobj, arglist);

    Integer retval = (Integer)retobj;

    System.out.println(retval.intValue());

    }

    catch (Throwable e) {

    System.err.println(e);

    }

    }

    }

    6、 创建新的对象

    import java.lang.reflect.*;

    public class constructor2 {

    public constructor2()

    {

    }

    public constructor2(int a, int b)

    {

    System.out.println(

    "a = " + a + " b = " + b);

    }

    public static void main(String args[])

    {

    try {

    Class cls = Class.forName("constructor2");

    Class partypes[] = new Class[2];

    partypes[0] = Integer.TYPE;

    partypes[1] = Integer.TYPE;

    Constructor ct

    = cls.getConstructor(partypes);

    Object arglist[] = new Object[2];

    arglist[0] = new Integer(37);

    arglist[1] = new Integer(47);

    Object retobj = ct.newInstance(arglist);

    }

    catch (Throwable e) {

    System.err.println(e);

    }

    }

    }

    7、 变更类实例中的数据的值

    import java.lang.reflect.*;

    public class field2 {

    public double d;

    public static void main(String args[])

    {

    try {

    Class cls = Class.forName("field2");

    Field fld = cls.getField("d");

    field2 f2obj = new field2();

    System.out.println("d = " + f2obj.d);

    fld.setDouble(f2obj, 12.34);

    System.out.println("d = " + f2obj.d);

    }

    catch (Throwable e) {

    System.err.println(e);

    }

    }

    }

    使用反射创建可重用代码:

    1、 对象工厂

    Object factory(String p) {

    Class c;

    Object o=null;

    try {

    c = Class.forName(p);// get class def

    o = c.newInstance(); // make a new one

    } catch (Exception e) {

    System.err.println("Can't make a " + p);

    }

    return o;

    }

    public class ObjectFoundry {

    public static Object factory(String p)

    throws ClassNotFoundException,

    InstantiationException,

    IllegalAccessException {

    Class c = Class.forName(p);

    Object o = c.newInstance();

    return o;

    }

    }

    2、 动态检测对象的身份,替代instanceof

    public static boolean

    isKindOf(Object obj, String type)

    throws ClassNotFoundException {

    // get the class def for obj and type

    Class c = obj.getClass();

    Class tClass = Class.forName(type);

    while ( c!=null ) {

    if ( c==tClass ) return true;

    c = c.getSuperclass();

    }

    return false;

    }

    展开全文
  • 原文链接:反射机制使用详解反射机制使用详解反射定义反射API反射对于单例的破坏IOC容器反转控制原理反射的定义java反射机制是java开发中有一个非常重要的概念,也是java的重要特征之一。反射的概念是由Smith在1982...

    原文链接:反射机制使用详解

    反射机制使用详解

    1. 反射定义
    2. 反射API
    3. 反射对于单例的破坏
    4. IOC容器反转控制原理

    反射的定义

    java反射机制是java开发中有一个非常重要的概念,也是java的重要特征之一。反射的概念是由Smith在1982年首次提出的,主要是指程序可以访问、检测和修改它本身状态或行为的一种能力,通过反射可以动态调用方法和属性,大部分框架也都是运用反射原理的。比如Spring。

    首先大家应该先了解两个概念,编译期和运行期,编译期就是编译器帮你把源代码翻译成机器能识别的代码,比如编译器把java代码编译成jvm识别的字节码文件,而运行期指的是将可执行文件交给操作系统去执行,而我们所聊的JAVA反射机制是在运行状态中的一系列操作,反射机制我们可以从两方面来进行定义:

    • 对于给定的一个类(Class)对象,可以获得这个类(Class)对象的所有属性和方法;
    • 对于给定的一个对象(new XXXClassName<? extends Object>),都能够调用它的任意一个属性和方法。

    这种动态获取类的内容以及动态调用对象的方法和获取属性的机制.就叫做JAVA的反射机制。

    如下图,根据Car类获取到Class,并通过Class创建Car的对象、获取Car中属性、执行Car内部方法这就是反射机制。

    9c7f0a238088911639a067e453d74fe2.png

    理解Class

    认识Class对象之前,先来了解一个概念,RTTI(Run-Time Type Identification)运行时类型识别,对于这个词一直是 C++ 中的概念,至于Java中出现RRTI的说法则是源于《Thinking in Java》一书,其作用是在运行时识别一个对象的类型和类的信息,这里分两种:传统的”RRTI”,它假定我们在编译期已知道了所有类型(在没有反射机制创建和使用类对象时,一般都是编译期已确定其类型,如new对象时该类必须已定义好),另外一种是反射机制,它允许我们在运行时发现和使用类型的信息。

    接下来我们用一个示例来解释RTTI的概念:

    1af5c3d83ffeb7d4a2799c8ba24b8980.png
    创建一个Car类,JVM就会创建一个Car对应Class类的Class对象,该Class对象保存了Car类相关的类型信息。实际上在Java中每个类都有一个Class对象,每当我们编写并且编译一个新创建的类就会产生一个对应Class对象并且这个Class对象会被保存在同名.class文件里(编译后的字节码文件保存的就是Class对象)总结特点如下:
    1. Class类也是类的一种,与class关键字是不一样的。
    2. 手动编写的类被编译后会产生一个Class对象,其表示的是创建的类的类型信息,而且这个Class对象保存在同名.class的文件中(字节码文件)
    3. 每个通过关键字class标识的类,在内存中有且只有一个与之对应的Class对象来描述其类型信息,无论创建多少个实例对象,其依据的都是用一个Class对象。
    4. Class类只存私有构造函数,因此对应Class对象只能有JVM创建和加载
    5. Class类的对象作用是运行时提供或获得某个对象的类型信息,这点对于反射技术很重要(关于反射稍后分析)。

    反射机制可以动态获取类信息以及调用对象方法,那它是通过什么实现的呢?这就要介绍一下Class类了。首先明确Class也是一个类,只是它是一个描述类的类,也可以生成对象。对于每个类而言,在JRE中有且仅有一个不变的Class类型的对象,而这个Class类型的对象只能由系统建立,封装了当前对象所对应的类的信息,有哪些属性、方法、构造器以及实现了哪些接口等。每个类的实例都会记得自己是由哪个Class实例所生成的。 要获取类信息或调用对象方法,肯定首先要获取到该类或对象对应的Class类的实例。一般获取Class对象有3种方式。

    • 通过类名获取,类名.class。
    • 通过对象获取,对象.getClass()。
    • 通过全类名获取,Class.forName(全类名)。
    package 

    通过Class对象创建实例

    package 

    反射机制带来什么好处?

    比如现在我们设计一个车辆生产的工厂类,可以生产小汽车、货车等车辆,代码编写如下:

    // 小汽车和火车都继承Car类
    

    此时工厂需要生产火车,工厂代码需要进行修改:

    /** 
    

    按照以上代码可以发现,当增加汽车类别的时候,需要修改工厂类,非常不方便,如果使用反射机制将会使得工厂类不需要进行再次修改:

    class 

    因此从这方面看使用反射将使得程序变得更加灵活简单。

    Class API详解

    方法名功能说明static Class<?> forName(String className)返回与具有给定字符串名称的类或接口关联的对象ClassT newInstance()创建由此对象表示的类的新实例ClassString getName()返回此对象表示的实体的名称(类、接口、数组类、基元类型或 void)Package getPackage()获取此类的包int getModifiers()返回此类或接口的 Java 语言修饰符,该修饰符以整数编码Method[] getMethods()返回一个数组,其中包含反映此对象表示的类或接口的所有公共方法的对象,包括由类或接口声明的对象以及从超类和超级接口继承的对象Method getMethod(String ,Class<?>...parameterTypers)返回一个对象,该对象反映此对象表示的类或接口的指定公共成员方法Class<?> getInterfaces()确定由此对象表示的类或接口实现的接口Type getGenericSuperclass()<U> Class<? extends U> asSubclass(Class<U> clazz)强制转换此对象以表示由指定类对象表示的类的子类T cast(Object obj)将对象强制转换到此对象表示的类或接口Class<? super T> getSuperclass()返回表示由 此 表示的实体的超类(类、接口、基元类型或 void)ClassLoader getClassLoader()返回该类的类加载器getFields()获取类中public类型的属性getField(String name)获取类中的属性,name参数指定了属性的名称getDeclaredFields()获取类中所有属性(public、protected、default、private),但不包括继承的属性getDeclaredField(String name)获取类中的属性(public、protected、default、private),name参数指定了属性的名称getConstructors()获取类中的public构造方法getConstructor(Class[] params)获取类的特定构造方法,params参数指定构造方法的参数类型getDeclaredConstructors()获取类中所有的构造方法(public、protected、default、private)getDeclaredConstructor(Class[] params)获取类的特定构造方法(public、protected、default、private),params参数指定构造方法的参数类型getDeclaredMethods()获取类中所有的方法(public、protected、default、private)getDeclaredMethods(String name,Class[] params)获取类中指定名称的方法,name参数指定方法的名字,parms参数指定方法的参数类型

    接下来我们将通过实例来演示API的具体使用

    现在我们有一个车类,其中具备有三个属性车辆颜色、速度、允许最高速度,还有drive方法。

    class 

    类的操作我们可以从实例的创建、属性值修改以及方法调用三个方面来完成。

    创建汽车实例

    1. 通过Class中的newInstance方法创建

    package 

    2. 通过构造方法创建

    构造方法的获取有如下4种方式

    fe1dbdcd6ce3f4b989bab052c018f573.png

    调用不带参构造方法

    package 

    调用带参构造方法

    package 

    操作属性

    属性操作API主要有以下4个

    7db233a454228cf110e890f0daa0c607.png

    公有属性

    getField方法调用公有属性

    package 

    私有属性

    getDeclaredField可以获取非公有属性

    package 

    方法调用

    方法调用API主要有以下4个

    aba4b3bb8f4974764bb9a74e8c2c00b7.png

    公有方法

    getMethod方法获取公有属性

    package 

    私有方法

    getDeclaredMethod方法获取非公有属性

    package 

    破坏单例模式

    如下使用双重锁实现的单例模式,单例模式的特点就是对象只会存在一个,如果需要破坏单例只需要使得对象实例存在多个即可。

    class 

    使用反射破坏单例模式示例:

    package 

    打印结果:false,根据结果可以判断出single1与single2并非一个对象,因此单例得到破坏

    控制反转

    控制反转定义

    控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则, Martin Fowler教授提出的一种软件设计模式,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫依赖查找(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。

    下面举例说明IoC,现在有一辆车,车子中有引擎,普通实现如下:

    // 引擎
    

    此时如果需要改变引擎对象,需要修改类Car中的引擎才可以做到,而使用IoC实现,代码如下:

    interface 

    IoC是一个很大的概念,可以用不同的方式实现。其主要形式有两种:

    • 依赖查找:容器中的受控对象通过容器的API来查找自己所依赖的资源和协作对象。这种方式虽然降低了对象间的依赖,但是同时也使用到了容器的API,造成了我们无法在容器外使用和测试对象。 依赖查找是一种更加传统的IoC实现方式。依赖查找也有两种类型:依赖拖拽(DP)和上下文化依赖查找(CDL)
    • 依赖注入:组件不做定位查询,只提供普通的Java方法让容器去决定依赖关系。容器全权负责的组件的装配,它会把符合依赖关系的对象通过JavaBean属性或者构造函数传递给需要的对象。通过JavaBean属性注射依赖关系的做法称为设值方法注入(Setter Injection);将依赖关系作为构造函数参数传入的做法称为构造器注入(Constructor Injection)

    依赖查找

    依赖拖拽(Dependency Pull)-DP

    依赖拖拽:依赖项是根据需要从注册表中拉来的 。

    public 

    上下文依赖查找(Contextualized Dependency Lookup)-CDL

    上下文依赖查找:在某些方面跟依赖拖拽类似,但是上下文依赖查找中,查找的过程是在容器管理的资源中进行的,而不是从集中注册表中,并且通常是作用在某些设置点上

    public 

    依赖注入(Dependency Injection)-DI

    依赖注入就是将服务注入到使用它的地方。对象只提供普通的方法让容器去决定依赖关系,容器全权负责组件的装配,它会把符合依赖关系的对象通过属性(JavaBean中的setter)或者是构造子传递给需要的对象。

    public 

    深入探讨可以加笔者QQ:1120855315

    点击获取免费Java免费视频

    添加QQ群837949026可以领取更多学习资料

    展开全文
  • 前面给大家介绍了一下什么是java反射机制,那么下面要给大家介绍的就是java反射机制的原理,那么它的原理究竟是怎样的呢?...一、java反射机制原理下面是我们经常可以见到的反射例子:Class>clz=Class....

    前面给大家介绍了一下什么是java反射机制,那么下面要给大家介绍的就是java反射机制的原理,那么它的原理究竟是怎样的呢?下面就通过下面来做一下详细的了解吧。

    首先我们再来介绍一下java反射机制。

    java反射机制就是java程序在运行的时候动态的创建类并调用类的方法以及属性。

    下面就来介绍一下原理。

    一、java反射机制原理

    下面是我们经常可以见到的反射例子:Class

    > clz = Class.forName("java.util.ArrayList");

    ArrayList object = (ArrayList) clz.newInstance();

    Method method = clz.getMethod("add",Object.class);

    method.invoke(list , "sss");

    来分析一下:

    前面的2行实现了类的装载、链接、初始化。

    后面的2行实现了从class对象当中,获取对象,之后执行反射调用。

    这里的话让我们来设想一下,如果,要实现Invoke方法,那么是不是只要实现下面的类就可以了呢?public class Method

    {

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

    {

    ArrayList list = (ArrayList) obj;

    list.add(args);

    }

    }

    反射的原理之一就是动态的生成类似上面的字节码,加载到jvm当中运行。

    再一起来看看Method对象流程。

    上面的Class对象是在加载类的时候,由jvm构造的。

    jvm为每一个类管理一个独一无二的Class对象,这个Class对象里维护着这个类的所有

    Method、Field、Constructor的cache,这份cache可以被叫做是根对象,每一次,getMethod获取到的Method对象都持有对根对象的引用。

    由于一些重量级的Method的成员变量,大多数都不希望每次在创建Method对象的时候,都要重新进初始化,所以,所有代表同一个方法的Method对象都共享着根对象的MethodAccessor,每一次创建都会调用根对象的copy方法复制一份。Method copy()

    {

    Method res = new Method(clazz, name, parameterTypes, returnType

    , exceptionTypes, modifiers, slot, signature

    , annotations, parameterAnnotations, annotationDefault);

    res.root = this;

    res.methodAccessor = methodAccessor;

    return res;

    }

    调用invoke方法流程

    首先的话,method.invoke方法会获取一个MethodAccessor。

    会先从Method的根对象当中获取MethodAccessor。

    假如是空,那么用reflectionFactory.newMethodAccessor返回DelegatingMethodAccessorImpl实例。

    之后再把MethodAccessor赋值给Method的root对象当中,之后调用DelegatingMethodAccessorImpl当中的invoke方法。

    在调用invoke的次数大于15次之后,MethodAccessor将由java代码生成。

    关于java反射机制原理就给你介绍到这里了,更多java反射机制常见问题,可以继续关注本站来了解。

    推荐阅读:

    展开全文
  • 对于java反射机制你了解多少呢?很多人表示对于它的原理都不是很清楚,下面就一起来详细的进行一下了解吧!首先我们要清楚概念,一切皆对象,类也是对象;之后要晓得类当中的东西,modifier constructor field method;...

    对于java反射机制你了解多少呢?很多人表示对于它的原理都不是很清楚,下面就一起来详细的进行一下了解吧!

    首先我们要清楚概念,一切皆对象,类也是对象;

    之后要晓得类当中的东西,modifier constructor field method;

    之后要晓得加载,当Animal.class在硬盘中的时候,是一个文件,在载入到内存当中的时候,可以认为是一个对象,是java.lang.class的对象;

    在运行程序的时候,实例化时产生Animal.class对象,那么这两个对象有什么不同呢?

    可以看一下下面的图片

    上面的Animal.class对象是java.lang.class的对象,下面的对象是Animal.class实例化产生的对象。

    f329b1c3b5228a3cde94304369366cab.png

    当Animal.class载入到JVM中的时候,JVM又是如何识别Animal.class当中含有的方法,成员变量,构造方法等内容的呢?

    可以看一下下图

    Animal.class实例化对象中成员变量 ,毛色 =红色;

    加载到内存时,毛色=null,是在实例化的时候毛色被赋值为红色;

    628f709589fe5d98ee95cd63a95b7e5d.png

    Animal.class当中,毛色这个属性对于java.lang.class来说是Field的一个属性值,毛色对于java.lang.class来说也是一个对象,这也是反射机制动态获取信息以及动态调用对象方法的原因。

    下面是Java.lang.class中的方法:

    132f7bc3c30b7e78c26679112d0b6588.png

    0ecf71fb06e93c8eda97dd302dd91fdf.png

    712662f59dbcab7b1e975e96f56dfaae.png

    在java.lang.class当中,毛色是Field的一个属性值,Animal中所有的方法,成员变量,构造器,修饰符都是按照java.lang.class中的标准去写的,否则的话会在编译的时候报错。

    df72154f32528c54afe7bfdfdf8227de.png

    放射机制简单实例代码public class _14_ReflectTest07

    {

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

    {

    //1.获取类

    Class c = Class.forName("_12_CustomerService");

    //获取某个特定的方法

    //通过:方法名+形参列表

    Method m = c.getDeclaredMethod("login", String.class, String.class);

    //通过反射机制执行login方法.

    Object o = c.newInstance();

    //调用o对象的m方法,传递"admin""123"参数,方法的执行结果是retValue

    Object retValue = m.invoke(o, "admin", "123");

    System.out.println(retValue); //true

    }

    }public class _12_CustomerService

    {

    //登录

    public boolean login(String name, String pwd)

    {

    if ("admin".equals(name) && "123".equals(pwd))

    {

    return true;

    }

    return false;

    }

    //退出

    public void logout()

    {

    System.out.println("系统已安全退出!");

    }

    }

    以上的内容你都清楚了吗?更多java基础知识,请继续关注奇Q工具网来进行了解吧,更多的内容可以为你分享。

    推荐阅读:

    展开全文
  • java反射机制的实现原理java反射机制有什么用,具体举例说明增加程序的灵活性。 如struts中。请CSS布局HTML小编今天和大家分享的派发控制。 当请CSS布局HTML小编今天和大家分享来到时。struts通过查询配置文件。找到...
  • 一 , 什么是java反射机制JAVA反射机制是在运行状态中,对于任意一个实体类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能...
  • Python之反射机制详解」Python小宇宙2020-08-26 16:51:46前言def f1(): print('f1')def f2(): print('f2')def f3(): print('f3')def f4(): print('f4')a = 1import test as ssss.f1()ss.f2()print(ss.a)我们要导入...
  • 目录什么是JAVA的反射机制JDK中提供的Reflection APIJAVA反射机制提供了什么功能获取类的Class对象获取类的Fields获取类的Method获取类的Constructor新建类的实例Class的函数newInstance通过Constructor对象的方...
  • 走过路过不要错过点击蓝字关注我们一、反射的概念及在Java中的类反射反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力。...在Java中的反射机制,被称为Reflection。(大家看到这个单词,第一...
  • JAVA反反射射机机制制实实例例详详解解 这篇文章主要介绍了JAVA反射机制,以实例形式较为详细的分析讲解了Java反射机制的具体概念功能与使用技巧, 具 一定参考借鉴价值,需要的朋友可以参考下 本文实例分析了JAVA反射...
  • 主要介绍了Java 反射机制原理与用法,结合实例形式详细分析了Java反射机制的相关概念、原理、基本使用方法及操作注意事项,需要的朋友可以参考下
  • 这种动态获取类信息和动态调用对象方法和属性的功能就是Java反射机制。注意定义中的措辞,是所有的方法和属性,即使是私有的也能调用。所以功能是非常强大的。但在我们日常开发中很少会用到反射机制,因为正是这种...
  • Java的类反射机制原理详解

    万次阅读 2018-08-05 20:39:02
    [原文](https://blog.csdn.net/sinat_38259539/article/details/71799078) Java的类反射机制 反射是框架设计的灵魂 (使用...
  • 反射(Reflection) 是 Java 程序开发语言的特征之一,它允许运行中的 Java ...在面试中面试官也经常对反射问题进行考察,反射是所有注解实现的原理,尤其在框架设计中,有不可替代的作用。关于反射,常见的面试考察点...
  • java编程:java反射机制原理案例详解

    千次阅读 2015-06-08 11:09:23
    本文采用案例讲解的方式生动的讲解了java反射原理和使用场景。 本文链接:http://blog.csdn.net/xiong_it/article/details/46409875 本篇文章依旧采用小例子来说明,因为我始终觉的,案例驱动是最好的,要不然只看...
  • Java反射机制详解

    2020-09-03 01:54:51
    主要介绍了Java反射机制,首先简单介绍了反射机制的预备知识,进一步分析了Java反射机制原理、实现技巧与应用方法,需要的朋友可以参考下
  • JAVA反射机制详解

    2011-05-13 21:32:42
    详细讲解的JAVA的反射机制JAVA反射的工作原理详细讲解的JAVA的反射机制JAVA反射的工作原理详细讲解的JAVA的反射机制JAVA反射的工作原理
  • Java 反射机制详解

    2020-03-08 11:36:18
    文章目录Java 反射机制详解1、什么是反射2、反射的原理3、反射的用途4、反射的优缺点5、反射的基本使用 1、什么是反射 反射是Java的特征之一,是一种间接操作目标对象的机制,核心是JVM在运行的时候才动态加载类,...
  • 深入理解java的Class与反射机制 https://blog.csdn.net/javazejian/article/details/70768369 那为什么需要这样一个Class对象呢?是这样的,当我们new一个新对象或者引用静态成员变量时,Java虚拟机(JVM)中的类加载...
  • JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。JAVA反射...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 122
精华内容 48
关键字:

java反射机制原理详解

java 订阅