java反射机制详解

java 反射机制

一、反射的概述

Java反射机制是 Java 语言的一个重要特性,它在服务器程序和中间件程序中得到了广泛运用。在服务器端,往往需要根据客户的请求,动态调用某一个对象的特定方法。此外,在 ORM 中间件的实现中,运用 Java 反射机制可以读取任意一个 JavaBean 的所有属性,或者给这些属性赋值

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性(不管这个方法或者属性是用public修饰,还是用private 修饰,反射机制可以忽略这种访问权限修饰符);这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。 要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象

反射就是把java类中的各种成分映射成一个个的Java对象

二,反射提供的功能

  • 在运行时判断任意一个对象所属的类

  • 在运行时构造任意一个类的对象

  • 在运行时判断任意一个类所具有的成员变量和方法

  • 在运行时调用任意一个对象的方法

class类 :代表一个类,是Java反射机制的起源和入口

要想实现反射,首先必须得到这个类的class字节码对象

用于获取与类相关的各种信息, 提供了获取类信息的相关方法

Class类继承自Object类

Class类是所有类的共同的图纸

每个类有自己的对象,同时每个类也看做是一个对象,有共同的图纸Class,存放类的结构信息,能够通过相应方法取出相应的信息:类的名字、属性、方法、构造方法、父类和接口。

三, 获取Class 对象的三种方法

想要操作反射,首先必须得到反射的入口

1.通过class.forName("全类名");

这里的全类名是包名点类名,仅仅写类名是找不到的。注意这里需要抛出异常

        // 第一种
       try {
           Class<?>  studentClass1 = Class.forName("exercise.Student");
      }catch (ClassNotFoundException e ){
           e.printStackTrace();
      }

2.类名.class

        Class<?> studentClass2 =  Student.class;

3.对象.getClass()

        Student stu1 = new Student("小明",1);
       Class<?>   studentClass3 =  stu1.getClass();

四,根据class 对象获取类的信息

可以用一个类的反射入口class 对象获取类的所有信息

例1:获取此类的所有public 方法 ,其中包括,父类的,实现接口的,自己的

        // 可以用一个类的反射入口class对象获取类的所有信息
// studentClass2 是我们利用上面三种方法之一 获取的class 对象
       Method[] methods =  studentClass2.getMethods();
       for(Method method : methods ){
           System.out.println(method);
      }

例2:获取所有的构造方法

        Constructor<?>[] constructors =  studentClass2.getConstructors();
       for(Constructor  constructor : constructors ){
           System.out.println(constructor);
      }

例3: 获取父类

        Class<?> superClass = studentClass2.getSuperclass();

例4: 获取当前类(只有本类的) 所有方法,包括私有的

        Method[] declareMethods =  studentClass2.getDeclaredMethods();
       for(Method method : declareMethods ){
           System.out.println(method);
      }

例5: 获取当前类(只有本类的)所有属性,包括私有的

        System.out.println("===========================================");
       Field[] declareFields =  studentClass2.getDeclaredFields();
       for(Field field : declareFields){
           System.out.println(field);
      }

重点: 可以获取当前类的对象,并通过对象调用类的方法

        try {
           Object instance = studentClass2.newInstance();
           Student student1 = (Student)instance;
           student1.study();
      } catch (InstantiationException e) {
           e.printStackTrace();
      } catch (IllegalAccessException e) {
           e.printStackTrace();
      }

五,通过反射获取对象的实例 操作对象

  1. class.newInstance() ,并强转类型,然后就可以操作对象了,主要是调用方法

            Object instance =  null;
           try {
                instance =  studentClass2.newInstance();
          } catch (InstantiationException e) {
               e.printStackTrace();
          } catch (IllegalAccessException e) {
               e.printStackTrace();
          }
           Student  student2  = (Student)instance;
           student2.setName("同济小孙");
           student2.setId(1832921);
           student2.study();
  1. 操作属性 可以操作类里面的public 属性和private 属性

    如果属性是private ,正常情况下是不允许外界操作属性值,这里可以用Field 类的setAccessible(true) 方法,暂时打开操作的权限

            System.out.println("===========================================");
           try {
               Student student3 =(Student)studentClass2.newInstance();
               Field idField =  studentClass2.getDeclaredField("id");
               idField.setAccessible(true);
               idField.set(student3,1111455);
               System.out.println(student3.getId());

          } catch (Exception e) {
               e.printStackTrace();
          }

    调用方法也一样,可以调用私有的方法,null 是因为这个方法没有参数

            System.out.println("===========================================");
           try {
               Student student4 =(Student)studentClass2.newInstance();
               Method sleepmethod =  studentClass2.getMethod("sleep",null);
               sleepmethod.setAccessible(true);  
               // 注意这个 sleep 方法需要是 public 修饰才可以访问到  
               sleepmethod.invoke(student4,null);
          } catch (Exception e) {
               e.printStackTrace();
          }

