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类常用方法:
- getName():返回String形式的该类的名称。
- newInstance():根据某个Class对象产生其对应类的实例,它调用的是此类的默认构造方法(没有默认无参构造器会报错)。
- getClassLoader():返回该Class对象对应的类的类加载器。
- getSuperClass():返回某子类所对应的直接父类所对应的Class对象。
- isArray():判定此Class对象所对应的是否是一个数组对象。
- getComponentType():如果当前类表示一个数组,则返回表示该数组组件的Class对象,否则返回 null。
- getConstructor(Class[]):返回当前Class对象表示的类的指定的公有构造子对象。
- getConstructors():返回当前Class对象表示的类的所有公有构造子对象数组。
- getDeclaredConstructor(Class[]):返回当前Class对象表示的类的指定已说明的一个构造子对象。
- getDeclaredConstructors():返回当前Class对象表示的类的所有已说明的构造子对象数组。
- getDeclaredField(String):返回当前Class对象表示的类或接口的指定已说明的一个域对象。
- getDeclaredFields():返回当前Class对象表示的类或接口的所有已说明的域对象数组。
- getDeclaredMethod(String, Class[]):返回当前Class对象表示的类或接口的指定已说明的一个方法对象。
- getDeclaredMethods():返回Class对象表示的类或接口的所有已说明的方法数组。
- getField(String):返回当前Class对象表示的类或接口的指定的公有成员域对象。
- getFields():返回当前Class对象表示的类或接口的所有可访问的公有域对象数组。
- getInterfaces():返回当前对象表示的类或接口实现的接口。
- getMethod(String, Class[]):返回当前Class对象表示的类或接口的指定的公有成员方法对象。
- getMethods():返回当前Class对象表示的类或接口的所有公有成员方法对象数组,包括已声明的和从父类继承的方法。
- isInstance(Object):此方法是Java语言instanceof操作的动态等价方法。
- isInterface():判定指定的Class对象是否表示一个接口类型。
- isPrimitive():判定指定的Class对象是否表示一个Java的基类型。
- 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();
}
}