黑马程序员_Java基础加强_反射

本文介绍了Java中的反射机制,包括Class类的重要方法,如获取构造器、字段和方法,以及Constructor、Method和Field类的使用。通过反射,开发者可以在运行时动态创建对象并调用方法,增强了代码的灵活性。
摘要由CSDN通过智能技术生成

---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

一、概述

在Java中非常重要的就是反射机制,在正常情况下如果有一个类,则肯定能够通过类创建对象;如果想要使用类的完整名称来创建对象的话,就需要用到Java的反射机制,Java反射机制的基石是Class类Class类表示所有类的本身【也就是一个类在内存中的字节码】,通过Class可以获取到一个类的完整结构,包括此类中的方法、属性、包名、类名等等...

Class类的常用方法:(注意Class类没有公开的构造方法【构造方法是私有的】)

静态方法:Class.forName("类的完整名称");通过此方法能够得到Class类的对象


Class类获取对象的3个基本方式:

1、对象.getClass()

2、类名.class

3、Class.forName("")


一般方法:

getConstructors()得到一个类的所有构造方法

getConstructor(Class...)得到指定的构造方法

getDeclaredFields()得到类中全部属性

getFields()得到类中继承来的或者本类中的public类型的字段

getMethods()得到类中的全部方法

getMethod(String Class)根据方法名称与参数类型获取类中的方法

getInterfaces()得到类所有实现的接口

getName()得到类的名称

getPackage()得到类的包名

getSupperClass()得到类的父类

newInstance()调用类的无参构造方法,实例化该类

getComponentType()返回表示数组类型的Class

isArray()是否数组

下面对各个方法做一个简要的介绍

package com.itheima.hightech;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectDemo1 {

	public static void main(String[] args) throws Exception{
		//1.得到Student类的所有构造方法
		Class<Student> clazz = Student.class;
		Constructor<?>[] cs = clazz.getConstructors();
		for (Constructor<?> constructor : cs) {
			System.out.println("这是全部构造方法的其中一个:"+constructor);
		}
		//2.得到Student类的有参数的构造方法
		Constructor<?> c = clazz.getConstructor(int.class,String.class);
		System.out.println("这是得到的指定的构造方法:"+c);
		
		//3.得到Student类中的全部字段
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			System.out.println("类中的字段:"+field);
		}
		//这个应该是得到类中继承来的或者本类中的public类型的字段
		Field[] fields2 = clazz.getFields();
		for (Field field : fields2) {
			System.out.println("继承来的或者本类中的public类型字段:"+field);
		}
		
		
		//得到Student类中的全部方法,包括父类中的非私有的方法
		Method[] ms = clazz.getMethods();
		for (Method method : ms) {
			System.out.println("全部方法:"+method);
		}
		
		//得到Student类中的指定的方法sayAge()
		Method m = clazz.getMethod("sayAge");
		System.out.println("指定方法:"+m);
		
		//得到Student类实现的全部接口,不包括父类实现的接口
		Class<?>[] cls = clazz.getInterfaces();
		for (Class<?> cl : cls) {
			System.out.println("全部接口:"+cl);
		}
		//得到类的名称
		System.out.println(clazz.getName());
		//得到包的名称
		System.out.println(clazz.getPackage());
		//得到类的父类
		System.out.println(clazz.getSuperclass());
		//得到类的继承关系列表
		Class<?> supperClazz = clazz.getSuperclass();
		while(true){
			System.out.println("继承关系:"+supperClazz);
			supperClazz = supperClazz.getSuperclass();
			if(supperClazz == Object.class){
				System.out.println("继承关系:class java.lang.Object");
				break;
			}
		}
		int[] arr = {1,2};
		//判断是否数组
		System.out.println(arr.getClass().isArray());
		//得到数组类型的名称
		System.out.println(arr.getClass());
		//如果是数组,得到数组中元素的类型
		if(arr.getClass().isArray()){
			System.out.println("数组中元素的类型:"+arr.getClass().getComponentType());
		}
	}
}
class Person implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 591343829826564664L;
	public int id;
	protected String summary;
}
class Student extends Person implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 6857111643274069272L;
	protected String desc;
	public Student(){}
	public Student(int age,String name){
		this.age = age;
		this.name = name;
	}
	private int age;
	private String name;
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public void sayAge(){
		System.out.println("我的年龄是:"+age);
	}
	
}

二、反射中的几个重要的类

1、Constructor 表示类中构造方法的类

2、Method 表示类中方法的类

3、Field 表示类中字段的类


分类介绍:

A、Constructor类

Constructor的获取可以有如下4中方式获得:

clazz.getConstructors() 获取所有的public修饰的构造方法

clazz.getConstructor(Class...c)根据参数类型获取指定的public修饰的构造方法

clazz.getDeclaredConstructors()获取类中所有的构造方法,包括private修饰的

