一.Person类
1.1实体
public class Person { private String name; private int age; public int num; public static String country = "cn";
public Person() {
}
public Person(String name, int age) {
this.name = name; this.age = age; System.out.println("2个参数的构造函数"); }
private Person(String name) { this.name = name; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public int getAge() { return age; }
public void setAge(int age) { this.age = age; }
public void eat() { System.out.println("吃东西"); }
public void eat(String food) { System.out.println("吃:" + food); }
public static void play(String game) { System.out.println("玩:" + game); }
private void movie(String name) { System.out.println("看:" + name); }
@Override public String toString() { return "Person [name=" + name + ", age=" + age + ", num=" + num + "]"; }
}
|
二.反射测试
2.1 获取Person 类的字节码对象. Class
/* * 获取Person 类的字节码对象. Class */ @Test public void testGetPersonClass() throws ClassNotFoundException { // 方式一: 类名.class Class clazz = Person.class;
// 方式二: 对象.getClass() Person p = new Person(); Class clazz1 = p.getClass();
// 方式三: Class 的静态方法forName 加载指定的类的... Class clazz2 = Class.forName("cn.itcast.gz.a_reflect.Person");
// 字节码文件只加载一次,所以是Class 对象在内存中是唯一的. System.out.println(clazz == clazz1); } |
2.2 获取Person 类的字节码信息,并分析
/** * 获取Person 类的字节码信息,并分析 * * @throws ClassNotFoundException * */ @Test public void testGetPersonInfo() throws ClassNotFoundException { Class clazz = Class.forName("cn.itcast.gz.a_reflect.Person"); // 获取类的类名 ->获取类的完整的名称... 全限定名称(包名+类名) String name = clazz.getName(); /**cn.itcast.gz.a_reflect.Person**/
// 获取类的简单名称只有类名. String simpleName = clazz.getSimpleName(); /**Person**/
// 获取类的修饰符 // public ->1 default 0 abstract 1024 int modifiers = clazz.getModifiers(); /**1**/
} |
2.3 获取类的成员变量
/** * 获取类的成员变量 * * @throwsClassNotFoundException * @throws NoSuchFieldException * @throws SecurityException * * 注意: 虽然反射可以获取类中的成员变量,还是面向对象的基本的原则静态成员变量: 随着的类的加载而加载. * 通过反射机制,给静态的变量赋值和取值时,不需要传递对象, 给类的成员取值和赋值. 非静态成员: * 创建对象,在对象的对内存中依赖于对象存在的. 通过反射机制,该非静态的成员变量时,需要指定一个对象. 给哪个对象的对象 * 赋值和取值吧... */ @Test public void testGetFields() throws Exception { Class clazz = Class.forName("cn.itcast.gz.a_reflect.Person");
Object p = clazz.newInstance(); /** Person [name=null, age=0, num=0] **/
// 获取类中的所有的公有的成员变量 Field[] fields = clazz.getFields(); for (Field field : fields) { System.out.println(field); } /** * public int cn.itcast.gz.a_reflect.Person.num ; * public static java.lang.String cn.itcast.gz.a_reflect.Person.country; */
// 获取类中所有的成员变量(包括私有的) Field[] declaredFields = clazz.getDeclaredFields(); for (Field field : declaredFields) { System.out.println(field.getName()); } /** name age num country **/
// 获取类中指定的成员变量... 指定成员变量的名称 Field f = clazz.getField("num"); /**public int cn.itcast.gz.a_reflect.Person.num**/
// 给成员变量赋值 f.set(p, 100); // 成员变量可以存储信息, 取出信息... System.out.println(f.get(p)); /**100**/ System.out.println(p); /**Person [name=null, age=0, num=100]**/
// 获取类中指定的成员变量 Field f1 = clazz.getField("country"); /**public static java.lang.String cn.itcast.gz.a_reflect.Person.country**/
// 获取成员变量的值. System.out.println(f1.get(null)); /**cn**/
f1.set(null, "us"); /**us**/
// 获取. 私有的成员变量 Field f2 = clazz.getDeclaredField("name"); /**private java.lang.String cn.itcast.gz.a_reflect.Person.name**/
// 暴力反射 (打开权限) f2.setAccessible(true); // 赋值,取值. 注意: name 是私有的成员变量... 无法直接赋值的 f2.set(p, "张三疯"); /** * 张三疯 * Person [name=张三疯, age=0, num=100] */ } |
2.4 获取类中的构造函数 Constructor 对象
/** * 获取类中的构造函数 Constructor 对象: 该对象提供了一个核心方法: newInstance(); 可以根据指定的构造函数,创建对象. * 反射用在以后的框架中... 配置文件. * * @throws Exception */ @Test public void testConstructor() throws Exception { Class clazz = Class.forName("cn.itcast.gz.a_reflect.Person");
// 获取所有的公有的构造函数... Constructor[] constructors = clazz.getConstructors();
// 获取类中所有的构造函数(包含私有的) Constructor[] declaredConstructors = clazz.getDeclaredConstructors(); for (Constructor constructor : declaredConstructors) { System.out.println(constructor); } /** * public cn.itcast.gz.a_reflect.Person() * public cn.itcast.gz.a_reflect.Person(java.lang.String,int) * private cn.itcast.gz.a_reflect.Person(java.lang.String) */
// 获取指定的构造函数... 一个类中存在多个构造函数, 是以重载的形式存在(函数名相同,参数列表不同). Constructor c1 = clazz.getConstructor(String.class, int.class); /**public cn.itcast.gz.a_reflect.Person(java.lang.String,int)**/
// 创建对象->获取的构造函数. 该构造函数需要2个参数. Person p = (Person) c1.newInstance("张无忌", 18); /**Person [name=张无忌, age=18, num=0]**/
// 获取无参数的构造函数. Constructor c2 = clazz.getConstructor(null); /**public cn.itcast.gz.a_reflect.Person()**/
// 根据获取的无参数构造创建对象. Person p1 = (Person) c2.newInstance(null); /**Person [name=null, age=0, num=0]**/
// 普通创建对象方式... 普通用法 Person person = new Person(); } |
2.4.1 私有构造函数用法
/** * 私有构造函数无法直接获取. 需要特殊的方法. 注意: 破坏了面向对象封装的基本原则... 不要随便使用... * * @throws Exception */ @Test public void getPrivateCon() throws Exception { Class clazz = Class.forName("cn.itcast.gz.a_reflect.Person"); // 获取私有的 Constructor c1 = clazz.getDeclaredConstructor(String.class); /**private cn.itcast.gz.a_reflect.Person(java.lang.String)**/
// 创建对象. 注意: 构造函数私有,所以使用时需要设置权限(暴力反射) c1.setAccessible(true);
Object p = c1.newInstance("赵敏"); /**Person [name=赵敏, age=0, num=0]**/ } |
2.5 获取类的方法.
/** * 获取类的方法. * * @throws Exception */ @Test public void testMehtod() throws Exception { Class clazz = Class.forName("cn.itcast.gz.a_reflect.Person");
Object p = clazz.newInstance();
// 获取所有的公有方法,包含父类的. Method[] methods = clazz.getMethods();
// 获取所有的构造函数.包含私有的. Method[] declaredMethods = clazz.getDeclaredMethods();
// 获取指定的方法. // 需要指定函数名, Method m1 = clazz.getMethod("eat", null); /**public void cn.itcast.gz.a_reflect.Person.eat()**/
// Method 对象的 invoke 方法. 执行方法... // 注意: 获取的eat 方法是非静态的, 在Java 中非静态的方法,必须依赖于对象调用的. m1.invoke(p, null);
// 获取有参数的eat 方法. Method m2 = clazz.getMethod("eat", String.class); m2.invoke(p, "馒头");
// 获取静态方法. // 注意: 执行静态方法时, 静态方法不需要创建对象就可以执行, 本例无需指定对象. Method m3 = clazz.getMethod("play", String.class); m3.invoke(null, "lol");
// 获取私有方法. Method m4 = clazz.getDeclaredMethod("movie", String.class); /**private void cn.itcast.gz.a_reflect.Person.movie(java.lang.String)**/
m4.setAccessible(true); m4.invoke(p, "c老师");
/** * public java.lang.String cn.itcast.gz.a_reflect.Person.toString() * public java.lang.String cn.itcast.gz.a_reflect.Person.getName() * public void cn.itcast.gz.a_reflect.Person.setName(java.lang.String) * public void cn.itcast.gz.a_reflect.Person.eat() public void * cn.itcast.gz.a_reflect.Person.eat(java.lang.String) public static * void cn.itcast.gz.a_reflect.Person.play(java.lang.String) private * void cn.itcast.gz.a_reflect.Person.movie(java.lang.String) public int * cn.itcast.gz.a_reflect.Person.getAge() public void * cn.itcast.gz.a_reflect.Person.setAge(int) public void * cn.itcast.gz.a_reflect.Person.eat() */ } |