反射
通过反射,我们可以在运行时获得程序或程序集中每一个类型的成员和成员的信息。程序中一般的对象的类型都是在编译期就确定下来的,而 Java 反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。
用处: eclipse工具写完对象然后会自动提示有哪些方法。
spring通过配置文件的配置实例化对象。灵活的配置起到解耦的作用。
动态代理会用到反射。
jdbc通过获得实体类字段上的注解中的内容然后拼接sql进行操作数据库。
java中的Class对象
每一个类都有一个Class对象,每当编译一个新类就产生一个Class对象,基本类型 (boolean, byte, char, short, int, long, float, and double)有Class对象,数组有Class对象,就连关键字void也有Class对象(void.class)。Class对象对应着java.lang.Class类,如果说类是对象抽象和集合的话,那么Class类就是对类的抽象和集合。
获得class对象的三种方式
-
使用Classforname(String className)
Class<?> userinfoClass = Class.forName("com.xpwang.blog.UserInfo");
-
直接获取一个类的Class对象
Class<?> userinfoClass2= UserInfo.class;
-
通过调用对象的getClass()方法获得。
UserInfo userInfo = new UserInfo(); Class<?> userinfoClass3 = userInfo.getClass();
Class对象的特性(直接用代码演示一目而了然)
// 不论通过哪种方式获得该类的Class对象,它们返回的都是指向同一个java堆地址上的Class引用。jvm不会创建 两个相同类型的Class对象
System.out.println(userinfoClass2==userinfoClass1);//true
System.out.println(userinfoClass2==userinfoClass3);//true
//数组的大小不同也是引用的同意个Class对象
String[] strings = new String[6];
String[] strings2 = new String[10];
System.out.println(strings.getClass()==strings2.getClass());//true
//一维数组和二维数组引用的不是同一个Class对象
String[][] strings3 = new String[6][6];
Integer[] integers = new Integer[6];
Class<?> array =strings.getClass();
Class<?> array2 =strings3.getClass();
System.out.println(array==array2);//false
//不同类型的数组引用的也不是同一个Class对象
Integer[] integers = new Integer[6];
Class<?> array =strings.getClass();
Class<?> array2 =integers.getClass();
System.out.println(array==array2);//false
通过Class对象创建实例、获取成员变量以及调用方法
- 直接通过Class对象newInstance的方法创建实例
Class<?> userinfoClass1 = Class.forName("com.xpwang.blog.UserInfo");
UserInfo newInstance = (UserInfo)userinfoClass1.newInstance();
newInstance.setAge(10);
System.out.println(newInstance);//UserInfo [name=null, age=10]
- 获取构造器通过构造器方法实例化对象
Constructor<?> constructor = userinfoClass1.getConstructor(String.class,Integer.class);//构造器后面的参数,如果是无参则后面为空
UserInfo newInstance = (UserInfo)constructor.newInstance("张三",15);
System.out.println(newInstance);//UserInfo [name=张三, age=15]
-
获取方法并调用
Class<?> userinfoClass1 = Class.forName("com.xpwang.blog.UserInfo"); UserInfo userInfo2 =(UserInfo)userinfoClass1.newInstance(); Method method = userinfoClass1.getMethod("query", String.class);//参数为方法名字和参数类型的Class对象 method.invoke(userInfo2, "张三");//已经查询到名字为张三的信息