clazz.getDeclaredConstructor(Class...)根据参数类型获取指定的构造方法,包括private修饰的


Constructor中常用的方法

package com.itheima.hightech;

import java.lang.annotation.Annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Constructor;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

/**
 * 构造方法使用简单实例
 */
public class ConstructorDemo {

	public static void main(String[] args) throws Exception{
		List<String> list = new MyArrayList();
		Type type = list.getClass().getGenericSuperclass();

		//得到构造方法,包含私有的构造方法
		Constructor<?> c1 = list.getClass().getDeclaredConstructor(String.class);
		//暴力反射,使构造方法变为可对外访问的
		c1.setAccessible(true);
		//根据构造方法获取该类的实例
		MyArrayList instance = (MyArrayList) c1.newInstance("dsfds");
		//访问变量的属性值
		System.out.println(instance.str);
		//访问变量的方法
		instance.add("11");
		
		//得到MyArrayList的泛型实际参数类型
		if(type instanceof ParameterizedType){
			ParameterizedType ptype = (ParameterizedType)type;
			Type[] as = ptype.getActualTypeArguments();
			for (Type a : as) {
				System.out.println(a instanceof Class<?>);
				System.out.println(a);
			}
		}
		//获取类上的所有Annotation
		Annotation[] anns = list.getClass().getAnnotations();
		for (Annotation ann : anns) {
			System.out.println(ann);
		}
		//得到某一个annotation
		MyAnnotation ann = list.getClass().getAnnotation(MyAnnotation.class);
		System.out.println(ann);
		
		//获取注解中的值
		System.out.println(ann.value());
	}
}

@SuppressWarnings("serial")
@MyAnnotation("tableName")
class MyArrayList extends ArrayList<String>{
	public String str;
	@SuppressWarnings("unused")
	private MyArrayList(String str){
		this.str = str;
	}
	public MyArrayList(){}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface MyAnnotation{
	public String value() default "";
}

Method类的使用

package com.itheima.hightech;

import java.lang.reflect.Method;

public class MethodDemo {

	public static void main(String[] args) throws Exception{
		String str = MethodDemo.getObject("aaa");
		System.out.println(str);
		//在这里本想使用String.class的,但是好像泛型T 只能用Object代表
		Method m = MethodDemo.class.getMethod("getObject", Object[].class);
		//通过Method调用方法
		//在这里可以使用两种方式:new Object[]{new Object[]{"ss","2dd"}}
		//原因是:可变参数的方法调用时,如果是数组,会自动拆解的
		System.out.println(m.invoke(null, (Object)new Object[]{"ss","dd"}));
		
		
		//得到参数类型
		Class<?>[] clses = m.getParameterTypes();
		for (Class<?> class1 : clses) {
			System.out.println(class1);
		}
		
		//得到所有的方法
		Method[] methods = MethodDemo.class.getMethods();
		for (Method method : methods) {
			System.out.println(method);
		}
		
		//得到方法的返回值
		Class<?> cls = m.getReturnType();
		System.out.println(cls);
	}
	
	public static <T> T getObject(T... ts){
		return ts[0];
	}
}
上面例子中需要重点注意的是:

//在这里本想使用String.class的,但是好像泛型T 只能用Object代表
Method m = MethodDemo.class.getMethod("getObject", Object[].class);
//通过Method调用方法
//在这里可以使用两种方式:new Object[]{new Object[]{"ss","2dd"}}
//原因是:可变参数的方法调用时,如果是数组,会自动拆解的
System.out.println(m.invoke(null, (Object)new Object[]{"ss","dd"}));



Field类的使用

这是我在工作中使用Field类写的一个工具类

package com.longtime.app.ixin.mgr.utils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;

/**
 * 
 * @author 陈克锋
 *
 */
public class DBUtils {
	private static final Logger logger = LoggerFactory.getLogger(DBUtils.class);

