反射(Reflection)
- 加载类,并允许以编程的方式解剖类中的各种成分
反射学什么?
1.反射第一步:加载类,获取类的字节码:Class对象
- 获取Class对象的3种方法:
public class Test1Class {
public static void main(String[] args) throws ClassNotFoundException {
Class<Student> c1 = Student.class;
System.out.println(c1.getName()); //全类名
System.out.println(c1.getSimpleName()); //简明:Student
Class<?> c2 = Class.forName("thread.Student");
System.out.println(c1 == c2);
Student s = new Student();
Class c3 = s.getClass();
System.out.println(c3 == c2);
}
}
2.获取类的构造器:Constructor对象
- Class提供了从类中获取构造器的方法
public class Test2Constructor {
@Test
public void testGetConstructors(){
//1.反射第一步:必须先得到这个类的Class对象
Class<Cat> c = Cat.class;
//2.获取全部构造器
// Constructor<?>[] constructors = c.getConstructors();
Constructor<?>[] constructors = c.getDeclaredConstructors());
//3.遍历数组中的每个构造器对象
for (Constructor<?> constructor : constructors) {
System.out.println(constructor.getName() + "--->"
+ constructor.getParameterCount());
}
}
@Test
public void testGetConstructor() throws NoSuchMethodException {
//1.反射第一步:必须先得到这个类的Class对象
Class<Cat> c = Cat.class;
//2.获取某个构造器:无参构造器
// Constructor<Cat> constructor = c.getConstructor();
Constructor<Cat> constructor = c.getDeclaredConstructor();
System.out.println(constructor.getName() + "--->"
+ constructor.getParameterCount());
//3.获取有参数构造器
Constructor<Cat> constructor2 =
c.getDeclaredConstructor(String.class, int.class);
System.out.println(constructor.getName() + "--->"
+ constructor.getParameterCount());
}
}
- 获取类构造器的作用:初始化对象返回
//无参构造器
constructor1.setAccessible(true); //禁止检查访问权限
Cat cat = constructor1.newInstance();
System.out.println(cat);
//有参构造器
constructor2.setAccessible(true);
Cat cat2 = constructor2.newInstance("喜洋洋", 3);
System.out.println(cat2);
3.获取类的成员变量
public class Test3Field {
@Test
public void testGetFields() throws NoSuchFieldException, IllegalAccessException {
//1.反射第一步:必须是先得到类的Class对象
Class<Cat> c = Cat.class;
//2.获取类的全部成员变量
Field[] fields = c.getDeclaredFields();
//3.遍历这个成员变量数组
for (Field field : fields) {
System.out.println(field.getName() + "--->" + field.getType());
}
//4.定位某个成员变量
Field fName = c.getDeclaredField("name");
System.out.println(fName.getName() + "--->" + fName.getType());
Field fAge = c.getDeclaredField("age");
System.out.println(fAge.getName() + "--->" + fAge.getType());
//赋值
Cat cat = new Cat();
fName.setAccessible(true);
fName.set(cat,"加菲猫");
System.out.println(cat);
//取值
String name = (String) fName.get(cat);
System.out.println(name);
}
}
4.获取类的成员方法:Method对象
-
public class Test3Method { @Test public void testGetMethods() throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { Class<Cat> c = Cat.class; //2.获取全部成员方法 Method[] methods = c.getDeclaredMethods(); //3.遍历 for (Method method : methods) { System.out.println(method.getName() + "--->" + method.getParameterCount() + "-->" + method.getReturnType()); } //4.获取某个方法对象 Method run = c.getDeclaredMethod("run"); System.out.println(run.getName() + "--->" + run.getParameterCount() + "-->" + run.getReturnType()); Method eat = c.getDeclaredMethod("eat", String.class); System.out.println(eat.getName() + "--->" + eat.getParameterCount() + "-->" + eat.getReturnType()); Cat cat = new Cat(); run.setAccessible(true); Object rs = run.invoke(cat);//调用无参数的run方法,用cat对象触发调用的 System.out.println(rs); eat.setAccessible(true); String rs2 = (String) eat.invoke(cat, "鱼儿"); System.out.println(rs2); } }
反射的作用?
- 最重要的用途是:适合做Java的框架,基本上,主流的框架都会基于反射设计出一些通用的功能
使用反射做一个简易版的框架
需求:
- 对于任意一个对象,该框架都可以把对象的字段名和对应的值,保存到文件中去
public class ObjectFrame {
public static void saveObject(Object obj) throws IllegalAccessException, FileNotFoundException {
PrintStream ps = new PrintStream(new FileOutputStream("D:\\java\\src\\date.txt", true));
//obj是任意对象,到底有多少个字段要保存
Class<?> c = obj.getClass();
String cName = c.getSimpleName();
ps.println("-----------" + cName + "-------------");
//从这个类中提取它的全部成员变量
Field[] fields = c.getDeclaredFields();
//遍历
for (Field field : fields) {
//拿到变量名字
String name = field.getName();
//拿到这个成员变量在对象中的数据
field.setAccessible(true);
String value = field.get(obj) + "";
ps.println(name + "=" + value);
}
ps.close();
}
}
public class Test5Frame {
@Test
public void save() throws FileNotFoundException, IllegalAccessException {
Student s1 = new Student("wyf",35,'男',185,"篮球");
Teacher t1 = new Teacher("xxx",4000);
ObjectFrame.saveObject(s1);
ObjectFrame.saveObject(t1);
}
}