六. 在程序执行中动态的决定调用的类以及方法

在本例中,程序执行之前,程序根本不知道具体的类和方法名是什么,需要执行时解析properties 文件,但是反射就可以办到

配置文件 :

文件名: class.txt

文件内容:

classnaem=reflect.Person

methodname=staticMethod

反射机制L

Properties prop =  new Properties();
prop.load( new FileReader("class.txt"));
String className = prop.getProperty("classname");
String methodName = prop.getProperty("methodname");

Class<?>  perClazz =  null;
try{
   perClazz =  Class.forName(className);
}catch(ClassNotFoundExcepytion e ){
   e.printStackTrace();
}
Method method =  perClazz.getMethod(method);
method.invoke(perrClass.newInstance());

附录代码

public class Person {
   private String name;
   private int age;
   public Person(String name,int age ){
       this.name =  name;
       this.age =  age;
  }
}


public class Student extends Person {

   private String name;
   private int id;

   public Student(String name ,int id ){
       super(name,20);
       this.name = name;
       this.id =  id ;
  }
   public Student (int id ){
       super("无名氏",20);
       this.name = "无名氏";
       this.id =  id;
  }
   public Student(){
       super("无名无学号",20);
       this.name =  "无名无学号";
       this.id =  100;
  }

   public String getName() {
       return name;
  }

   public int getId() {
       return id;
  }

   public void setName(String name) {
       this.name = name;
  }

   public void setId(int id) {
       this.id = id;
  }

   public void study(){
       System.out.println(name +" , 学号为"+id + ", 正在认真的学习");
  }

   public void sleep(){
       System.out.println(name +" , 学号为"+id + ", 正在睡觉");
  }
}

测试


import exercise.Student;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class TestReflect {

   public static void main(String[] args ){
       // 获取类对象的三种方式

       // 第一种
       try {
           Class<?>  studentClass1 = Class.forName("exercise.Student");
      }catch (ClassNotFoundException e ){
           e.printStackTrace();
      }

       // 第二种
       Class<?> studentClass2 =  Student.class;

       // 第三种
       Student stu1 = new Student("小明",1);
       Class<?>   studentClass3 =  stu1.getClass();

       // 可以用一个类的反射入口class对象获取类的所有信息
       Method[] methods =  studentClass2.getMethods();
       for(Method method : methods ){
           System.out.println(method);
      }
       System.out.println("===========================================");

       Constructor<?>[] constructors =  studentClass2.getConstructors();
       for(Constructor  constructor : constructors ){
           System.out.println(constructor);
      }

       System.out.println("===========================================");
       Class<?> superClass = studentClass2.getSuperclass();

       System.out.println("===========================================");
       Method[] declareMethods =  studentClass2.getDeclaredMethods();
       for(Method method : declareMethods ){
           System.out.println(method);
      }


       System.out.println("===========================================");
       Field[] declareFields =  studentClass2.getDeclaredFields();
       for(Field field : declareFields){
           System.out.println(field);
      }

       System.out.println("===========================================");
       try {
           Object instance = studentClass2.newInstance();
           Student student1 = (Student)instance;
           student1.study();
      } catch (InstantiationException e) {
           e.printStackTrace();
      } catch (IllegalAccessException e) {
           e.printStackTrace();
      }

       System.out.println("===========================================");
       Object instance =  null;
       try {
            instance =  studentClass2.newInstance();
      } catch (InstantiationException e) {
           e.printStackTrace();
      } catch (IllegalAccessException e) {
           e.printStackTrace();
      }
       Student  student2  = (Student)instance;
       student2.setName("同济小孙");
       student2.setId(1832921);
       student2.study();

       System.out.println("===========================================");
       try {
           Student student3 =(Student)studentClass2.newInstance();
           Field idField =  studentClass2.getDeclaredField("id");
           idField.setAccessible(true);
           idField.set(student3,1111455);
           System.out.println(student3.getId());

      } catch (Exception e) {
           e.printStackTrace();
      }

       System.out.println("===========================================");
       try {
           Student student4 =(Student)studentClass2.newInstance();
           Method sleepmethod =  studentClass2.getMethod("sleep",null);
           sleepmethod.setAccessible(true);
           // 注意这个 sleep 方法需要是 public 修饰才可以访问到
           sleepmethod.invoke(student4,null);
      } catch (Exception e) {
           e.printStackTrace();
      }
  }

}



posted @ 2020-07-21 11:36  同济小孙  阅读(296)  评论(0编辑  收藏  举报