本文为作者原创,转载请注明出处(http://www.cnblogs.com/mar-q/)by 负赑屃

  反射reflection主要为了动态操作Java代码,它的主要功能体现在Java提供的reflection library中,在《Java核心技术》中总结反射作用:1、在运行中对类的结构进行动态分析;2、在运行中查看对象;3、实现通用的数组操作;4、利用Method对象。下面分几个章节,结合书中的代码,来仔细看看这四个作用是如何实现的(第一部分是理解反射机制的关键)。

一、类的动态分析

  在Java代码运行时,会为每个对象维护一个类型标识,通过Java中提供的Class类可以访问这些信息。我们知道,在Java中Object类是所有类的父类,Object类中提供了一个getClass()方法,可以返回一个Class类的实例。当你用任意一个类对象来调用这个getClass方法时,返回的Class实例对象就可以标识出类对象的属性。例如:

//根据对象获取类名
Date d = new Date();
Class dateClass = d.getClass();
String dateName = dateClass.getName();
//根据类名获取Class对象,并根据这个Class对象创建类名下的实例对象
try{
  Class cl = Class.forName(dateName);
  Object xx = cl.newInstance();
} cathc(ClassNotFoundException e){
  e.printStackTrace();
}

  Date是java.util常用的日期类,这里定义了一个Date对象d,通过d.getClass()方法获取Class类的实例,该实例包含了Date类的属性,例如类名称、类构造函数、类方法、类变量常量等等信息,通过Class类的getName()方法就可以获取类名,上面String打印出来我们可以看到结果是java.util.Date,是的,返回的类名中还包括了包名。还可以调用Class中的静态方法forName()获得类名对应的Class对象,并根据这个Class对象为类名对应的类创建实例,注意这里会抛出一个异常。

  上面听起来有点绕,打个比方,这个Class类有点像盖房子的设计图,设计图中包含了房子的所有细节信息,我们可以根据房子获取到设计图,从而获得房子的尺寸、房型等等信息,也可以根据设计图再盖一栋一样的房子。

  除了通过getClass和getName方法获取Class对象外,还可以通过类名.class的方法生成Class对象。例如

Class c1 = Date.class;
Class c2 = int.class;
Class c3 = Double[].class;

  注意,在上面的代码中,Class对象实现代表一个类型,不一定是一个类,例如int。我们可以通过==运算实现两个Class对象的比较操作,例如date.getClass()==Date.class。

  知道上面这些内容,我们基本就可以利用反射来分析类的能力了,一个类主要就是三个部分:域(Field,包括常量、变量等)、方法(Method)、构造函数(Constructor构造器),要分析一个类主要就是查看类的三部分构成。我们用reflect库中的三个类:Filed、Method、Constructor来描述类的能力,书中提供了一个打印类全部信息的方法,我会和大家一起仔细阅读这份代码:ReflectionTest.java

public class ReflectionTest{
public static void main(String[] args){
// 通过main函数参数列表或者用户输入来读取类名,保存为name
String name;
if (args.length > 0) name = args[0];
else{
Scanner in = new Scanner(System.in);
System.out.println("Enter class name (e.g. java.util.Date): ");
name = in.next();
}
try{
// 打印出类名及其父类名(包括包名)
Class cl = Class.forName(name);//通过forName()方法获取Class对象
Class supercl = cl.getSuperclass();//通过getSuperclass()获取父类Class对象
String modifiers = Modifier.toString(cl.getModifiers());//反射库中的Modifier类,可以获取类或者Field、Method、Constructor的
                                       //public、private、static、final等修饰符描述
if (modifiers.length() > 0) System.out.print(modifiers + " ");
System.out.print("class " + name);
if (supercl != null && supercl != Object.class) System.out.print(" extends "
+ supercl.getName());
System.out.print("\n{\n");
printConstructors(cl);//打印类的构造器
System.out.println();
printMethods(cl);//打印类中的方法
System.out.println();
printFields(cl);//打印类中的常量、变量等域信息
System.out.println("}");
}catch (ClassNotFoundException e){//如果没有找到你所输入的类,则返回一个异常
e.printStackTrace();
}
System.exit(0);
} /**
* 打印类的构造器
* @param 参数为Class对象
*/
public static void printConstructors(Class cl){
Constructor[] constructors = cl.getDeclaredConstructors();//定义了一个Constructor[]数组保存类的构造器
for (Constructor c : constructors){
String name = c.getName();//获取构造器名称
System.out.print(" ");
String modifiers = Modifier.toString(c.getModifiers());//获取构造器的修饰符
if (modifiers.length() > 0) System.out.print(modifiers + " ");
System.out.print(name + "(");
Class[] paramTypes = c.getParameterTypes();//获取参数的列表
for (int j = 0; j < paramTypes.length; j++){
if (j > 0) System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.println(");");
}
} /**
* 打印类中的所有方法,对比构造器,多了一个返回值类型
* @param 参数为Class对象
*/
public static void printMethods(Class cl){
Method[] methods = cl.getDeclaredMethods();//定义一个Method[]数组保存类中的方法
for (Method m : methods){
Class retType = m.getReturnType();//获取Method的返回值类型
String name = m.getName();//获取Method名
System.out.print(" ");
String modifiers = Modifier.toString(m.getModifiers());//获取Method的修饰符
if (modifiers.length() > 0) System.out.print(modifiers + " ");
System.out.print(retType.getName() + " " + name + "(");
// print parameter types
Class[] paramTypes = m.getParameterTypes();//获取Method参数列表
for (int j = 0; j < paramTypes.length; j++){
if (j > 0) System.out.print(", ");
System.out.print(paramTypes[j].getName());
}
System.out.println(");");
}
} /**
* 打印类中的所有域
* @param 参数为Class对象
*/
public static void printFields(Class cl){
Field[] fields = cl.getDeclaredFields();//定义一个Field[]数组保存类的所有域
for (Field f : fields){
Class type = f.getType();//获取域的类型
String name = f.getName();
System.out.print(" ");
String modifiers = Modifier.toString(f.getModifiers());//获取域的修饰符
if (modifiers.length() > 0) System.out.print(modifiers + " ");
System.out.println(type.getName() + " " + name + ";");
}
}
}

  我们可以输入任意的类名,如java.util.Date或者你自己定义的某个类,获取该类的能力分析,注意名称不要输入错误,否则将打印一个异常信息。

/************

//二、利用反射分析对象

//  在编写代码时要想查看对象的域名和类型是一件很容易的事情,但是利用反射机制我们可以在编译时查看还不清楚的对象域。查看对象域的关键方法是Field类中的get方法,

*************/

聊聊Java中的反射(一)的更多相关文章

  1. Java中的反射和注解

    前言 在Java中,反射机制和注解机制一直是一个很重要的概念,那么他们其中的原理是怎么样呢,我们不仅仅需要会使用,更要知其然而之所以然. 目录 反射机制 反射如何使用 注解定义 注解机制原理 注解如何 ...

  2. java中的反射机制在Android开发中的用处

    JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反 ...

  3. 浅说Java中的反射机制(二)

    写过一篇Java中的反射机制,不算是写,应该是抄了,因为那是别人写的,这一篇也是别人写的,摘抄如下: 引自于Java基础--反射机制的知识点梳理,作者醉眼识朦胧.(()为我手记) 什么是反射? 正常编 ...

  4. 浅说Java中的反射机制(一)

    在学习传智播客李勇老师的JDBC系列时,会出现反射的概念,由于又是第一次见,不免感到陌生.所以再次在博客园找到一篇文章,先记录如下: 引用自java中的反射机制,作者bingoideas.(()为我手 ...

  5. java中动态反射

    java中动态反射能达到的效果和python的语法糖很像,能够截获方法的实现,在真实方法调用之前和之后进行修改,甚至能够用自己的实现进行特别的替代,也可以用其实现面向切片的部分功能.动态代理可以方便实 ...

  6. 简单聊聊java中的final关键字

    简单聊聊java中的final关键字 日常代码中,final关键字也算常用的.其主要应用在三个方面: 1)修饰类(暂时见过,但是还没用过); 2)修饰方法(见过,没写过); 3)修饰数据. 那么,我们 ...

  7. 第89节:Java中的反射技术

    第89节:Java中的反射技术 反射技术是动态的获取指定的类,和动态的调用类中的内容(没有类前就可以创建对象,将对象的动作完成,这就是动态的获取指定的类). 配置文件把具体实现的类名称定义到配置文件中 ...

  8. java笔记十:java中的反射

    Java中,反射是一种强大的工具.它使您能够创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代表链接.反射允许我们在编写与执行时,使我们的程序代码能够接入装载到JVM中的类的内部信息,而 ...

  9. 【Java基础】java中的反射机制与动态代理

    一.java中的反射机制 java反射的官方定义:在运行状态下,可以获取任意一个类的所有属性和方法,并且可通过某类任意一对象实例调用该类的所有方法.这种动态获取类的信息及动态调用类中方法的功能称为ja ...

