JAVA反射机制

  最近学习的内容,怎么都是离不开反射,可一直对反射的理解一知半解的,不够系统。今天认真地学习了一下反射,下面做个总结。


反射是用来做什么的

  java程序中的许多对象在运行时都会出现两种类型:编译是类型和运行时类型,例如代码:Person p = new Student();这行代码将会生成一个p变量,该变量的编译时类型为Person,运行时类型为Student;除此之外,还有更极端的情形,程序在运行时接收到外部传入的一个对象,该对象的编译时类型为Object,但程序又需要调用该对象运行时类型的方法。那么,这些问题怎么解决呢?

  编译时无法预知该对象和类可能属于哪些类,但程序可以依靠运行时的信息来发现该对象和类的真实信息,然后使用反射来解决。


反射的核心

  先来理解一下Class对象。我们都知道,类是某一类对象的抽象,类是概念层次的东西。但不知道有没有想过,类也是一种对象。就像我们说概念主要用于定义、描述其他事物,但概念本身也是一种事物,那么概念本身也需要被描述——这有点像一个哲学命题。但是事实就是这样,每个类是一批具有相同特征的对象的抽象,而系统中所有的类实际上也是实例,他们都是java.lang.Class的实例。

  当类被加载后,系统就会为给类生成一个对应的Class对象。通过该Class对象就可以访问到JVM中的这个类。在java程序中获得Class对象通常有三种方式。使用Class类的forName(String clazzName)静态方法。该方法需要传入字符串参数,该字符串参数的值是某个类的全限定类名。

  调用某个类的class属性来获取该类对应的Class对象。

  调用某个对象的getClass()方法。该方法是java.lang.Object类中的一个方法,所以所有的java对象都可以调用该方法,该方法返回该对象所属类对应的Class对象。

  我们获得了Class对象,调用该对象的一系列方法就可以获得运行时需要的信息,从而解决问题。


反射的优缺点

  优点:可以实现动态创建对象和编译,体现出很大的灵活性。

  缺点:对性能有影响。尽管反射非常强大,但也不能滥用。


反射的基本使用

  首先是基础代码,我们定义一个接口及其实现,作为我们反射操作的目标:

interface HelloWorldService
{
    void sayHello(String name);
}

class MyHelloWorld implements HelloWorldService
{
    public String name;
    
    
    public void sayHello(String name)
    {
        System.out.println("Hello " + name + ".");
    }

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

    public String getName() {
        return name;
    }
}

 实例化对象:

private static void createInstanceTest() throws ClassNotFoundException, InstantiationException, IllegalAccessException
{
    Class classType = Class.forName("sample.reflection.MyHelloWorld");
    MyHelloWorld hello = (MyHelloWorld)classType.newInstance();
    hello.sayHello("Zhang San");
}

 获取方法及字段信息:

private static void printClassTypeInfo(String type) throws ClassNotFoundException
{
    Class classType = Class.forName(type);
    Method[] methods = classType.getDeclaredMethods();
    System.out.println("Methods info as below:");
    for(Method method : methods)
    {
        System.out.println(method.toGenericString());
    }
    Field[] fields = classType.getFields();
    System.out.println("Fields info as below:");
    for (Field field : fields)
    {
        System.out.println(field.toGenericString());
    }
}
 调用对象的方法:

private static void invokeMethodTest() throws InstantiationException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalArgumentException, InvocationTargetException
{
    Class classType = Class.forName("sample.reflection.MyHelloWorld");
    MyHelloWorld hello = (MyHelloWorld)classType.newInstance();
    Method method = classType.getMethod("sayHello", new Class[]{String.class});
    method.invoke(hello, new Object[]{"Zhang San"});
}


总结:这里最好结合前面博客JDK动态代理一并理解。这是反射的基础知识总结,随着不断的实践会有更多的理解。


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值