Java反射机制

Java反射机制

定义:在运行状态中,对于任何一个类,我们都能够知道这个类有哪些方法和属性。对于任何一个对象,我们都能够对它的方法和属性(包括私有的方法和属性)进行调用。这种动态获取对象信息和调用对象方法的功能称之为反射机制。

反射其实是获取类的字节码文件,也就是.class文件,那么就可以通过Class这个对象进行获取。

反射的四种方式
public static void main(String[] args) {
	//第一种
	ClassName c = new ClassName();//创建一个对象
	Class<?> class1 = c.getClass();//获取该对象的Class类
	System.out.println(class1.getName());//输出类名称
	//第二种
	Class<?> class2 = ClassName.class;
	System.out.println(class2.getName());//输出类名称
	//第三种
	try {
		Class<?> class3 = SetUtil.class.getClassLoader().loadClass("com.zxx.util.ClassName");
		System.out.println(class3.getName());//输出类名称
	} catch (ClassNotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
	//第四种
	try {
		Class<?> class4 = Class.forName("com.zxx.util.ClassName");//根据类的路径名称获取
		System.out.println(class4.getName());//输出类名称
	} catch (ClassNotFoundException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	}
}
Class类常用方法:
  1. getName():返回String形式的该类的名称。
  2. newInstance():根据某个Class对象产生其对应类的实例,它调用的是此类的默认构造方法(没有默认无参构造器会报错)。
  3. getClassLoader():返回该Class对象对应的类的类加载器。
  4. getSuperClass():返回某子类所对应的直接父类所对应的Class对象。
  5. isArray():判定此Class对象所对应的是否是一个数组对象。
  6. getComponentType():如果当前类表示一个数组,则返回表示该数组组件的Class对象,否则返回 null。
  7. getConstructor(Class[]):返回当前Class对象表示的类的指定的公有构造子对象。
  8. getConstructors():返回当前Class对象表示的类的所有公有构造子对象数组。
  9. getDeclaredConstructor(Class[]):返回当前Class对象表示的类的指定已说明的一个构造子对象。
  10. getDeclaredConstructors():返回当前Class对象表示的类的所有已说明的构造子对象数组。
  11. getDeclaredField(String):返回当前Class对象表示的类或接口的指定已说明的一个域对象。
  12. getDeclaredFields():返回当前Class对象表示的类或接口的所有已说明的域对象数组。
  13. getDeclaredMethod(String, Class[]):返回当前Class对象表示的类或接口的指定已说明的一个方法对象。
  14. getDeclaredMethods():返回Class对象表示的类或接口的所有已说明的方法数组。
  15. getField(String):返回当前Class对象表示的类或接口的指定的公有成员域对象。
  16. getFields():返回当前Class对象表示的类或接口的所有可访问的公有域对象数组。
  17. getInterfaces():返回当前对象表示的类或接口实现的接口。
  18. getMethod(String, Class[]):返回当前Class对象表示的类或接口的指定的公有成员方法对象。
  19. getMethods():返回当前Class对象表示的类或接口的所有公有成员方法对象数组,包括已声明的和从父类继承的方法。
  20. isInstance(Object):此方法是Java语言instanceof操作的动态等价方法。
  21. isInterface():判定指定的Class对象是否表示一个接口类型。
  22. isPrimitive():判定指定的Class对象是否表示一个Java的基类型。
  23. newInstance():创建类的新实例。
反射在实际开发中的应用

例如查询数据库时,返回的是一个二维的结果集,需要用到ResultSet来遍历结果集,获取每一行的数据。

public List<Account> Select() {
	List<Account> Accounts = new ArrayList<Account>(); 
	Account Account = null;
	try {
		Connection con = Util.getConnection();//连接数据库的封装方法
		PreparedStatement ps = con.prepareStatement("select * from account");
		ResultSet rs = ps.executeQuery();
		while (rs.next()) {
			Account = new Account();
			Account.setAccountid(rs.getInt(1));
			Account.setAccount(rs.getString(2));
			Account.setBank(rs.getString(3));
			Account.setBankaccount(rs.getString(4));
			Account.setAccountearlybalance(rs.getDouble(5));
			Account.setAccountnote(rs.getString(6));
			Account.setAccountstate(rs.getBoolean(7));
			Account.setAccountbalance(rs.getDouble(8));
			Accounts.add(Account);
		}
	} catch (SQLException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
	} finally{
		Util.close(con, ps, rs);//关闭的封装方法
	}
	return Accounts;
}

如上所示的遍历中是将结果一个一个放入Po类中,比较麻烦,这时就可以使用反射封装方法,方法如下所示(注:在方法中我只对一些常用的数据类型进行了判断),在遍历中调用方法即可。

public static void sqlSetClass(Object className,ResultSet rs){
	try{
		Class<?> clas = className.getClass();
		Field[] filed=clas.getDeclaredFields();
		for (int i = 0; i < filed.length; i++) {
			Field field=clas.getDeclaredField(filed[i].getName());
			field.setAccessible(true);
			String Type=filed[i].getType().getSimpleName();
			if (Type.equals("boolean")||Type.equals("Boolean")) {
				try {
					field.set(className,resultSet.getBoolean(filed[i].getName()));
				} catch (Exception e) {}
			}else if(Type.equals("byte")||Type.equals("Byte")) {
				try {
					field.set(className,resultSet.getByte(filed[i].getName()));
				} catch (Exception e) {
					field.set(className,0);
				}
			}else if(Type.equals("short")||Type.equals("Short")) {
				try {
					field.set(className,resultSet.getShort(filed[i].getName()));
				} catch (Exception e) {
					field.set(className,0);
				}
			}else if(Type.equals("int")||Type.equals("Integer")) {
				try {
					field.set(className,resultSet.getInt(filed[i].getName()));
				} catch (Exception e) {
					field.set(className,0);
				}
			}else if (Type.equals("long")||Type.equals("Long")) {
				try {
					field.set(className,resultSet.getLong(filed[i].getName()));
				} catch (Exception e) {
					field.set(className,0);
				}
			}else if(Type.equals("char")||Type.equals("Character")) {
				try {
					field.set(className,resultSet.getCharacterStream(filed[i].getName()));
				} catch (Exception e) {}
			}else if(Type.equals("float")||Type.equals("Float")) {
				try {
					field.set(className,resultSet.getFloat(filed[i].getName()));
				} catch (Exception e) {
					field.set(className,0.0);
				}
			}else if(Type.equals("double")||Type.equals("Double")) {
				try {
					field.set(className,resultSet.getDouble(filed[i].getName()));
				} catch (Exception e) {
					field.set(className,0.0);
				}
			}else if(Type.equals("String")){
				try {
					field.set(className,resultSet.getString(filed[i].getName()).trim());
				} catch (Exception e) {}
			}else if(Type.equals("InputStream")) {
				try {
					field.set(className,resultSet.getBinaryStream(filed[i].getName()));
				} catch (Exception e) {}
			}else {
				try {
					field.set(className,resultSet.getObject(filed[i].getName()));
				} catch (Exception e) {}
			}
		}
	} catch (IllegalArgumentException e) {
		e.printStackTrace();
	} catch (NoSuchFieldException e) {
		e.printStackTrace();
	} catch (SecurityException e) {
		e.printStackTrace();
	} catch (IllegalAccessException e) {
		e.printStackTrace();
	}
}
上一篇:VMX,SVM编程指北——勘误


下一篇:命令行启动虚拟机和hadoop集群