随机推荐

  1. Hibernate的Configuration对象的configure()方法

    Configuration configuration=new Configuration(); configuration.configure(); 在Hibernate底层实现configure( ...

  2. PHP 动态调整内存限制

    最近公司的一个PHP项目在操作大文件的时候总是抛出这个异常 Fixing PHP Fatal Error: Allowed Memory Size Exhausted 经过一番调试后发现是达到了PHP ...

  3. 工作中对数组的一些处理,整理(结合underscore.js)

    1.数组里边相同元素提取成map,并以'',''分隔 例如:var arr = [{a:"xx",b:''xxx''},{a:"xxx",b:''xxxxx'' ...

  4. mybatis错误——java.io.IOException: Could not find resource com/xxx/xxxMapper.xml

    在学习Mybatis的时候,参考网上的教程进行简单demo的搭建,配置的没有问题,然后出现了下面的错误! Exception in thread "main" java.lang. ...

  5. 每周分享之 二 http协议(3)

    本次分享http协议,共分为三部分,这是第三部分,主要讲解一个完整的http请求都经过哪些步骤,当我们在地址栏中输入网址,到返回页面都经历了什么 1.输入网址 当我们在浏览器中输入网址的时候,浏览器就 ...

  6. Beautiful Dream hdu3418 (直接做或二分)

    Beautiful Dream Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)T ...

  7. Coin Change (IV) (dfs)

    Coin Change (IV) Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %lld & %llu [Subm ...

  8. 微软的一篇ctr预估的论文:Web-Scale Bayesian Click-Through Rate Prediction for Sponsored Search Advertising in Microsoft’s Bing Search Engine。

    周末看了一下这篇论文,觉得挺难的,后来想想是ICML的论文,也就明白为什么了. 先简单记录下来,以后会继续添加内容. 主要参考了论文Web-Scale Bayesian Click-Through R ...

  9. Island Perimeter

    You are given a map in form of a two-dimensional integer grid where 1 represents land and 0 represen ...

  10. Java历程-初学篇 Day07 循环结构2 for循环

    一,格式 for(赋值语句//为循环变量赋初值;条件语句//循环结构的循环条件;赋值语句//迭代,修改循环变量的值){ //循环体; } 二,简单举例 for(int i=1;i<=10;i++ ...