基于Class参数在函数中创建对象

时间:2018-01-26 12:47:16

标签: java design-patterns

我想定义一个创建不同类型对象的函数,这些对象共享相同的基类。我想传入对象类型并使用函数创建对象,然后修改其属性。问题是创建所有这些对象的主类没有对象的属性,因此代码无法编译。

示例:

public void new_generic_report(Class report_class, String report_name) {

    Report new_report = this.reportManager.createReport(report_class);
    new_report.set_name(report_name);

}

调用new_generic_report(GreenReport.class, "green_report");失败,因为new_report属于Report类而不是GreenReport,因此它没有.set_name方法。

我知道我可以在主要的Report类中实现.set_name方法(以及其他常用方法),但我正在编写代码来与我无法修改的API进行交互。

2 个答案:

答案 0 :(得分:1)

如果您确定createReport返回正确类的实例,则可以执行强制转换:

((SpecialClass)new_report).set_name(report_name);

另一种方法是使用反射:

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

public class Test {
    static class Base {};
    static class Child extends Base {
        public void setName(final String name) {
            System.out.println("setName("+name+")");
        }
    }


    public static void main(String[] args) {
        new Test().new_generic_report(Child.class, "Testname");
    }


    public void new_generic_report(final Class clazz, final String name) {
        Base base = createBase(clazz);

        try {
            Method m = clazz.getMethod("setName", String.class);
            m.invoke(base, name);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    private Base createBase(Class report_class) {
        return new Child();
    }
}

当然,只有返回的实例实现了方法,这才有效。

答案 1 :(得分:1)

为您的报告创建一个父类:

public abstract class NamedReport extends Report
{
    public abstract void setName(String name);
}


class GreenReport extends NamedReport {

    @Override
    public void setName(String name) {

    } 
}

然后只需在您的方法中投射您的课程:

public void new_generic_report(Class report_class, String report_name) {

    Report new_report = this.reportManager.createReport(report_class);
    if (new_report  instanceof NamedReport)
    {
        ((NamedReport)new_report).set_name(report_name);
    }
}