Java反射入门

  Java这么多高灵活性,很多都是利用反射来实现的,所谓的反射是指,编译期间完全未知的classes,运行时,对任一个类(根据类名-字符串),能够知道这个类的所有属性和方法;对于任一个对象,都能够调用它的任意一个方法和属性。

简而言之,Java反射机制主要提供了以下功能:

  ?  在运行时判断任意一个对象所属的类;obj.getClass()

  ?  在运行时构造任意一个类的对象

  ?  在运行时判断任意一个类所具有的成员变量和方法

  ?  在运行时调用任意一个对象的方法

  下面我们先用一个简单小例体现一下Java Reflect上述的功能,然后模拟一下Java Reflect应用之一Hibernate的
ORMapping的实现。

Java反射功能测试

  首先定义一个User.java类,代码如下:

package reflect;

/**
 *  @author--zhipeng
 */
public class User {

	private String name;

	//构造方法1(默认构造方法)***********************
	public User(){

	}
	//构造方法2
	public User(String name){
		this.name=name;
	}
	//******自定义方法*************
	public void getMessage(){
		System.out.print("kobe bryant never stop trying");
	}
	//******重写toString方法,在测试的时候会用到*****
	@Override
	public String toString() {
		return "name:"+this.name;
	}
	//**************************
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

}

  下面我将在ReflectTest.java类中,首先获得User的类名,然后根据类名来获得类的方法、属性、注解等,并调用方法,代码如下:

package reflect;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import reflect.User;

/**
 *  @author--zhipeng
 */
public class ReflectTest {

	public static void main(String[] args) throws Exception {
		Class clazz = User.class;//获得User的类名,返回reflect.User
		Object obj = create(clazz);//创建User的一个对象
		System.out.println(obj);//输出对象,会调用对象的toString方法
		System.out.println("---------");
		invoke1(obj, "getMessage");//调用User对象的getMessage方法
	}
	/*
	**根据类名,new一个对象,并返回*/
	static Object create(Class clazz) throws Exception {
		//如果clazz含有无参数的构造方法,可以如下方式实例化
		//clazz.newInstance();
		//根据类名和参数(类型、个数),找到相应的构造方法-下面创建构造方法参数为String的构造方法
		Constructor con=clazz.getConstructor(String.class);
		//实例化对象
		Object obj=con.newInstance("myName is zhipeng");
		//返回对象
		return obj;
	}
	/*
	**根据对象,方法名(字符串),来调用方法*/
	static void invoke1(Object obj, String methodName)throws Exception{
		//getDeclaredMethods可以获取类本身(不包括父类)所有方法的名字(包括私有方法)**一般不用这种方法,私有的属性一般不能修改
		Method[] ms = obj.getClass().getDeclaredMethods();
		//getMethods可以获取类本身,以及父类的方法的名字,但不包括私有的方法
		ms = obj.getClass().getMethods();
		for (Method m : ms) {
			//如果方法名字匹配,则反射调用方法
			if (methodName.equals(m.getName()))
				m.invoke(obj, null);
		}
		/*
		**防止方法重载,可用下面的方式(可以指明参数)--与上面的for循环(无法防止方法重载)一个效果
		**Method m = obj.getClass().getMethod(methodName, null);
		**m.invoke(obj, null);
		*/
	}

	/*
	**根据类名获取类的属性(一般不直接操作属性)*/
	static void field(Class clazz) throws Exception {
		Field[] fs = clazz.getDeclaredFields();
		//fs = clazz.getFields();
		for (Field f : fs)
			System.out.println(f.getName());
	}
	/*
	**根据类名获取类的注解*/
	static void annon(Class clazz) throws Exception {
		Annotation[] as = clazz.getAnnotations();
		for (Annotation a : as)
			System.out.println(a.getName());
	}

}

  运行结果:

简单模拟ORMapping

  上面我们测试了Java反射所提供的基本功能,下面简单模拟Hibernate的OR映射,基本思路就是传入sql语句,将结果集包装为object,并将结果集的字段与object的属性映射好,代码如下:

package reflect;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

/**
 *  @author--zhipeng
 */
public class ORMTest {

