java反射机制的理解

文章目录

    • 类与Class
      • 引出运行时类型识别
      • 类对象的生命周期
    • 反射
      • 利用反射动态加载方法
      • 动态加载属性
    • 通过一个例子展示如何利用反射机制动态获取类对象以及对象方法和属性

类与Class

  • RTTI(Run-Time Type Identification)运⾏时类型识别
  • 一个Class对象就是⼀个类的说明书
    • JVM根据这个说明书创建出来⼀个类的实例

引出运行时类型识别

java反射机制的理解_第1张图片
java反射机制的理解_第2张图片

看上面这个例子:有个通不过编译了,为什么?
java是个强类型的语言,whitecat1这个变量是Object类型的;
其编译的类型为Object类型的, Object这个类没有catchmouse这个方法,故会报错!
(注意:Object是一个非常重要的类,必须对它的所有方法都必须非常了解!!!)

java反射机制的理解_第3张图片

类对象的生命周期

先看下面这个例子:
java反射机制的理解_第4张图片
在程序运行之后:(发现多出class文件了)
java反射机制的理解_第5张图片
java反射机制的理解_第6张图片
为什么呢?
这就要说到java程序的运行过程了,一般是这样的:
.java文件被前端编译器编译为.class文件,而后jvm通过一系列复杂操作将.class文件变为计算机可以识别的二进制文件,最后显示 程序执行的结果(这里为hello);
java反射机制的理解_第7张图片
为了便于理解,这里将拼接的命令行展示如下:
java反射机制的理解_第8张图片
类的加载顺序如下,为了方便理解,这里找出自己写的class和object:
java反射机制的理解_第9张图片
java反射机制的理解_第10张图片
Object–>Animal–>Cat–>whiteCat;
这些.class文件从哪里来的呢?
就是在target/里面
java反射机制的理解_第11张图片
到这里,我们总结一下:
我们自己写的类是从target下面的classes文件里面(通过读取.class文件加载)加载的;
其实在java的世界里面,一般一个.java文件都会对应一个.class(字节码)文件;但是.class不一定对应一个.java文件!.class完全可以“从天而降”,比如它完全是可以从网上下载下来的,文件的本质就是字节流!也可以动态生成的!(可以在内存里面被创造出来,其实这就是ClassLoad所做的事情!)
到了这里就要引出这篇文章的主角-反射了!

反射

先看一个例子:
java反射机制的理解_第12张图片

java反射机制的理解_第13张图片

注意理解下面这句话:
传进来的参数是java.lang.String,这里的Class(这里是c)是String这个类的“说明书”; (我们正常不用反射的程序一般是通过.java文件转变为的.class获取“说明书”的(这不是在运行时动态获取的),而反射是运行时利用forName等方法结合传进来的参数动态获取对象类型的!!!)
而后命令java虚拟机说:请根据说明书创造一个对象出来

利用反射动态加载方法

java反射机制的理解_第14张图片
下面虽然没有调用这个beCute方法,但是根据传进来的参数动态地选择了要调用的方法!!
java反射机制的理解_第15张图片

动态加载属性

java反射机制的理解_第16张图片
java反射机制的理解_第17张图片
java反射机制的理解_第18张图片
java反射机制的理解_第19张图片

通过一个例子展示如何利用反射机制动态获取类对象以及对象方法和属性


package com.github.reflection;


import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

class Test {
    //private field
    private String s;

    //public constructor
    public Test() {
    }

    public Test(String s) {
        this.s = s;
    }

    //public method with no arguments
    public void method1() {
        System.out.println("the string is: " + s);
    }

    //public method with arguments
    public void method2(int n) {
        System.out.println("the number is " + n);
    }

    //private method
    private void method3() {
        System.out.println("private method invoked, I am method3");
    }
}

public class reflect_test {

    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {

        Class cls = Class.forName("com.github.reflection.Test");


        System.out.println("the name of class is: " + cls.getName());

        Constructor constructor = cls.getConstructor();
        System.out.println("the name of construct is: " + constructor.getName());

        //getMethods:get all public methods including current class and its father class
        //getDeclaredMethod:get current class's all method including public, protected and private
        Method[] methods = cls.getMethods();

        for (Method method : methods) {
            System.out.println("method name is :" + method.getName());
        }

        System.out.println("=============================================");

        Method methodcall1 = cls.getDeclaredMethod("method2", int.class);


        //first parameter: the object the underlying method is invoked from
        //second parameter: the arguments used for the method call
        methodcall1.invoke(new Test(), 20);

        //parameter: the name of the field
        Field field = cls.getDeclaredField("s");

        //allows the object to access the field
        //irrespective of the access specifier used with the field
        field.setAccessible(true);

        // takes object and the new value to be assigned
        // to the field as arguments
        field.set(new Test("I can be used only by constructor"), "java");

        System.out.println("=============================================");

        Method methodcall2 = cls.getDeclaredMethod("method1");

        methodcall2.invoke(new Test("I can be used only by constructor when the method is invoked"));

        System.out.println("=============================================");

        Method methodcall3 = cls.getDeclaredMethod("method3");

        methodcall3.setAccessible(true);

        methodcall3.invoke(new Test());
    }
}


你可能感兴趣的:(java进击之路,java相关)