**理解反射机制:**
1. JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
2. Java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。
i. 获得类的Field实例
ii. 获得类的Constructor实例
iii. 获得类的Method实例
iv. 通过“字符串类名”动态创建类的实例,这种就是通过反射创建实例.
下面就通过最近学习的一个例子来模拟反射机制的运作方式,以后再框架里面的实例化都是通过反射实现的,框架为了方便管理,就需要自己通过反射来创建实例,而我们自己new出来的对象,对于框架来说,就不是自己生的”儿子”,不好管理。
例:
编写一个程序从控制台输入一个学生类的类名,如:com.bluebridge.reflect.Student,通过反射创建出学生对象;同时从控制台输入姓名,年龄,性别等信息。
a) 使用反射技术通过Field对象给属性赋值。
b) 使用反射技术调用“setter”的Method的invoke(student对象,值)方法来给学生对象的属性赋值
这里都是写在一个类里面的,包括main函数:
/**
* /* 能过类来获得该Class实例所表示的类的结构:
* 1. 属性,即字段 java.lang.reflect.Field
* 2. 构造函数java.lang.reflect.Constructor
* 3. 方法:java.lang.reflect.Method
*
* 总结,通过反射创建对象可以有以下两种方式: 1. Class.newInstance()通过默认构造函数创建对象 2.
* 通过类的Constructor构造器来对象,只要传入参数以构造器定义的参数列表一致。
*
*
* @param args
*/
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
// 输入需要创建的完整类名
System.out.print("请输入完整的类名(包名+类名):");
// 输入类名
String className = input.next();
try {
// 动态加载类,将字符串定的类加载到JVM中去运行,即在JVM环境下可以找到这样一个类
Class cls = Class.forName(className);
// 通过默认构造函数创建对象
Object object = cls.newInstance();
Field[] fields = cls.getDeclaredFields();
for (Field field : fields) {
String fileName = field.getName();
Field fild2 = cls.getDeclaredField(fileName);//得到申明的属性
fild2.setAccessible(true);//修改属性的可访问性,可以从private变成可以直接访问的
setValue(object, fild2, input);//调用setValue方法
}
System.out.println(object);
System.out.println("=============下面是调用方法===================");
//只得本类声明的方法
Method[] methods = cls.getDeclaredMethods();
Method setnameMethod = cls.getDeclaredMethod("setName",String.class);
setnameMethod.setAccessible(true);// 改变类的访问属性
System.out.print("请输入姓名:");
String string = input.next();
//调用setName方法
setnameMethod.invoke(object, string);
Method setAgeMethod = cls.getDeclaredMethod("setAge", Integer.TYPE);
setAgeMethod.setAccessible(true);
System.out.print("请输入年龄:");
int i = input.nextInt();
//调用setName方法
setAgeMethod.invoke(object, i);
Method setGenderMethod = cls.getDeclaredMethod("setGender",
String.class);
setGenderMethod.setAccessible(true);
System.out.print("请输入性别:");
string = input.next();
setGenderMethod.invoke(object, string);
System.out.println(object);
} catch (ClassNotFoundException e) {
System.err.println(e.getMessage());
} catch (InstantiationException e) {
System.err.println(e.getMessage());
} catch (IllegalAccessException e) {
System.err.println(e.getMessage());
} catch (NoSuchFieldException e) {
System.err.println(e.getMessage());
} catch (SecurityException e) {
System.err.println(e.getMessage());
} catch (NoSuchMethodException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 判断文件的参数的类型
*
* @param object
* 对象,Student
* @param fild2
* @param input
* @throws IllegalArgumentException
* @throws IllegalAccessException
*/
public static void setValue(Object object, Field fild2, Scanner input)
throws IllegalArgumentException, IllegalAccessException {
Class fieldType = fild2.getType();
// int
if (fieldType == Integer.class || fieldType == Integer.TYPE) {
System.out.print("请输入" + fild2.getName() + ":");
int i = input.nextInt();
fild2.set(object, i);
// double
} else if (fieldType == Double.class || fieldType == Double.TYPE) {
System.out.print("请输入" + fild2.getName() + ":");
double dou = input.nextDouble();
fild2.set(object, dou);
// long
} else if (fieldType == Long.class || fieldType == Long.TYPE) {
System.out.print("请输入" + fild2.getName() + ":");
long log = input.nextLong();
fild2.set(object, log);
// string
} else if (fieldType == String.class) {
System.out.print("请输入" + fild2.getName() + ":");
String string = input.next();
fild2.set(object, string);
// char
} else if (fieldType == Character.TYPE || fieldType == Character.class) {
System.out.print("请输入" + fild2.getName() + ":");
char chrs = 0;
try {
chrs = (char) System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
fild2.set(object, chrs);
}
}