Java 反射机制的实例详解

Java 反射机制的实例详解

前言

今天介绍下Java的反射机制,以前我们获取一个类的实例都是使用new一个实例出来。那样太low了,今天跟我一起来学习学习一种更加高大上的方式来实现。

正文

Java反射机制定义

Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 用一句话总结就是反射可以实现在运行时可以知道任意一个类的属性和方法。

反射机制的优点与缺点

为什么要用反射机制?直接创建对象不就可以了吗,这就涉及到了动态与静态的概念

静态编译:在编译时确定类型,绑定对象,即通过。

动态编译:运行时确定类型,绑定对象。动态编译最大限度发挥了java的灵活性,体现了多态的应用,有以降低类之间的藕合性。

优点

可以实现动态创建对象和编译,体现出很大的灵活性,特别是在J2EE的开发中它的灵活性就表现的十分明显。比如,一个大型的软件,不可能一次就把把它设计的很完美,当这个程序编译后,发布了,当发现需要更新某些功能时,我们不可能要用户把以前的卸载,再重新安装新的版本,假如这样的话,这个软件肯定是没有多少人用的。采用静态的话,需要把整个程序重新编译一次才可以实现功能的更新,而采用反射机制的话,它就可以不用卸载,只需要在运行时才动态的创建和编译,就可以实现该功能。

缺点

对性能有影响。使用反射基本上是一种解释操作,我们可以告诉JVM,我们希望做什么并且它满足我们的要求。这类操作总是慢于只直接执行相同的操作。

理解Class类和类类型

想要了解反射首先理解一下Class类,它是反射实现的基础。

类是java.lang.Class类的实例对象,而Class是所有类的类(There is a class named Class) 对于普通的对象,我们一般都会这样创建和表示:

Code code1 = new Code();

上面说了,所有的类都是Class的对象,那么如何表示呢,可不可以通过如下方式呢:

Class c = new Class(); 

但是我们查看Class的源码时,是这样写的:

private Class(ClassLoader loader) {
classLoader = loader;
}

可以看到构造器是私有的,只有JVM可以创建Class的对象,因此不可以像普通类一样new一个Class对象,虽然我们不能new一个Class对象,但是却可以通过已有的类得到一个Class对象,共有三种方式,如下:

Class c1 = Code.class; 

这说明任何一个类都有一个隐含的静态成员变量class,这种方式是通过获取类的静态成员变量class得到的

Class c2 = code1.getClass(); 

code1是Code的一个对象,这种方式是通过一个类的对象的getClass()方法获得的

Class c3 = Class.forName(“com.trigl.reflect.Code”); 

这种方法是Class类调用forName方法,通过一个类的全量限定名获得 ,这里,c1、c2、c3都是Class的对象,他们是完全一样的,而且有个学名,叫做Code的类类型(class type)。 这里就让人奇怪了,前面不是说Code是Class的对象吗,而c1、c2、c3也是Class的对象,那么Code和c1、c2、c3不就一样了吗?为什么还叫Code什么类类型?这里不要纠结于它们是否相同,只要理解类类型是干什么的就好了,顾名思义,类类型就是类的类型,也就是描述一个类是什么,都有哪些东西,所以我们可以通过类类型知道一个类的属性和方法,并且可以调用一个类的属性和方法,这就是反射的基础。

举个简单例子代码:

public class ReflectDemo {
public static void main(String[] args) throws ClassNotFoundException {
//第一种:Class c1 = Code.class;
Class class1=ReflectDemo.class;
System.out.println(class1.getName());

  //第二种:Class c2 = code1.getClass();
  ReflectDemo demo2= new ReflectDemo();
  Class c2 = demo2.getClass();
  System.out.println(c2.getName());

  //第三种:Class c3 = Class.forName("com.trigl.reflect.Code");
  Class class3 = Class.forName("com.tengj.reflect.ReflectDemo");
  System.out.println(class3.getName());
}
}

执行结果:

com.tengj.reflect.ReflectDemo
com.tengj.reflect.ReflectDemo
com.tengj.reflect.ReflectDemo

