基础对象的工厂和基于字符串的继承对象,而不使用java中的强制转换

时间:2012-11-09 08:27:53

标签: java reflection

假设我们有:

abstract class Item {   public Item(){}}
abstract class ExtraItem extends Item {  public ExtraItem(){}}
class A extends Item{ public A(){}}
class B extends Item{ public B(){}}
class C extends Item{ public C(){}}
class EA extends ExtraItem{ public A(){}}
class EB extends ExtraItem{ public B(){}}
class EC extends ExtraItem{ public C(){}}

我想写这样的工厂类但没有强制转换:

   class Factory {

       Item createItem(String className){
                Class clazz = Class.forName(className);
                return (Item) clazz.newInstance(); //I don't want here cast to Item    
    }
    ExtraItem createExtraItem(String className){
               Class<? extends ExtraItem> clazz = (Class<? extends ExtraItem>)   Class.forName(className); // I don't want here cast to Extraitem
                return clazz.newInstance();
        }
    }

我尝试按上面的方式编写(当然还有演员):

@SuppressWarnings("unchecked")
public static <T extends Item> T createItem(String protocolType) {
    try {
        String className = protocolType;
        Class<?> clazz = Class.forName(className);                        
        return (T) clazz.newInstance();
    } catch (Exception e) {
        Log.e("ItemFactory", "Lack key \"" + protocolType + "\" in map: " + e.getLocalizedMessage());
    }
    return null;
}

但是如何在这里使用Class.cast()方法?这是一个更好的方法吗?

3 个答案:

答案 0 :(得分:1)

如果您只是不喜欢编译器警告,那么您可以使用Class.asSubclass为您进行检查:

Class<? extends Item> clazz = Class.forName(className).asSubclass(Item.class);

ExtraItem的原则相同。如果命名的类实际上不是ClassCastException的子类,则会在运行时抛出Item

答案 1 :(得分:0)

在string中传递className时,无法避免强制转换。由于您没有类型,我将创建Class<?>,而newInstance()会生成Object

如果您不想强制转换,则应传递要创建实例的类的Class实例。

除了演员是正常的操作,所以避免它没有太大的意义。请记住,大多数代码都可以在您编程工作时运行。如果您确定传递的字符串可以创建继承Item的类,那么您可以投射而不会产生任何意外后果。

答案 2 :(得分:0)

如果您不想将演员签名更改为:

class Factory {
    <T extends Item> T createItem(Class<T> itemClass) {
        try {
            return itemClass.newInstance();
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    <T extends ExtraItem> T createExtraItem(Class<T> itemClass) {
        return createItem(item);
    }
}