6
回答
java通过反射后获得的对象的类型确定问题
利用AWS快速构建适用于生产的无服务器应用程序,免费试用12个月>>>   
public Object before(Object object) { 
        System.out.println("Object"); 
        return null; 

    }

public Project before(Project p) {
        System.out.println("Project");
        return null;
    }

有如上的2个方法,目的就是同样的方法名根据传参的类型自动去调用不同的方法。而要传递进去的对象却是通过反射动态创建的,如下:

Class c =  Class.forName("com.domain.Project");
Object  obj=c.newInstance();
before(obj);

那问题来了,这样的话,它打印的总是"Object",就是说根本没有运行我希望的 before(Project p)这个方法,而是运行的 before(Object object)。那么现在我怎样让它运行我希望的方法呢?

当然大家也都看到,动态创建的obj确实是Project类型的,但貌似方法调用时是比对的“你认为的它的类型”来完成调用。那我现在就需要把它认为成:

Project  obj=(Project )c.newInstance();

可问题是,我不知道传入的字符串"com.domain.Project",当然也就无从知道我要强转到的具体类型是什么。现在我应该怎么做呢?

举报
sxgkwei
发帖于6年前 6回/6K+阅
共有6个答案 最后回答: 5年前
反射本来就不是通用方案,一般的做法是被反射的类实现某个接口,然后通过接口接收反射对象,强制转换类型来调用接口方法。

引用来自“xoHome”的答案

反射本来就不是通用方案,一般的做法是被反射的类实现某个接口,然后通过接口接收反射对象,强制转换类型来调用接口方法。
我懂你的意思,并且已经想到可以自己定义整个项目的BaseObject,并且定义待实现方法before,然后所有的pojo类都继承这个BaseObject,然后实现各自的before方法,通过反射获得对象时就认为它都是BaseObject,然后调用它的before方法即可。可是,pojo一般是作为和数据库表的映射而建立的,所以我不想破坏pojo的单纯性,所以想到在service层建立一个公共的处理,内部方法名相同,通过参数不同来做不同的处理,继而才有了如上的问题。
--- 共有 3 条评论 ---
xoHome回复 @sxgkwei : 你对POJO没有提供任何标识性的配置,仅仅靠反射是做不到你想要的效果的。要么,向框架一样,配置POJO,要么,自己写代理,性质和你这个差不多。 6年前 回复
sxgkwei回复 @xoHome : 我当前做法是在Object里面通过这样的核心语句做的:this.getClass().getDeclaredMethod("before",object.getClass()).invoke(this, object);也可以达到调用效果,就是觉得这样的方案不怎么理想,没有用到java本身提供的特性。 6年前 回复
xoHome那你可以遍历对象的所有Method方法,执行invoke调用。 这样你就得做进一步处理,在调用过程需要做个代理。 或者用另外一种办法,在POJO上做配置,根据配置信息来定位方法。 6年前 回复

如果你想要反射一个具体对象出来,参数就要改变不能再是string这种东西了,必须是某一个类型的Class对象,这样才可以直接发射出具体对象。Class<Project>class类是有泛型的,默认的就是object了。

通过配置文件的反射对象全部都是Object,这是配置文件这种反射的硬伤。虽然你自己可能知道他是那种类型,但是无法告诉虚拟机,所以虚拟机无法帮你完全方法重载的调用。

引用来自“Monkey”的答案

如果你想要反射一个具体对象出来,参数就要改变不能再是string这种东西了,必须是某一个类型的Class对象,这样才可以直接发射出具体对象。Class<Project>class类是有泛型的,默认的就是object了。

通过配置文件的反射对象全部都是Object,这是配置文件这种反射的硬伤。虽然你自己可能知道他是那种类型,但是无法告诉虚拟机,所以虚拟机无法帮你完全方法重载的调用。

没办法,是外部传入的string然后我把它翻译成对象,然后根据不同的对象做不同的事情。这个是改变不了的事实了,所以泛型于我没有一点用。所以只能像我上面写到的在Object的方法内在用反射机制自己查找方法并完成调用了。唉,如果Project.class可以得到一个Class对象,然后又个通过方法Project.class.XXX()来重新返回到Project这个东西(不知道这个叫啥- .-!)就好了。那样我最起码可以:

Class c = Class.forName("com.lecast.rule.domain.Project");

c=(Class<c.XXX()>)c;

c.XXX() obj=c.newInstance();

这样估计就没问题了。问题是,返回不到Project这个玩意儿,java没有这样的机制。

--- 共有 1 条评论 ---
MonkeyClass<String> classType = (Class<String>) Class.forName(" java.lang.String") 这样可以直接newInstace一个String出来的。关键就是使用配置文件泛型不明。 6年前 回复

很明显,你需要建立一个规则,需要把传入的string和对应的类型联系起来。可以使用xml配置文件。

获取对象后,你不知道类型,无法知道对象中的方法,所以,后面的方法调用,都用反射调用,那么,配置文件里面就需要写调用的方法,当然,你写方法时可以规定命名规则,那么,你写配置文件处理类的时候,你用通配符调用就方便了。具体可以跟我QQ联系,我可以把代码给你。QQ:761011857,邮箱:windyjack38@gmail.com

顶部