	/**
	 * 例如:一个JavaBean Person [person为传递进来的Person对象] 字段有 private String id,private String name <br>
	 * 		对应表为 person 字段为 id,name
	 *      忽略字段为 name
	 *      生成的sql 语句为 insert into 'tableName' (id) value (?)
	 *      生成的insertVals 为List 类型 [person.getId()]
	 *      
	 * @param entity service传递进来需要保存的对象
	 * @param tableName  表名
	 * @param ignoreColumns 那些字段不需要插入
	 * @return sql 生成的sql语句
	 * 		   insertVals 生成的体替代?的字段值
	 * 		   timeConsuming 耗时长
	 */
	public static <T> Map<String,Object> getInsertSql(T entity,String tableName,List<String> ignoreColumns){
		Map<String,Object> map = new HashMap<String, Object>();
		List<Object> insertVals = new ArrayList<Object>();
		long statTime = System.currentTimeMillis();
		try{
			StringBuffer sqlBuffer = new StringBuffer("insert into ");
			sqlBuffer.append(tableName).append(" (");
			StringBuffer valueBuffer = new StringBuffer(" value (");
			
			Field[] fields = entity.getClass().getDeclaredFields();
			PropertyDescriptor descriptor = null;
			for (Field field : fields) {
				if(ignoreColumns!=null && ignoreColumns.contains(field.getName())){
					continue;
				}
				descriptor = new PropertyDescriptor(field.getName(), entity.getClass());
				sqlBuffer.append(field.getName()).append(',');
				valueBuffer.append('?').append(',');
				insertVals.add(descriptor.getReadMethod().invoke(entity));
			}
			sqlBuffer.replace(sqlBuffer.length()-1, sqlBuffer.length(), ")").append((valueBuffer.replace(valueBuffer.length()-1, valueBuffer.length(), ")")));
			map.put("sql", sqlBuffer.toString());
			map.put("insertVals", insertVals);
			map.put("timeConsuming", System.currentTimeMillis()-statTime);
		}catch(Exception e){
			logger.debug("get insert sql failure.");
		}
		return map;
	}
	
	/**
	 * 
	 * @param entity
	 * @param tableName
	 * @param ignoreColumns
	 * @param whereColumn 条件字段
	 * @return sql ,updateVals ,timeConsuming
	 */
	public static <T> Map<String, Object> getUpdateSql(T entity,
			String tableName, List<String> ignoreColumns,String whereColumn) {
		Map<String,Object> map = new HashMap<String, Object>();
		List<Object> updateVals = new ArrayList<Object>();
		long statTime = System.currentTimeMillis();
		try{
			StringBuffer sqlBuffer = new StringBuffer("update ");
			sqlBuffer.append(tableName).append(" set");
			
			Field[] fields = entity.getClass().getDeclaredFields();
			PropertyDescriptor descriptor = null;
			for (Field field : fields) {
				if(ignoreColumns!=null && ignoreColumns.contains(field.getName())){
					continue;
				}
				descriptor = new PropertyDescriptor(field.getName(), entity.getClass());
				sqlBuffer.append(" ").append(field.getName()).append("=").append("?,");
				updateVals.add(descriptor.getReadMethod().invoke(entity));
			}
			map.put("sql", sqlBuffer.replace(sqlBuffer.length()-1, sqlBuffer.length(), " where ").append(whereColumn).append("=?").toString());
			descriptor = new PropertyDescriptor(whereColumn, entity.getClass());
			updateVals.add(descriptor.getReadMethod().invoke(entity));
			map.put("updateVals", updateVals);
			map.put("timeConsuming", System.currentTimeMillis()-statTime);
		}catch(Exception e){
			e.printStackTrace();
			logger.debug("get insert sql failure.");
		}
		return map;
	}
	
	/**
	 * 得到记录总数
	 * @param sql
	 * @return
	 */
	public static int getCount(String sql,JdbcTemplate jdbcTemplate,Object...reqVal){
		List<Integer> list = jdbcTemplate.query(sql, reqVal ,new RowMapper<Integer>(){
			@Override
			public Integer mapRow(ResultSet rs, int rowNum) throws SQLException {
				
				return rs.getInt(1);
			}
		});
		if(list!=null && list.size()>0){
			return list.get(0);
		}
		return 0;
	}
	/**
	 * 
	 * @param obj
	 * @param sql
	 * @param jdbcTemplate
	 * @param params
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> List<T> queryList(final T obj,String sql,JdbcTemplate jdbcTemplate,Object...params){
		try {
			return jdbcTemplate.query(sql, params,new RowMapper<T>(){
				@Override
				public T mapRow(ResultSet rs, int rowNum) throws SQLException {
					try{
						Constructor<T> c = (Constructor<T>)obj.getClass().getConstructor();
						T returnObj = c.newInstance();
						Field[] fields = obj.getClass().getDeclaredFields();
						PropertyDescriptor descriptor = null;
						for (Field field : fields) {
							descriptor = new PropertyDescriptor(field.getName(), returnObj.getClass());
							descriptor.getWriteMethod().invoke(returnObj, rs.getObject(field.getName()));
						}
						return returnObj;
					}catch(Exception e){
						throw new RuntimeException("error.");
					}
				}
			});
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
	
	public static void main(String[] args)throws Exception {
		
		queryList(new String(), null, null);
		
	}

}
本来想使用BeanUtils工具类进行field的取值操作与赋值操作,但是测试的时候发现效率很低,就以insert语句的组成来说,就耗费了700ms,使用PropertyDescriptor类进行操作时,效率有很大的提升,耗时大概在2ms左右。

在下篇准备写一个通用DAO与通用Service   GenericDao,GenericService


---------------------- ASP.Net+Android+IOS开发.Net培训、期待与您交流! ----------------------

详细请查看:http://edu.csdn.net


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值