Java反射相关操作

前面我们知道了怎么获取Class,那么我们可以通过这个Class干什么呢?

总结如下:

获取成员方法Method
获取成员变量Field
获取构造函数Constructor

下面来具体介绍

获取成员方法信息

单独获取某一个方法是通过Class类的以下方法获得的:

public Method getDeclaredMethod(String name, Class c){

}

如有疑问请留言或者到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

时间: 2017-10-14

java获取版本号及字节码编译版本方法示例

前言 之所以会有这篇文章,是因为公司的开发环境比较老,寻找一些jar包的时候总是会纠结对应的编译版本,感觉很麻烦,所以写了一个工具类用于读取class或jar文件的编译版本,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧. 示例代码 package com.jinggujin.util; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; import java.

Java编程基础测试题分享

单选题:(每道题目2分) 1. 下列哪个声明是错误的?(B) A.  int i=10; B.  float f=1.1;     //float f=1.1f C.  double d=34.4; D.  byte b=127; long类型的数据加后缀L或者l float类型的数据加后缀F或者f 整数默认是int类型 浮点数默认是double类型 2. 下面哪个不是java中的关键字?(C) A. public B.  true C.  main D.  class 3. 下面程序哪个语句是

老生常谈JavaScript面向对象基础与this指向问题

前 言 我们的程序语言经历了从"面向机器".到"面向过程".再到"面向对象"的一个过程.而JavaScript是一门基于对象的一门语言,它介于面向过程与面向对象之间.在学习JavaScript的过程中,OOP是非常重要的一环,下面我们来一起探讨一下JS中的面向对象吧!!! 1 .OOP的基础问题 1.1什么是面向过程和面向对象? 面向过程:专注于如何去解决一个问题的过程步骤.编程特点是由一个个的函数去实现每一步的过程步骤,没有类和对象的概念. 面

Java 动态代理原理分析

Java 动态代理原理分析 概要 AOP的拦截功能是由java中的动态代理来实现的.说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行之前,或者目标类函数执行之后,或者在目标类函数抛出异常时候执行.Spring中的动态代理是使用Cglib进行实现的.我们这里分析的是JDK中的动态代理实现机制. 下面我们通过例子快速了解JDK中的动态代理实现方式. 示例 需要代理的接口 public interface IHello { public void sayHel

java实现可安装的exe程序实例详解

java实现可安装的exe程序实例详解 通过编写Java代码,实现可安装的exe文件的一般思路: 1.在eclipse中创建java项目,然后编写Java代码,将编写好的Java项目导出一个.jar格式的jar包: 2.通过安装exe4j软件,将导出的.jar格式的文件制作成.exe格式的可执行的文件,(注意:此时的.exe文件只是可以执行,还不能够安装): 3.通过安装Inno setup软件,将可执行的.exe格式的文件..jar格式的文件以及其它需要的文件制作成一个可安装的.exe格式的文

详解Java中@Override的作用

详解Java中@Override的作用 @Override是伪代码,表示重写(当然不写也可以),不过写上有如下好处: 1.可以当注释用,方便阅读: 2.编译器可以给你验证@Override下面的方法名是否是你父类中所有的,如果没有则报错.例如,你如果没写@Override,而你下面的方法名又写错了,这时你的编译器是可以编译通过的,因为编译器以为这个方法是你的子类中自己增加的方法. 举例:在重写父类的onCreate时,在方法前面加上@Override 系统可以帮你检查方法的正确性. @Overr

详解Java中hashCode的作用

详解Java中hashCode的作用 以下是关于HashCode的官方文档定义: hashcode方法返回该对象的哈希码值.支持该方法是为哈希表提供一些优点,例如,java.util.Hashtable 提供的哈希表. hashCode 的常规协定是: 在 Java 应用程序执行期间,在同一对象上多次调用 hashCode 方法时,必须一致地返回相同的整数,前提是对象上 equals 比较中所用的信息没有被修改.从某一应用程序的一次执行到同一应用程序的另一次执行,该整数无需保持一致. 如果根据

详解JAVA中static的作用

1.深度总结 引用一位网友的话,说的非常好,如果别人问你static的作用:如果你说静态修饰 类的属性 和 类的方法 别人认为你是合格的:如果是说 可以构成 静态代码块,那别人认为你还可以: 如果你说可以构成 静态内部类, 那别人认为你不错:如果你说了静态导包,那别人认为你很OK: 那我们就先在这几方面一一对static进行总结:然后说一些模糊的地方,以及一些面试中容易问道的地方: 1)static方法 static方法一般称作静态方法,由于静态方法不依赖于任何对象就可以进行访问,因此对于静态方

