基础
编译期和运行期,编译期就是编译器帮你把源代码翻译成机器能识别的代码,比如编译器把java代码编译成jvm识别的字节码文件,而运行期指的是将可执行文件交给操作系统去执行,JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制
反射机制的实现核心就是通过实例化Class类来动态获得Java类的信息;
每一个自定义的类在编译成.class文件的时候都会创建一个对应的实例化的Class对象,
Class对象是JVM用来保存普通类的信息的类——可以通过实例化Class类而得到一个普通类;
这种实现方式和JVM的懒加载机制相迎合——在需要的时候将需要的.class文件和Class对象加载进内存中;
懒加载:当Cat.java编译成Cat.class文件后并不会立即被加载到内存,而是在它的的静态成员第一次被访问时才被加载(这么看来,Cat的默认构造方法也是静态的!)
Class对象的获得
得到一个实例对象对应的Class对象有以下三种方式:
1.通过实例变量的getClass()方法:
|
1 2 |
|
2.通过类Class的静态方法forName():
|
1 2 3 4 5 |
|
3.直接给出对象类文件的.class:
|
1 |
|
反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射机制是通过上述的Class类实现的,也就是说,因为我们为每个Java类都创建了相应的Class实例对象来保存关于类的信息,从而我们可以通过获得这个类的Class对象获得对应的类的信息——
也即是说,我们可以通过只知道一个类的类名,或者这个类的一个实例对象,就可以获得这个类的全部信息,这就是Java的反射机制;
代码示例:
package JavaReflection;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class mainTest{
public static void main(String []args)
{
System.out.println("通过反射机制获得类的信息:");
System.out.println("//通过对象获取——");
entity obj1=new entity();
Class class1=obj1.getClass();
Field[] fields1 = class1.getDeclaredFields();
for (Field field : fields1){
System.out.println(field);
}
Method[] methods1 = class1.getDeclaredMethods();
for (Method method : methods1){
System.out.println(method);
}
System.out.println("//通过类名获取属性字段——");
try {
Class class2= Class.forName("JavaReflection.entity");
Field[] fields2 = class2.getDeclaredFields();
for (Field field : fields2){
System.out.println(field);
}
Method[] methods2 = class2.getDeclaredMethods();
for (Method method : methods2){
System.out.println(method);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
System.out.println("//直接获取.class 文件");
Class class3=entity.class;
Field[] fields3 = class3.getDeclaredFields();
for (Field field : fields3){
System.out.println(field);
}
Method[] methods3 = class3.getDeclaredMethods();
for (Method method : methods3){
System.out.println(method);
}
}
}
class entity {
private String stringField;
public static String staticField;
public String publicField;
static {
staticField ="nihao";
}
public entity()
{
}
//public 方法
public void pubfunction() {
;
}
//private方法
private void prifunction() {
;
}
}
运行结果:
通过反射机制获得类的信息:
//通过对象获取——
private java.lang.String JavaReflection.entity.stringField
public static java.lang.String JavaReflection.entity.staticField
public java.lang.String JavaReflection.entity.publicField
public void JavaReflection.entity.pubfunction()
private void JavaReflection.entity.prifunction()
//通过类名获取属性字段——
private java.lang.String JavaReflection.entity.stringField
public static java.lang.String JavaReflection.entity.staticField
public java.lang.String JavaReflection.entity.publicField
public void JavaReflection.entity.pubfunction()
private void JavaReflection.entity.prifunction()
//直接获取.class 文件
private java.lang.String JavaReflection.entity.stringField
public static java.lang.String JavaReflection.entity.staticField
public java.lang.String JavaReflection.entity.publicField
public void JavaReflection.entity.pubfunction()
private void JavaReflection.entity.prifunction()
反射的意义就是让Java的代码在运行期间可以获得;
反射的应用
注解
编写框架
需要在运行期间动态获取类的时候
如下:这段代码想必大家肯定都有写过,这个数据库的连接驱动类就是编译的时候不知道你到底是用的mysql,oracle还是其他数据库,而是由运行期动态加载的
// 1.加载驱动程序
Class.forName("com.mysql.jdbc.Driver");
// 2.获得数据库的连接
Connection conn = DriverManager.getConnection(URL, NAME, PASSWORD);
// 3.通过数据库的连接操作数据库,实现增删改查
Statement stmt = conn.createStatement();
ResultSet rs = stmt
.executeQuery("select user_name,age from user");
while (rs.next()) {// 如果对象中有数据,就会循环打印出来
System.out.println(rs.getString("user_name") + ","
+ rs.getInt("age"));
}
来源:https://blog.csdn.net/qq_42468130/article/details/91126566