Java反射机制详解

£可爱£侵袭症+ 提交于 2019-11-26 13:22:17

基础

编译期运行期,编译期就是编译器帮你把源代码翻译成机器能识别的代码,比如编译器把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

Dog dog = new Dog();//dog是类Dog的对象,Dog是类Class的实例对象;

Class d = dog.getClass();//通过dog的getClass()方法可以得到dog对象对应的Class的实例对象——Dog

2.通过类Class的静态方法forName():

1

2

3

4

5

try {

           Class dog1 = Class.forName("Dog");

       } catch (ClassNotFoundException e) {

           e.printStackTrace();

       }

3.直接给出对象类文件的.class:

1

Class dog2 = Dog.class;

 

反射机制

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"));
        }

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!