Java 反射机制

来源:互联网 发布:java高内聚低耦合 编辑:程序博客网 时间:2024/05/22 08:24

反射

经常使用反射,但其实一直对反射没有一个较为深入的理解,今天就来整体梳理并且总结一下这个知识点。

概念:

反射是一种运行时获取,检测,访问类自身信息的能力。对于运行时的任意一个类,都能知道这个类的所有属性和方法;对于该类的任意一个对象,都能够调用它的任意方法和属性。这也是Java称为”动态语言”的原因。

用途:

  • 运行时获取一个类的对象(只需知道类名即可);
  • 运行时获取一个类的属性和方法(包括构造方法),包括它的父类信息;
  • 运行时判断任意对象所属的类;
  • 运行时调用任意一个对象的方法。

反射的这些功能的前提是本地存在需要的类。当通过反射与一个未知的对象打交道时,JVM只是简单的检查这个对象,看它属于哪个特定的类,在用这个类做其他事情之前必须加载哪个类的Class对象,因此,哪个类.class文件对于JVM来说必须是可获取的,要么在本地,要么通过网络获取。

与反射相关的API

java.lang.Classjava.lang.reflect

Class类与java.lang.reflect类一起封装了对java反射的支持,该类库包含了Field,Method,Constructor类,这些类型的对象是由JVM在运行时创建的,用以表示未知类里对应的成员,这样你就可以使用Constructor创建新的对象,用get(),set()方法读取和修改与Field对象关联的字段,用invoke()方法调用与Method关联的方法。还可以通过getField(), getMethods()和getConstructor()等方法返回表示字段,方法,构造器。这样,匿名对象的类信息就能在运行时被完全确定下来了,而在编译时不需要知道任何。

一个简单的例子

Person.java

public abstract class Person {    private int mAge;    Person(int age){        this.mAge = age;    }    public void setAge(int age){        this.mAge = age;    }    public abstract void dress();//穿衣}

doExam.java

public interface doExam {    public void exam();}

Student.java

public class Student extends Person implements doExam {    private String mGrade;//年级    public Student(int age){        super(age);    }    public Student(int age, String grade){        super(age);        this.mGrade = grade;    }    public void setGrade(String grade){        mGrade = grade;    }    public String getGrade(){        return this.mGrade;    }    private void doHomework(boolean isDo){        if(isDo){            System.out.println("我要做家庭作业!");        }else{            System.out.println("我要去打LOL");        }    }    @Override    public void dress() {        System.out.println("myreflect.Student -----> 学生穿校服");    }    @Override    public void exam() {}}

下面是main方法,直接在main方法中做一些测试,这样看起来更加一目了然:

public class ReflectTest {    public static void main(String[] args) throws Exception {        getClassNameTest();        getConstructorTest();        getInterfacesTest();        constructorTest();        methodTest();        fieldTest();    }    // 1. 获取类名    private static void getClassNameTest() throws ClassNotFoundException {        System.out.println("-----------------getClassNameTest-----------------");        //方法一        Class studentClass = Class.forName("myreflect.Student");        System.out.println("getName = "+studentClass.getName());        //方法二        Class studentClass1 = Student.class;        System.out.println("getName = "+studentClass1);        //获取父类        Class superClass = studentClass.getSuperclass();        System.out.println("getSuperclass = "+superClass.getName());    }    // 2. 获取构造方法    private static void getConstructorTest() throws ClassNotFoundException {        System.out.println("-----------------getConstructorTest-----------------");        Class studentClass = Class.forName("myreflect.Student");        Constructor[] consList = studentClass.getDeclaredConstructors();        for(Constructor cons:consList){            System.out.println("Constructor = "+cons.getName());        }    }    // 3. 获取所有的接口    private static void getInterfacesTest() throws ClassNotFoundException {        System.out.println("----------------getInterfacesTest------------------");        Class studentClass = Class.forName("myreflect.Student");        Class<?> interfaces[] = studentClass.getInterfaces();        System.out.println("studentClass实现的接口有:");        for (int i = 0; i < interfaces.length; i++) {            System.out.println((i + 1) + ":" + interfaces[i].getName());        }    }    // 4. 通过反射实例化一个对象    private static void constructorTest() throws Exception {        System.out.println("----------------constructorTest------------------");        Class studentClass = Class.forName("myreflect.Student");        Constructor<Student> cons = studentClass.getConstructor(int.class, String.class);        Student student = cons.newInstance(15, "初三");        student.setAge(24);        student.setGrade("研一");        System.out.println("student age = "+student.getAge());        System.out.println("student grade = "+student.getGrade());    }    //修改属性字段    private static void fieldTest() throws Exception {        System.out.println("----------------fieldTest------------------");        Student student = new Student(15,"初三");        //获取父类,否则不能找到        Class personClass = Class.forName("myreflect.Person");        Field field = personClass.getDeclaredField("mAge");        field.setAccessible(true);        field.set(student,100);        System.out.println("student age = "+student.getAge());    }    // 5. 操作方法    //操作普通方法可以使用 getMethod() ,该方法有两个参数:一个是方法名,一个是参数类型    //操作private类型方法需要使用 getDeclaredMethod(), 同样有两个参数,该方法有两个参数:一个是方法名,一个是参数类型    public static void methodTest() throws Exception {        System.out.println("----------------methodTest------------------");        Student student = new Student(15,"初三");        Class studentClass = Class.forName("myreflect.Student");        Method method = studentClass.getMethod("setAge",int.class);        method.invoke(student,22);        System.out.println("修改后的对象为:student age = "+student.getAge());        Method method1 = studentClass.getDeclaredMethod("doHomework",boolean.class);        method1.setAccessible(true);        method1.invoke(student, false);    }}

运行结果:
这里写图片描述

0 0
原创粉丝点击