Java - 如何在编译时不知道结果类型的情况下返回变量类型对象?

时间:2016-09-15 22:54:10

标签: java generics interface

假设您有一个接口和两个实现该接口的类:

public interface IElement {
    boolean isDisplayed();
}

public class Button implements IElement  {
    @Override
    public boolean isDisplayed() {
        // checks if displayed
        return false;
    }

    public void click() {
        // clicks
    }
}

public class Textbox implements IElement  {
    @Override
    public boolean isDisplayed() {
        // checks if displayed
        return false;
    }

    public void enterText(String text) {
        // enters text
    }
}

在一个完全独立的类中,我们有一个方法,它想要返回一个Button或一个Textbox,具体取决于提供的参数的值。像这样的东西:

public class WhichElement {

    public <T extends IElement> T getElement(String elementName) {

        if (elementName.equalsIgnoreCase("button")) {
            return new Button();
        }
        else if (elementName.equalsIgnoreCase("textbox")) {
            return new Textbox();
        }
    }
}

然而,由于返回的对象不是类型T,因此失败。 我试过像这样返回界面:

public IElement getElement(String elementName)

但是我不能做我真正想做的事情,这就是:

WhichElement picker = new WhichElement();
picker.getElement("button").click();  <-- errors here because it's an IElement not a Button :(

我可以将它强制转换为正确的对象,并相信该方法可以返回相同的方法,但是这似乎很危险。我更倾向于确定所需对象的类型并直接返回该对象。 有没有办法做我正在尝试的事情?

2 个答案:

答案 0 :(得分:3)

您可以在返回之前将getElement()的结果转换为T,这将产生编译器警告。

警告是存在的,因为编译器将在调用站点插入一个强制转换,如果运行时结果不是正确的类型,将从没有的位置抛出ClassCastException。明显的演员。基本上,如果getElement()不是通用的,编译器会生成您编写的相同代码,并且只返回IElement

不是使用一种工厂方法来生成多种类型,而是为每种类型创建不同的工厂方法。这将为您提供类型安全性,确保实际提供应用程序所需的每个元素,帮助重构,并将getElement("buttton")等运行时错误更改为编译时错误。

依赖注入是另一种方法:给应用程序一个按钮,而不是找到一个按钮。

答案 1 :(得分:0)

有两种方法。

public Button getButton() {
    return new Button();
}

public Textbox getTextbox() {
    return new Textbox();
}

在语义和代码方面没有太大区别

picker.getButton()          // Strongly typed
picker.getElement("button") // Stringly typed

另外,stringly typed版本更长。