反射是为学习框架的底层源码做准备。
定义:反射就是加载类,并允许已编程的方式解剖类中的各种成分(成员变量、方法、构造器等)。
1.获取Class的三种方式
首先要创建一个Student类
public class test {
public static void main(String[] args) throws Exception {
Class c1 = Student.class;
System.out.println(c1.getName()); // 全类名
System.out.println(c1.getSimpleName()); // 简名: Student
Class c2 = Class.forName("com.d2_reflect.Student");
System.out.println(c1 == c2);
Student s = new Student();
Class c3 = s.getClass();
System.out.println(c3 == c2);
}
}
2.获取类的构造器
下面代码可以拿到cat类的构造器
public class test {
@Test
public void testGetConstructors() {
// 1. 反射第一步,必须先得到这个类的Class对象
Class c = Cat.class;
// 2. 获取类的全部构造器
Constructor[] constructors = c.getDeclaredConstructors();
// 3. 遍历数组中的每个构造器对象
for (Constructor constructor : constructors) {
System.out.println(constructor.getName() + " ---> " + constructor.getParameterCount());
}
}
@Test
public void testGetConstructor() throws Exception {
// 1. 反射第一步,必须先得到这个类的Class对象
Class c = Cat.class;
// 2. 获取某个构造器,无参数构造器
Constructor constructor = c.getDeclaredConstructor();
System.out.println(constructor.getName() + " ---> " + constructor.getParameterCount());
// 3. 获取有参数构造器
Constructor constructor2 = c.getDeclaredConstructor(String.class, int.class);//后边加上参数类型
System.out.println(constructor2.getName() + " ---> " + constructor2.getParameterCount());
}
}
public class test {
@Test
public void testGetConstructor() throws Exception {
// 1. 反射第一步,必须先得到这个类的Class对象
Class c = Cat.class;
// 2. 获取类的某个构造器,无参数构造器
Constructor constructor1 = c.getDeclaredConstructor();
System.out.println(constructor1.getName() + " ---> " + constructor1.getParameterCount());
constructor1.setAccessible(true); // 取消检查访问权限,暴力访问
Cat cat = (Cat) constructor1.newInstance();
System.out.println(cat);
// 3. 获取有参数构造器
Constructor constructor2 = c.getDeclaredConstructor(String.class, int.class);
System.out.println(constructor2.getName() + " ---> " + constructor2.getParameterCount());
constructor2.setAccessible(true); // 取消检查访问权限
Cat cat2 = (Cat) constructor2.newInstance("叮当猫", 3);
System.out.println(cat2);
}
}
3.获取类的成员变量
public class test {
@Test
public void testGetFields() throws Exception {
// 1. 反射第一步,必须先得到类的Class对象
Class 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.获取类的成员方法
public class test {
@Test
public void testGetFields() throws Exception {
// 1. 反射第一步,必须先得到类的Class对象
// 1. 反射第一步,先得到Class对象。
Class 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"); // 拿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, "鱼儿"); // 调用有参数的eat方法
System.out.println(rs2);
反射的作用及应用场景
基本作用:可以得到一个类的全部成分然后操作。
可以破快封装性
最重要:适合做Java的框架,基本数,主流的框架会基于反射设计出一些通用的功能。
public class test {
@Test
public void save() throws Exception {
Student s1 = new Student("马吴彦祖", 45, '男', 185.3, "篮球,冰球,游泳");
Teacher t1 = new Teacher("珊姐", 999.9);
// 把任意对象的字段名和其对应的值等信息,保存到文件中去。
ObjectFrame.saveObject(s1);
ObjectFrame.saveObject(t1);
}
}
框架
public class ObjectFrame {
// 目标: 保存任意对象的字段和其数据到文件中去
public static void saveObject(Object obj) throws Exception {
PrintStream ps = new PrintStream(new FileOutputStream("junit-output.txt", true));
// obj是任意对象,剥夺有多少个字段需要保存。
Class c = obj.getClass();
String cName = c.getSimpleName();
ps.println("=============== " + cName + " ===============");
// 2. 从这个类中提取出的全部成员变量
Field[] fields = c.getDeclaredFields();
// 3. 遍历成员变量
for (Field field : fields) {
// 4. 获取变量的名字
String name = field.getName();
// 5. 突破javabean规范进行直接访问
field.setAccessible(true); // 取消检查访问控制
String value = field.get(obj) + "";
ps.println(name + " = " + value);
}
ps.close();
}
}
两个学生和老师的构造器自己写一下。
标签:反射,System,Class,public,println,class,out From: https://blog.51cto.com/u_16382144/11963157