Spring基础之 反射(Reflection)
1.了解Class
package com.inspire.reflection.Class_api; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ClassUtils { public static void main(String[] args) { String s="abc"; printclassFieldMessage(s); printClassMethodMessage(s); } /** * 打印类的信息,成员方法 * @param obj 该对象所属类的信息 */ public static void printClassMethodMessage(Object obj){ //获取类的信息,获取类的类类型 Class c1=obj.getClass();//传递的哪个子类的对象,c就是该子类的类类型 //获取类的名称 System.out.println("类名是:"+c1.getName()); //获取方法 /* Method类,方法的对象 一个成员方法就是一个Method对象 getMethods方法获取的是所有的public的方法,包括父类继承而来的 getDeclaredMethods方法获取的是所有该类自己定义的方法。不问访问权限 */ Method[] methods=c1.getMethods(); // Method[] method=c1.getDeclaredMethods(); for (int i = 0; i <methods.length ; i++) { //获取方法的返回值类型的类类型(比如返回String类型,返回的是String.class) Class returnType=methods[i].getReturnType(); System.out.print(returnType.getName()+" "); //获取方法的名称 System.out.print(methods[i].getName()+"("); //获取参数类型 获取的是参数列表类型的类类型 Class[] paramType=methods[i].getParameterTypes(); for (Class c:paramType) { System.out.print(c.getName()+","); } System.out.println(")"); } } /** * 打印类的信息,成员变量 * @param obj */ public static void printclassFieldMessage(Object obj) { //获取成员变量 /** * 成员变量也是对象 * java.lang.reflect.Field * Field封装了关于成员变量的操作 * getFields方法获取的是所有的public的成员变量信息 * getDeclaredFields()获取的是该类自己声明的成员信息(public/private) */ Class c1=obj.getClass();//传递的哪个子类的对象,c就是该子类的类类型 //Field[] fields=c1.getFields(); Field[] fields=c1.getDeclaredFields(); for (Field f:fields) { //得到成员变量类型的类类型 Class fieldType=f.getType(); //得到成员变量的名称 String typeName=f.getName(); System.out.println(typeName+" "+fieldType); } } /** * 打印对象的构造函数的信息 * @param obj */ public static void printClassConMessage(Object obj){ Class c=obj.getClass(); /* 构造函数也是对象 java.lang.Constructor中封装了构造函数的信息 getDeclaredConstructor获取自己声明的构造函数 */ Constructor[] constructors=c.getDeclaredConstructors(); //Constructor[] constructors=c.getConstructors(); for (Constructor constructor:constructors) { System.out.println(constructor.getName()+"("); //获取构造函数的参数列表 Class[] paramType=constructor.getParameterTypes(); for (Class c1:paramType) { System.out.print(c1.getName()+","); } System.out.println(")"); } } }
2.获取一个类的类对象
(1).定义一个类
public class Student { private int id; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } 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; } private int age; }
(2).获取类对象
public class ClassDemo1 { public static void main(String[] args) { //Student的实例对象如何表示? // Student student=new Student(); /*Student也是实例对象,是Class类的实例对象。如何表示? 任何一个类都是Class类的实例对象,都有三种表示方法 */ //方式一:任何一个类都有一个隐含的静态成员class Class c1=Student.class; //方式二:已知该类的对象,通过getClass方法 Student student=new Student(); Class c2=student.getClass(); /* c1,c2表示了Student类的类类型(Class type) 万事万物皆对象 类也是对象,是Class类的实例对象 这个对象我们称为该类的类类型 */ //c1,c2都代表了Student类的类类型,一个类只可能是Class类的一个实例对象 System.out.println(c1==c2); //true //方式三: try { Class c3=Class.forName("com.inspire.reflection.Class_object.Student"); System.out.println(c2==c3); //true } catch (ClassNotFoundException e) { e.printStackTrace(); } /* 有了类的类类型,我们可以通过类类型创建该类的对象.即通过c1,c2,c3创建对象 */ try { Student student1= (Student) c1.newInstance(); //调用方法 student1.getAge(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
3.通过反射调用方法
public class Printer { public void printA(){ System.out.println("无参的方法.........."); } public void printA(int a,int b){ System.out.println(a+":"+b); } }
public class MethodDemo { public static void main(String[] args) { Printer printer=new Printer(); Class c=printer.getClass(); try { //获取方法 Method method= c.getDeclaredMethod("printA", int.class, int.class);//获取自己声明的方法 //c.getMethod("printA", int.class, int.class);//获取public的方法 //方法的反射操作 method.invoke(printer,1,3); //放回方法的返回值 System.out.println("========================="); Method method1=c.getDeclaredMethod("printA"); method1.invoke(printer); } catch (Exception e) { e.printStackTrace(); } } }
4.通过反射理解泛型
java中泛型是防止错误输入的。只在编译时有效。编译之后集合的泛型是去泛型化的
public static void main(String[] args){ ArrayList<String> list1=new ArrayList<String>(); list1.add("hello"); ArrayList list2=new ArrayList<String>(); //System.out.println(c1==c2);//结果为true,说明编译之后集合的泛型是去泛型化的 Class c2=list1.getClass(); try { Method method=c2.getMethod("add", Object.class); //注意这里:虽然上面定义list1时是String类型的,但是这里可以加入int类型的数据 method.invoke(list1,100); System.out.println(list1.size()); System.out.println(list1);//不能用foreach遍历,类型不一样了 } catch (Exception e) { e.printStackTrace(); } }