详解Java中多线程异常捕获Runnable的实现

详解Java中多线程异常捕获Runnable的实现 1.背景: Java 多线程异常不向主线程抛,自己处理,外部捕获不了异常.所以要实现主线程对子线程异常的捕获. 2.工具: 实现Runnable接口的LayerInitTask类,ThreadException类,线程安全的Vector 3.思路: 向LayerInitTask中传入Vector,记录异常情况,外部遍历,判断,抛出异常. 4.代码: package step5.exception; import java.util.Vector

详解Java中list,set,map的遍历与增强for循环

详解Java中list,set,map的遍历与增强for循环 Java集合类可分为三大块,分别是从Collection接口延伸出的List.Set和以键值对形式作存储的Map类型集合. 关于增强for循环,需要注意的是,使用增强for循环无法访问数组下标值,对于集合的遍历其内部采用的也是Iterator的相关方法.如果只做简单遍历读取,增强for循环确实减轻不少的代码量. 集合概念: 1.作用:用于存放对象 2.相当于一个容器,里面包含着一组对象,其中的每个对象作为集合的一个元素出现 3.jav

详解java中的PropertyChangeSupport与PropertyChangeListener

详解java中的PropertyChangeSupport与PropertyChangeListener java中的PropertyChangeSupport与PropertyChangeListener配合使用能够实现,绑定属性会在属性值发生变化时,通知所有相关的监听器. javaBean: package com.wang.test.property; import java.beans.PropertyChangeListener; import java.beans.PropertyC

详解Java中Comparable和Comparator接口的区别

详解Java中Comparable和Comparator接口的区别 本文要来详细分析一下Java中Comparable和Comparator接口的区别,两者都有比较的功能,那么究竟有什么区别呢,感兴趣的Java开发者继续看下去吧. Comparable 简介 Comparable 是排序接口. 若一个类实现了Comparable接口,就意味着"该类支持排序".  即然实现Comparable接口的类支持排序,假设现在存在"实现Comparable接口的类的对象的List列表(

详解Java中的sleep()和wait()的区别

详解Java中的sleep()和wait()的区别 对于sleep()方法,我们首先要知道该方法是属于Thread类中的.而wait()方法,则是属于Object类中的. sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态. 在调用sleep()方法的过程中,线程不会释放对象锁. 而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象

详解Java中数组判断元素存在几种方式比较

1. 通过将数组转换成List,然后使用List中的contains进行判断其是否存在 public static boolean useList(String[] arr,String containValue){ return Arrays.asList(arr).contains(containValue); } 需要注意的是Arrays.asList这个方法中转换的List并不是java.util.ArrayList而是java.util.Arrays.ArrayList,其中java.

详解Java 中的UnitTest 和 PowerMock

学习一门计算机语言,我觉得除了学习它的语法外,最重要的就是要学习怎么在这个语言环境下进行单元测试,因为单元测试能帮你提早发现错误:同时给你的程序加一道防护网,防止你的修改破坏了原有的功能:单元测试还能指引你写出更好的代码,毕竟不能被测试的代码一定不是好代码:除此之外,它还能增加你的自信,能勇敢的说出「我的程序没有bug」. 每个语言都有其常用的单元测试框架,本文主要介绍在 Java 中,我们如何使用 PowerMock,来解决我们在写单元测试时遇到的问题,从 Mock 这个词可以看出,这类问题主