一. 反射是什么?
对于任意一个类,知道一个类的字节码文件, 就能够知道这个类的属性和方法,就能够调用它的任意一个方法和属性。
二. 反射怎么用?
比如我要获取类Student的各个属性。
1. 首先获取Class对象,有三种方式:
1.1. 使用Object类中getClass方法(不常用, 因为都已经有对象了)
Student stu1 = new Student();
Class stuClass = stu1.getClass();
1.2. 任何数据类型(包括基本数类型)都有一个"静态"的class属性
(需要导入类的包,依赖性强,不导包就会报错)
Class stuClass = Student.class;
1.3. 通过Class类的静态方法: forName(String className)(常用)
Class stuClass3 = Class.forName("com.neu.Student");
2. 通过调用Class方法实现反射
-
获取构造器并调用
1 public Constructor[] getConstructors():所有"公有的"构造方法
2 public Constructor[] getDeclaredConstructors():获取所有的构造方法(包括私有、受保护、默认、公有)
3 public Constructor getConstructor(Class… parameterTypes): 获取单个的"公有的"构造方法:
4 public Constructor getDeclaredConstructor(Class… parameterTypes):获取"某个构造方法"可以是私有的,或受保护、默认、公有;
5 Constructor–>newInstance(Object… initargs) 调用constructor生成实例对象, 用Object接受 -
获取成员变量并更改:
1 Field[ ] getFields(): 获取所有的"共有字段", 批量
2 Field[ ] getDeclaredFields(): 获取所有字段, 包括私有、受保护、默认、共有,批量
3 public Field getField(String fieldName): 获取某个"共有的"字段
4 public Field getDeclaredField(String fieldName): 获取某个字段(可以私有)
5 Field --> public void set(Object obj,Object value): 1. obj:要设置的字段所在对象; 2. value:要为字段设置的值; -
获取成员方法并调用
1 public Method[] getMethods():获取所有"公有方法";(包含了父类的方法也包含Object类)
2 public Method[] getDeclaredMethods():获取所有的成员方法,包括私有的(不包括继承的)
3 public Method getMethod(String name,Class<?>… parameterTypes):参数: 1. name方法名 2.Class … : 形参的Class类型对象
4 public Method getDeclaredMethod(String name,Class<?>… parameterTypes)
5 Method --> public Object invoke(Object obj,Object… args):参数:obj: 要调用方法的对象 args: 调用方法时所传递的实参
调用static的方法时, 用null做Object的实参
实训时讲师的代码如下:
public static void main(String[] args) throws Exception {
//ActionClass action = getActionClass();
//什么是反射?
//反射是 分析类 的程序。
/*获得操作对象有3种方式:
1. 类名.class
2. Class.forName("类路径")
3. 对象.getClass()
*/
/*System.out.println(Main.class.getName());
System.out.println(Class.forName("a.b.c.d.e.Main"));
System.out.println(new Main().getClass());*/
//获得操作对象
/*Class<Main> c1 = Main.class;
Class c2 = Class.forName("a.b.c.d.e.Main");
Class c3 = new Main().getClass();*/
//利用反射分析 My类
Class<My> clazz = My.class;
System.out.print(Modifier.toString(clazz.getModifiers()) + " ");
System.out.print(clazz.getName() +" ");//类路径
System.out.println(" extends " + clazz.getGenericSuperclass().getTypeName());//父类
// System.out.println(clazz.getGenericInterfaces().length);//所有接口
//获取my类的所有属性
Field[] fields = clazz.getDeclaredFields();
for(Field f : fields){
System.out.print(Modifier.toString(f.getModifiers()) +" ");
System.out.print(f.getType().getName() +" ");
System.out.println(f.getName());
}
//获取构造方法
Constructor[] cons = clazz.getDeclaredConstructors();
for(Constructor c : cons){
System.out.println(c.getParameterCount());
Class[] params = c.getParameterTypes();
for(Class p : params){
System.out.print(p + " ");
}
}
System.out.println();
//实例方法
Method[] methods = clazz.getMethods();
for(Method m : methods){
System.out.print(m.getReturnType() + " ");
System.out.print(m.getName() + "( ");
Class[] types = m.getParameterTypes();
for(Class t : types){
System.out.print(t.getTypeName() + " ");
}
System.out.println(" ) ");
}
}
public static void main(String[] args) throws Exception {
//ActionClass action = getActionClass();
//什么是反射?
//反射是 分析类 的程序。
/*获得操作对象有3种方式:
1. 类名.class
2. Class.forName("类路径")
3. 对象.getClass()
*/
/*System.out.println(Main.class.getName());
System.out.println(Class.forName("a.b.c.d.e.Main"));
System.out.println(new Main().getClass());*/
//获得操作对象
/*Class<Main> c1 = Main.class;
Class c2 = Class.forName("a.b.c.d.e.Main");
Class c3 = new Main().getClass();*/
//利用反射分析 My类
/*Class<My> clazz = My.class;
System.out.print(Modifier.toString(clazz.getModifiers()) + " ");
System.out.print(clazz.getName() +" ");//类路径
System.out.println(" extends " + clazz.getGenericSuperclass().getTypeName());//父类
// System.out.println(clazz.getGenericInterfaces().length);//所有接口
//获取my类的所有属性
Field[] fields = clazz.getDeclaredFields();
for(Field f : fields){
System.out.print(Modifier.toString(f.getModifiers()) +" ");
System.out.print(f.getType().getName() +" ");
System.out.println(f.getName());
}
//获取构造方法
Constructor[] cons = clazz.getDeclaredConstructors();
for(Constructor c : cons){
System.out.println(c.getParameterCount());
Class[] params = c.getParameterTypes();
for(Class p : params){
System.out.print(p + " ");
}
}
System.out.println();
//实例方法
Method[] methods = clazz.getMethods();
for(Method m : methods){
System.out.print(m.getReturnType() + " ");
System.out.print(m.getName() + "( ");
Class[] types = m.getParameterTypes();
for(Class t : types){
System.out.print(t.getTypeName() + " ");
}
System.out.println(" ) ");
}*/
Class<My> clazz = My.class;
//获取无参构造
Constructor<My> c = clazz.getDeclaredConstructor(null);
//构造方法的作用: 1.实例化对象 2.属性赋值
//创建对象(利用反射创建 My类的对象)
My my = c.newInstance(null);
System.out.println(my);
System.out.println(my.getId());
System.out.println(my.getName());
//构造2
/*c = clazz.getDeclaredConstructor(int.class,String.class);
my = c.newInstance(100,"zyw");
System.out.println(my.getId());
System.out.println(my.getName());*/
//反射调实例方法
Method m1 = clazz.getMethod("setId", int.class);
//实例方法 必须对象调用
//invoke(对象,参数值列表)
m1.invoke(my, 123);
m1 = clazz.getMethod("getId", null);
Object result = m1.invoke(my, null);
System.out.println(result);
//调用静态方法
m1 = clazz.getMethod("test");
//null 表示不用传对象
m1.invoke(null);
}