	public static void main(String[] args)throws Exception{
		//将select结果集(这里为一条)包装为User对象,并将结果集的字段,与User对象的属性映射
		User user = (User) getObject(
				"select id as Id, name as Name, birthday as Birthday, money as Money  from user where id=1",
				User.class);
		System.out.println(user);
	}
	//获取一个ResultSet的字段(列)名
	private static String[] getColNames(ResultSet rs) throws SQLException {
		ResultSetMetaData rsmd = rs.getMetaData();
		int count = rsmd.getColumnCount();
		String[] colNames = new String[count];
		for (int i = 1; i <= count; i++) {
			colNames[i - 1] = rsmd.getColumnLabel(i);
		}
		return colNames;
	}
	//传入一个sql语句与类名,返回一个相应类的对象
	static Object getObject(String sql, Class clazz) throws SQLException,Exception,
	 IllegalAccessException, InvocationTargetException
	{
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			//JdbcUtils为自定义类-这里不多介绍
			conn = JdbcUtils.getConnection();
			ps = conn.prepareStatement(sql);
			rs = ps.executeQuery();
			//获取sql语句执行结果集的列名
			String[] colNames = getColNames(rs);
			Object obj=null;
			//获取clazz的所有方法名
			Method[] ms = clazz.getMethods();
			while (rs.next()) {
				obj = clazz.newInstance();//要求类必须有参数为空的构造方法,类似Hibernate
				for (int i = 0; i < colNames.length; i++) {
				//用set+"字段名"来匹配,实体类中字段的set方法
					String colName = colNames[i];
					String methodName = "set" + colName;
					//OR映射
					for (Method m : ms) {
						if (methodName.equals(m.getName())) {
							m.invoke(obj, rs.getObject(colName));
							break;
						}
					}
				}
			}
			return obj;
		} finally {
			JdbcUtils.free(rs, ps, conn);
		}
	}
}

  上面的getObject(String sql, Class clazz)方法为映射一条数据,如果映射多条数据可改方法为:

	static List<Object> getObjects(String sql, Class clazz)
			throws SQLException, Exception, IllegalAccessException,
			InvocationTargetException {
		Connection conn = null;
		PreparedStatement ps = null;
		ResultSet rs = null;
		try {
			conn = JdbcUtils.getConnection();
			ps = conn.prepareStatement(sql);
			rs = ps.executeQuery();
			String[] colNames = getColNames(rs);

			List<Object> objects = new ArrayList<Object>();
			Method[] ms = clazz.getMethods();
			while (rs.next()) {
				Object object = clazz.newInstance();
				for (int i = 0; i < colNames.length; i++) {
					String colName = colNames[i];
					String methodName = "set" + colName;
					for (Method m : ms) {
						if (methodName.equals(m.getName())) {
							m.invoke(object, rs.getObject(colName));
							break;
						}
					}
					objects.add(object);
				}
			}
			return objects;
		} finally {
			JdbcUtils.free(rs, ps, conn);
		}
	}

总结

  上面的映射方式是用构造字符串方式,set+”字段名”映射类的属性,Hibernate的映射当然要复杂的多,通过配置文件来配置。但是实现原理差不多,Java映射为Java灵活性做了很好的支持。

Java反射入门,布布扣,bubuko.com

时间: 2024-10-05 17:45:47

Java反射入门的相关文章

Java反射机制大神必学系列之 ,高级与低级的差别在哪里?

Java反射机制大神必学系列之 ,高级与低级的差别在哪里?java学习爱好者 2019-05-20 19:08前言今天介绍下Java的反射机制,以前我们获取一个类的实例都是使用new一个实例出来.那样太low了,今天跟我一起来学习学习一种更加高大上的方式来实现. 正文Java反射机制定义 Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制.

Java反射-初步入门

Java反射-初步入门 学反射先了解什么是反射. 百度百科:JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 上面提到了类和对象,先了解什么是类和对象. java中类: 1.抽象描述 类:类是客观存在的.抽象的.概念东西. 对象:对象是具体的,指一个具体的东西. 打比方:饮料是一个类,可乐.雪碧就是对象. 总结一句话:类是对象的模版,对象

