zoukankan      html  css  js  c++  java
  • 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();
          }
      }

    }



  • 相关阅读:
    新建maven web工程报错
    Linux的系统suspend和resume
    Linux内核配置---menuconfig
    printk()函数学习笔记
    驱动调试笔记
    i2c接口笔记
    无线路由器的加密模式WEP,WPA-PSK(TKIP),WPA2-PSK(AES) WPA-PSK(TKIP)+WPA2-PSK(AES)。
    Linux下sniffer实现(转)
    驱动模块(3)——Linux交叉编译工具链
    ehci ohci 驱动逻辑
  • 原文地址:https://www.cnblogs.com/1832921tongjieducn/p/13354175.html
Copyright © 2011-2022 走看看