java反射机制与具体使用方法

一、认识反射机制
答:java是一门是动态的语言,可以适应于变化的环境,比如,Java中的类是根据需要载入的。反射机制就是java“动态性”的重要体现,是java的一个重要特点,主要用于JavaEE的框架之中。它允许在运行状态中,通过某一具体的类,便可以得知该类的所有属性和方法,通过仁义类的实例,便可以调用它的任意方法和属性。
二、实例化Class对象
答:先简单认识一下反射:在正常情况下,程序中类的实例是在类已经定义好的基础上生成的,但是在反射机制中, 可以打破这一概念。反射中所谓的“反”就是可以通过实例找到该实例的出处。
我们知道,java中所有的类都是Object类的子类,而在Object类中有一个名为getClass()的方法,利用这个方法就可以获得一个实例的所属类,该方法定义如下:public final Class<?> getClass()。
例1、 Date myDate=new Date();
System.out.println(myDate.getClass());
以上代码将会输出
:class java.util.Date 即myDate的所属类的全类名,此时就可以通过反射机制中的方法去访问其全部信息(包括函数和字段)
在java.lang包下有一个反射的源头类,名为Class,Class 类的实例表示正在运行的 Java 应用程序中的类和接口。该类有三种实例化方法,
一是上面介绍的getClass()方法,该方法是通过实例调用的。

        Date myDate=new Date();
        Class<?>class1=myDate.getClass();

二是通过类名称的class属性取得,在框架中(hibernate、mybatis、spring)经常使用,比如

  Class<?>class1=Date.class;

三是通过Class类的一个名为forName(String fullname)可以获得,和上面两种方法相比,该方法无需导入需要的包,String类型的参数是类的全路径名称。

    Class<?>class1=Class.forName("java.util.Date");

三、反射实例化对象
在正常情况下,我们可以根据已有的类,然后new出其实例,但是反射机制支持一种别样的生成实例的方法。在java.lang.Class类中有一个newInstance()方法,通过该方法可以创建此 Class 对象所表示的类的一个新实例,比如:

package com.andy.temp;

class Cat{
    public Cat() {
       System.out.println("-----这是无参构造函数-----------");
    }
    @Override
    public String toString() {      
        return "this is a cat";
    }
}

public class Temp {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {

        Class<?>class1=Class.forName("com.andy.temp.Cat");
        Object cat=class1.newInstance();//相当于正常情况下的new,会调用构造函数
        System.out.println(class1);//输出“class com.andy.temp.Cat”
        System.out.println(cat);//调用toString方法
    }

}

程序的输出结果如下:
—–这是无参构造函数———–
class com.andy.temp.Cat
this is a cat

读到这里,是不是会感觉反射的做法比较多余,明明可以用一个new可以解决的问题为什么要写两行代码来取代呢?这是因为在开发中,new是造成耦合的主要元凶。具体例子如下:
让我们回忆一下工厂模式中的简单工厂(静态工厂),代码如下:

package com.andy.test;
interface  Fruit{
    public void eat() ; 
}
class Apple implements Fruit{

    @Override
    public void eat() {
        System.out.println("eat apples");       
    }   
}
class Orange implements Fruit{

    @Override
    public void eat() {
        System.out.println("eat oranges");      
    }   
}
class MyFactory {
    public static Fruit getInstance(String calssName) {
        if ("apple".equals(calssName)) {
             return new Apple();
        }
        else if ("orange".equals(calssName)) {
             return new Orange();
        }
        else
           return null;     
    }
}
public class Factory {
  public static void main(String[] args) {
    Fruit fruit=MyFactory.getInstance("apple");
    fruit.eat();
}
}

简单工厂有很多局限,每增加一个类就要修改工厂类,那么如果随时都有可能增加新的类,工厂类也会一直进行更改。以上都是通过new进行实例化的,而new就成了问题的关键点。现在通过反射来弥补以上bug。

package com.andy.test;
interface  Fruit{
    public void eat() ; 
}
class Apple implements Fruit{

    @Override
    public void eat() {
        System.out.println("eat apples");       
    }   
}
class Orange implements Fruit{

    @Override
    public void eat() {
        System.out.println("eat oranges");      
    }   
}
class MyFactory {
    public static Fruit getInstance(String calssName) {
        Fruit fruit=null;
        try {
            fruit =(Fruit)Class.forName(calssName).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fruit;
    }
}
public class Factory {
  public static void main(String[] args) {
    Fruit fruit=MyFactory.getInstance("com.andy.test.Orange");
    fruit.eat();
}
}

主要修改了MyFactory类,使其使用反射机制根据传入的参数动态的生成实例,此时增加类时,就不需要再更改MyFactory类了,注意在主函数调用时,传入的是全类名。

下一篇:《用反射机制调用构造函数》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值