java反射快速入门(一)

本文会从以下几个方面讲起 ① 反射的简单解释 ② java反射的API接口 及 demo ③ 反射的优缺点.应用场景 一.什么是反射? java反射:在程序运行中动态获取类的信息,及动态调用对象的方法,这就是java反射 二.java反射的API接口 常用API接口规律 getXX() : 获取类本身 及父类的public属性.方法等 getDeclaredXX() :  获取类本身的所有私有.保护属性.方法等 getDeclaredXX(String name) : 获取类本身的指定name的

Java Annotation入门

Java Annotation入门作者:cleverpig 版权声明:本文可以自由转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明作者:cleverpig(作者的Blog:http://blog.matrix.org.cn/page/cleverpig)原 文:[http://www.matrix.org.cn/resource/article/44/44048_Java+Annotation.html]http://www.matrix.org.cn/resource/arti

Java新手入门的30个基本概念

Java新手入门的30个基本概念 在我们学习Java的过程中,掌握其中的基本概念对我们的学习无论是J2SE,J2EE,J2ME都是很重要的,J2SE是Java的基础,所以有必要对其中的基本概念做以归纳,以便大家在以后的学习过程中更好的理解java的精髓,在此我总结了30条基本的概念. Java概述: 目前Java主要应用于中间件的开发(middleware)---处理客户机于服务器之间的通信技术,早期的实践证明,Java不适合pc应用程序的开发,其发展逐渐变成在开发手持设备,互联网信息站,及车载

Java反射学习总结终(使用反射和注解模拟JUnit单元测试框架)

本文是Java反射学习总结系列的最后一篇了,这里贴出之前文章的链接,有兴趣的可以打开看看. http://blog.csdn.net/a396901990/article/category/2302221 本文介绍了如何利用反射和注解去简单的模拟JUnit4单元测试框架,之所以选择JUnit4是因为4.0以后最大的改进就是使用了注解.需要注意的是这里并不是完全的模拟,只是简单实现了一下Runner类和JUnit注解相关的工作流程.所以本文的主要目的是介绍反射和注解的使用.废话不多说,直接进入正文

《JAVA 从入门到精通》 - 正式走向JAVA项目开发的路

以前很多时候会开玩笑,说什么,三天学会PHP,七天精通Nodejs,xx天学会xx ... 一般来说,这样子说的多半都带有一点讽刺的意味,我也基本上从不相信什么快速入门.我以前在学校的时候自觉过很多门语言,但基本都只是了解了一个大概,入门肯定也算不上了.顶多也就能吹吹牛,说几个大的概念而已. 公司最近转型,决定抛弃PHP了,我们的出路是:要么H5,要么JAVA,要么走人.纠结了一段时间后,决定还是转JAVA了. 当一个人在自己熟悉的领域的时候,好像说什么都很有自信,都觉得自己是对的.那时候我们的

使用JAVA反射的利与弊

在Java的20周年的纪念日的日子里,让我们来重新温习下Java里面的高级知识,Java肯定希望大家了解她,要不然你跟她天天相濡以沫了这么长时间,让她知道你竟然不了解她,不在乎她,那么她该有多伤心呢,所以我们不应该做一个负心汉,更不应该做一个忘恩负义的人,她教会了你生存的技能,所以我们也应该将她发扬光大! Java的核心技能有如下几项:  (1)JVM的调优  (2)类加载器  (3)反射  (4)动态编译  (5)动态代理  (6)注解  (7)多线程  (8)IO,NIO,Socket,Ch

Java Web入门学习路线图的规划

Java作为学习编程开发入门语言,可能对于许多新手来说可能有点摸不着北,做位一名有几年开发经验的老鸟,希望给一些新人分享经验,当然其他老鸟如果有什么意见可以指出,我也会努力纠正. 本人工作是有关Java Web 开发,所以我会以Java Web标准开发去做一个标准,当然Java 能做的事情很多,包括Android,Java Me等,后期只要我们努力可以学习更多,更深的我也说不了,我现在只谈谈怎么去入门,至于登堂入室,大家有了套路以后,都能够达到.我写这个初衷,是因为我本来是一名非计算机专业的学生