Java中的反射

来源:互联网 发布:寂寞聊天软件 编辑:程序博客网 时间:2024/06/07 05:42

整理了一下之前学习时候的一点笔记。如有错误欢迎指正,不喜勿喷。

关于反射,我们想要在了解它之前我们先得知道它是什么意思:
有反就正,我们知道先有一个类然后有一个对象,就像:

Date date=new date();

然后才能调用date对象调用相关的方法。
那么“反”是什么意思呢?
在这之前先介绍一下Class类,这个类在Java.lang.Class中,这个类是反射的源头。

package snippet;import java.util.Date;public class demo {    public static void main(String[] args) {        Date date=new Date();        Class<?>cls=date.getClass();        System.out.println(cls);    }}

我们能从文档中查询到getClass的返回值是Object,所以任意的对象都能调用这个方法,一个 实例对象通过调用这个方法可以返回创建这个对象的类名。
以上代码控制台输出:

class java.util.Date

我们再来看一个范例:

package snippet;public class deni {    public static void main(String[] args) throws ClassNotFoundException {        Class<?> cls=Class.forName("java.util.Date");        System.out.println(cls);    }}

这个控制台输出和上面的一样输出:

class java.util.Date

但是这里不用再导包了,只需要你使用Class.forName("java.util.Date");这个方法就可以得到这个类。

然后我们可以使用newInstance()方法来创建一个实例。

package snippet;import java.util.Date;public class deni {    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {        Class<?> cls=Class.forName("java.util.Date");            Date date=(Date)cls.newInstance();            System.out.println(date);    }}

控制台输出为当前的时间。
为什么不用new关键字直接创建实例而要使用两行代码去获得一个实例呢?
这又涉及到解耦的问题了。接下来我们以一个例子来看看使用反射是否在解耦方面优于一般的方法。

package snippet;interface fruit{public void eat();}class apple implements fruit{    public void eat(){        System.out.println("eat apple");   }}class orange implements fruit{   public void eat(){        System.out.println("eat orange");    }   }class factory{    public static fruit getInstance(String className){        if("apple".equals(className))            return new apple();        else if("orange".equals(className))            return new orange();        else return null;    }}public class student {    public static void main(String[] args) {        fruit f=factory.getInstance("apple");        f.eat();    }}

这是一个简单的工厂设计模式,如果我们需要创建更多的实例,就要在factory中实例化一个类,这样如果频繁有实例增加那么我们就要不断修改factory工厂类。所以我们要来修改一下这个代码:

package snippet;interface Fruit{public void eat();}class apple implements Fruit{    public void eat(){        System.out.println("eat apple");   }}class orange implements Fruit{   public void eat(){        System.out.println("eat orange");    }   }class factory{    public static Fruit getInstance(String  className) {        Fruit fruit=null;            try {                fruit = (Fruit)Class.forName(className).newInstance();            } catch (Exception e) {}            return fruit;        }   }public class student {    public static void main(String[] args){        Fruit f=factory.getInstance("snippet.apple");        f.eat();    }}

这样无论增加多少实例也不同更改工厂类,只需要增加“水果类”,更改调用时的参数就好了。

原创粉丝点击