Java SE之初探反射机制
【Keywords】:Java,Hibernate,虚拟机,框架,SQL
【Abstract】: 反射的概念:所谓的反射就是java语言在运行时拥有一项自观的能力,反射使您的程序代码能够得到装载到JVM中的类的内部信息,允许您执行程序时才得到需要类的内部信息,而不是在编写代码的时候就必须要知道所需类的内部信息,这使反射成为构建灵活的应用的主要工具。
反射的常用类和函数:Java反射机制的实现要借助于4个类:Class,Constructor,Field,Method;其中class代表的是类对象,Constructor-类的构造器对象,Field-类的属性对象,Method-类的方法对象,通过这四个对象我们可以粗略的看到一个类的各个组成部分。其中最核心的就是Class类,它是实现反射的基础,它包含的方法我们在第一部分已经进行了基本的阐述。应用反射时我们最关心的一般是一个类的构造器、属性和方法。
一、预先需要掌握的知识(java虚拟机)
java虚拟机的方法区:
java虚拟机有一个运行时数据区,这个数据区又被分为方法区,堆区和栈区,我们这里需要了解的主要是方法区。方法区的主要作用是存储被装载的类的类型信息,当java虚拟机装载某个类型的时候,需要类装载器定位相应的class文件,然后将其读入到java虚拟机中,紧接着虚拟机提取class中的类型信息,将这些信息存储到方法区中。这些信息主要包括:
1、这个类型的全限定名
2、这个类型的直接超类的全限定名
3、这个类型是类类型还是接口类型
4、这个类型的访问修饰符
5、任何直接超接口的全限定名的有序列表
6、该类型的常量池
7、字段信息
8、方法信息
9、除了常量以外的所有类变量
10、一个到class类的引用
等等(读者可以参考《深入java虚拟机》这本书的叙述)
Class类:
Class类是一个非常重要的java基础类,每当装载一个新的类型的时候,java虚拟机都会在java堆中创建一个对应于新类型的Class实例,该实例就代表此类型,通过该Class实例我们就可以访问该类型的基本信息。上面说到在方法区中会存储某个被装载类的类型信息,我们就可以通过Class实例来访问这些信息。比如,对于上面说到的信息Class中都有对应的方法,如下:
1、getName();这个类型的全限定名
2、getSuperClass();这个类型的直接超类的全限定名
3、isInterface();这个类型是类类型还是接口类型
4、getTypeParamters();这个类型的访问修饰符
5、getInterfaces();任何直接超接口的全限定名的有序列表
6、getFields();字段信息
7、getMethods();方法信息
等等(读者可以自己参看jdk帮助文档,得到更多的信息)
二、java反射详解
反射的概念:所谓的反射就是java语言在运行时拥有一项自观的能力,反射使您的程序代码能够得到装载到JVM中的类的内部信息,允许您执行程序时才得到需要类的内部信息,而不是在编写代码的时候就必须要知道所需类的内部信息,这使反射成为构建灵活的应用的主要工具。
反射的常用类和函数:Java反射机制的实现要借助于4个类:Class,Constructor,Field,Method;其中class代表的是类对象,Constructor-类的构造器对象,Field-类的属性对象,Method-类的方法对象,通过这四个对象我们可以粗略的看到一个类的各个组成部分。其中最核心的就是Class类,它是实现反射的基础,它包含的方法我们在第一部分已经进行了基本的阐述。应用反射时我们最关心的一般是一个类的构造器、属性和方法,下面我们主要介绍Class类中针对这三个元素的方法:
1、得到构造器的方法
Constructor getConstructor(Class[] params) -- 获得使用特殊的参数类型的公共构造函数,
Constructor[] getConstructors() -- 获得类的所有公共构造函数
Constructor getDeclaredConstructor(Class[] params) -- 获得使用特定参数类型的构造函数(与接入级别无关)
Constructor[] getDeclaredConstructors() -- 获得类的所有构造函数(与接入级别无关)
2、获得字段信息的方法
Field getField(String name) -- 获得命名的公共字段
Field[] getFields() -- 获得类的所有公共字段
Field getDeclaredField(String name) -- 获得类声明的命名的字段
Field[] getDeclaredFields() -- 获得类声明的所有字段
3、获得方法信息的方法
Method getMethod(String name, Class[] params) -- 使用特定的参数类型,获得命名的公共方法
Method[] getMethods() -- 获得类的所有公共方法
Method getDeclaredMethod(String name, Class[] params) -- 使用特写的参数类型,获得类声明的命名的方法
Method[] getDeclaredMethods() -- 获得类声明的所有方法
应用反射的基本步骤:
1、获得你想操作的类的Class对象;
方法一:Class c=Class.forName("java.lang.String")
方法二:对于基本数据类型可以用形如Class c=int.class或Class c=Integer.TYPE的语句
方法三:Class c=MyClass.class
2、调用Class中的方法得到你想得到的信息集合,如调用getDeclaredFields()方法得到类的所有属性;
3、处理第2步中得到的信息,然后进行你想做的实际操作。
反射实例:
下面我将针对类的构造器、属性和方法分别举三个例子,向大家演示一下反射的应用过程。
1、构造器
步骤为:通过反射机制得到某个类的构造器,然后调用该构造器创建该类的一个实例
import java.lang.reflect.*;
public class ConstructorDemo{
public ConstructorDemo(){ }
public ConstructorDemo(int a, int b){
System.out.println("a="+a+"b="+b);
}
public static void main(String args[]){
try {
Class cls = Class.forName("ConstructorDemo");
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); }
}
}
2、属性
步骤为:通过反射机制得到某个类的某个属性,然后改变对应于这个类的某个实例的该属性值
import java.lang.reflect.*;
public class FieldDemo1{
public double d;
public static void main(String args[]){
try {
Class cls = Class.forName("FieldDemo1");
Field fld = cls.getField("d");
FieldDemo1 fobj = new FieldDemo1();
System.out.println("d = " + fobj.d);
fld.setDouble(fobj, 12.34);
System.out.println("d = " + fobj.d);
} catch (Throwable e){
System.err.println(e); }
}
}
3、方法
步骤为:通过反射机制得到某个类的某个方法,然后调用对应于这个类的某个实例的该方法
//通过使用方法的名字调用方法
import java.lang.reflect.*;
public class MethodDemo1{
public int add(int a, int b){
return a + b;
}
public static void main(String args[]){
try {
Class cls = Class.forName("MethodDemo1");
Class partypes[] = new Class[2];
partypes[0] = Integer.TYPE;
partypes[1] = Integer.TYPE;
Method meth = cls.getMethod("add", partypes);
MethodDemo1 methobj = new MethodDemo1();
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);
}
}
}
三、java反射的应用(Hibernate)
我们在第二部分中对java反射进行了比较系统的阐述,也举了几个简单的实例,下面我们就来讨论一下java反射的具体应用。前面我们已经知道,Java反射机制提供了一种动态链接程序组件的多功能方法,它允许程序创建和控制任何类的对象(根据安全性限制)之前,无需提前硬编码目标类。这些特性使得反射特别适用于创建以非常普通的方式与对象协作的库。例如,反射经常在持续存储对象为数据库、XML或其它外部格式的框架中使用。下面我们就已Hibernate框架为例像大家阐述一下反射的重要意义。
Hibernate是一个屏蔽了JDBC,实现了ORM的java框架,利用该框架我们可以抛弃掉繁琐的sql语句而是利用Hibernate中Session类的save()方法直接将某个类的对象存到数据库中,也就是所涉及到sql语句的那些代码Hibernate帮我们做了。这时候就出现了一个问题,Hibernate怎样知道他要存的某个对象都有什么属性呢?这些属性都是什么类型呢?如此,它在向数据库中存储该对象属性时的sql语句该怎么构造呢?解决这个问题的利器就是我们的java反射!
下面我们以一个例子来进行阐述,比如我们定义了一个User类,这个User类中有20个属性和这些属性的get和set方法,相应的在数据库中有一个User表,这个User表中对应着20个字段。假设我们从User表中提取了一条记录,现在需要将这条记录的20个字段的内容分别赋给一个User对象myUser的20个属性,而Hibernate框架在编译的时候并不知道这个User类,他无法直接调用myUser.getXXX或者myUser.setXXX方法,此时就用到了反射,具体处理过程如下:
1、根据查询条件构造PreparedStament语句,该语句返回20个字段的值;
2、Hibernate通过读取配置文件得到User类的属性列表list(是一个String数组)以及这些属性的类型;
3、创建myUser所属类的Class对象c;c=myUser.getClass();
4、构造一个for循环,循环的次数为list列表的长度;
4.1、读取list[i]的值,然后构造对应该属性的set方法;
4.2、判断list[i]的类型XXX,调用PreparedStament语句中的getXXX(i),进而得到i出字段的值;
4.3、将4.2中得到的值作为4.1中得到的set方法的参数,这样就完成了一个字段像一个属性的赋值,如此循环即可;
看到了吧,这就是反射的功劳,如果没有反射很难想象如果完成同样的功能会有多么难!但是反射也有缺点,比如性能比较低、安全性比较复杂等,这里就不在讨论这些东西,感兴趣的读者可以在网上找到答案,有很多的!
参考文档:Java反射原理 http://china-jianchen.iteye.com/blog/728774;
Java SE之初探反射机制的更多相关文章
- Java 核心类库之反射机制
1:什么是反射机制? 2:反射机制它可以做什么呢? 3:反射机制对应的API又是什么? 1):通过反射机制来获取一个对象的全限定名称(完整包名),和类名: 2):实例化Class对象 3):获取对象的 ...
- java.lang.Class<T> -- 反射机制
1反射机制是什么 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为jav ...
- Java进阶之reflection(反射机制)——反射概念与基础
反射机制是Java动态性之一,而说到动态性首先得了解动态语言.那么何为动态语言? 一.动态语言 动态语言,是指程序在运行时可以改变其结构:新的函数可以引进,已有的函数可以被删除等结构上的变化.比如常见 ...
- 在JAVA中,关于反射机制的讨论
一.什么是反射机制 简单的来说,反射机制指的是程序在运行时能够获取自身的信息.在java中,只要给定类的名字, 那么就可以通过反射机制来获得类的所有信息. 二.哪里用到反射机制 ...
- java工厂类与反射机制
java 简单工厂类 2012-04-22 15:44:07| 分类: java | 标签:java工厂类 简单工厂类 |举报|字号 订阅 简单工厂模式需要由以下角色组成: 接口 ...
- JAVA(五)反射机制/Annotation
成鹏致远 | lcw.cnblog.com |2014-02-04 反射机制 1.认识Class类 在正常情况下,必须知道一个类的完整路径之后才可以实例化对象,但是在 java中也允许通过一个对象来找 ...
- java的泛型与反射机制
什么是泛型? 泛型,即“参数化类型”.顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参) ...
- java.lang.Class<T> -- 反射机制及动态代理
Interface : Person package java_.lang_.component.bean; public interface Person { String area = " ...
- JAVA动态性之一一反射机制reflection
package com.bjsxt.reflection.test.bean; public class User { private int id; private int age; private ...
随机推荐
- 《ERP系统修正数据的sql文件》
第一 1.修正销售客户创建者的sql脚本: UPDATE e_sales_customers sc SET sc.user_id = ( SELECT tmp.user_id FROM ( SELEC ...
- CSS实现水平居中的5种思路
前面的话 水平居中是经常遇到的问题.看似方法较多,条条大路通罗马.但系统梳理下,其实都围绕着几个思路展开.本文将介绍关于水平居中的5种思路 text-align [思路一]:在父元素中设置text-a ...
- 学习笔记之csrf
CBV 添加 csrf 第一种: 指定方法方面添加 装饰器 @memethod_decorator(xxx) 第二种 全部添加: 注意 在类名前: @method_decorator(xxx,name ...
- Swagger2 配置
1. 每个请求都需要换取key: @Bean public Docket createRestApi() { //添加head参数start ParameterBuilder appId = new ...
- python 模块之-logging
python 模块logging import logging ### 简单使用格式 日志级别等级CRITICAL > ERROR > WARNING > INFO > ...
- day30 item系列
item 会将数据操作类似于字典的操作具体用到的方法 __getitem__(self, item): __setitem__(self, key, value): __delitem__(self, ...
- Leetcode 347.前K个高频元素 By Python
给定一个非空的整数数组,返回其中出现频率前 k 高的元素. 示例 1: 输入: nums = [1,1,1,2,2,3], k = 2 输出: [1,2] 示例 2: 输入: nums = [1], ...
- # BZOJ5300 [CQOI2018]九连环 题解 | 高精度 FFT
今天做了传说中的CQOI六道板子题--有了一种自己很巨的错觉(雾 题面 求n连环的最少步数,n <= 1e5. 题解 首先--我不会玩九连环-- 通过找规律(其实是百度搜索)可知,\(n\)连环 ...
- 洛谷 P1407 [国家集训队]稳定婚姻 解题报告
P1407 [国家集训队]稳定婚姻 题目描述 我国的离婚率连续7年上升,今年的头两季,平均每天有近5000对夫妇离婚,大城市的离婚率上升最快,有研究婚姻问题的专家认为,是与简化离婚手续有关. 25岁的 ...
- suoi37 清点更多船只 (卡空间线段树)
sbw巨佬的卡空间方法,把线段树的叶节点只记到长度为16的区间,然后在叶节点上暴力修改查询,这样点数是$\frac{N}{8}$的,可以过... orz #include<bits/stdc++ ...