非常底层却又非常重要的技术:反射(Reflect),是后期学习各种框架最基础的技能
反射(Reflect)是在运行时动态访问类与对象的技术
反射是JDK1.2版本后的高级特性,隶属于java.lang.reflect
大多数Java框架都基于反射实现参数配置、动态注入等特性
反射出现原因:在最初编写代码的时候要实例化一个对象,通过new关键字对指定的类进行实例化。但这种方法的缺点是把实例化的工作写死在程序中的,正是因为这种固定写死的代码不够灵活,所以在我们实际工作中会产生各种不便与困扰。
反射的根本目的就是把我们创建对象的时机从原先的程序编译时延长到程序运行时
反射为何如此重要:因为在各种各样Java的高级框架中,这类框架在应用程序启动的时候会动态地去读取这些配置文件的信息,同时利用反射技术在运行的时候去创建不同的对象。正是因为反射的存在,让Java程序变得比以前更加灵活更加容易被管理
Class.forName(包名+类名)是动态反射中最常用的一个方法,用于加载指定的类
Class.forName(包名+类名).newInstance() 表示对这个类进行实例化,相当于常规操作中的new创建对象,而在反射中创建对象就是newInstance
由于newInstance()方法返回的是Object类对象,因此还需要进行强制类型转换
Java反射相比起传统代码,即使增加了新的类,也不需要修改源代码。在运行时动态决定去实例化哪个对象
毫不夸张地说,正是因为Java提供了反射这种灵活的特性才诞生了比如spring,MyBatis等这种Java高级框架。这些高级框架无一例外都是构建在反射这种基础之上的。因此,学好反射对于掌握其他Java框架非常重要。
-Class类
-Constructor构造方法类
-Method方法类
-Field成员变量类
反射就是基于这四个类来完成在运行时动态创建对象,执行方法,访问成员变量这些操作的
public class ClassExample {
public static void main(String[] args) {
try {
// 1、Class.forName()方法将指定的类加载到jvm,并返回对应的class对象(字节码文件加载到jvm中)
Class<?> employeeClass = Class.forName("com.example.demo01.entity.Employee");
// 2、newInstance 通过默认的构造方法创建对象
Employee employee = (Employee)employeeClass.newInstance();
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
public class ConstructorExample {
public static void main(String[] args) {
try {
// 1、Class.forName()方法将指定的类加载到jvm,并返回对应的class对象(字节码文件加载到jvm中)
Class<?> employeeClass = Class.forName("com.example.demo01.entity.Employee");
// 2.1 获取到constructor构造方法类 得到指定格式到构造方法 Class数组
Constructor<?> constructor = employeeClass.getConstructor(new Class[]{
Integer.class,
String.class,
Float.class,
String.class
});
// 2.2 newInstance 传入对应的方法创建对象
Employee employee = (Employee)constructor.newInstance(new Object[]{
100,
"zhangsan",
8000f,
"开发"
});
System.out.println(employee);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
// 当被调用的方法的内部抛出了异常而没有被捕获时就会抛出该异常
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
Constructor类的特点
Method对象指代某个类中的方法的描述。作为Method,它说明的是我们要调用的某个类的方法里面包含了哪些返回值,参数有几个,各是什么类型都是能通过Method对象来获取的
public class MethodExample {
public static void main(String[] args) {
try {
Class<?> employeeClass = Class.forName("com.example.demo01.entity.Employee");
Constructor<?> constructor = employeeClass.getConstructor(new Class[]{
Integer.class,
String.class,
Float.class,
String.class
});
Employee employee = (Employee) constructor.newInstance(new Object[]{
100,
"zhangsan",
8000f,
"开发"
});
// 3、根据方法名和方法参数类 获取到方法对象
Method updateSalary = employeeClass.getMethod("updateSalary", new Class[]{Float.class});
// 3.1 执行对应方法:哪个对象、方法参数值
Employee invoke = (Employee)updateSalary.invoke(employee, new Object[]{1000f});
System.out.println(invoke);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
// 当被调用的方法的内部抛出了异常而没有被捕获时就会抛出该异常
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
public static void main(String[] args) {
try {
Class<?> employeeClass = Class.forName("com.example.demo01.entity.Employee");
Constructor<?> constructor = employeeClass.getConstructor(Integer.class, String.class, Float.class, String.class);
Employee employee = (Employee) constructor.newInstance(new Object[]{100, "zhangsan", 8000f, "开发"});
// 4.1 根据classObj获取字段对象Field
Field enameFiled = employeeClass.getField("ename");
// 4.2 获取 这个实例employee的字段值
String ename = (String) enameFiled.get(employee);
// 4.3 给字段值赋值
enameFiled.set(employee, "zhangsa");
System.out.println(employee);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
// 当被调用的方法的内部抛出了异常而没有被捕获时就会抛出该异常
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (NoSuchFieldException e) {
throw new RuntimeException(e);
}
}