Javagenerics:generics仅定义为返回types
我正在寻找GWT的一些GXT代码,我碰到了generics的这种用法,我无法在Java教程中find另一个例子。 如果你想查看所有的代码,类名是com.extjs.gxt.ui.client.data.BaseModelData
。 这里是重要的部分:
private RpcMap map; public <X> X get(String property) { if (allowNestedValues && NestedModelUtil.isNestedProperty(property)) { return (X)NestedModelUtil.getNestedValue(this, property); } return map == null ? null : (X) map.get(property); }
X
在类中或层次结构中的任何地方都没有被定义,当我在eclipse中点击“去声明”时,它只是进入公共方法签名中的<X>
。
我试着用以下两个例子来调用这个方法来看看会发生什么:
public Date getExpiredate() { return get("expiredate"); } public String getSubject() { return get("subject"); }
他们编译并显示没有错误或警告。 我想至less我必须做一个演员才能使这个工作。
这是否意味着generics允许一个神奇的返回值,可以是任何东西,只会在运行时炸掉? 这与仿制药应该做什么似乎是相反的。 任何人都可以解释这个给我,也可能给我一个链接到一些文件,解释这个更好一点? 我已经阅读了Sun的23页关于generics的pdf,并且返回值的每个示例都是在类级别定义的,或者是在传入的参数之一中定义的。
该方法返回所期望的types( <X>
在方法中定义,并且是绝对无限的)。
这是非常非常危险的,因为没有规定返回types实际上匹配返回的值。
这样做的唯一好处是,您不必强制返回任何types的通用查找方法的返回值。
我会说:小心使用这样的构造,因为你几乎失去了所有的types安全性,只有在每次调用get()
时都不必写明确的types转换。
是的:这几乎是在运行时爆发的黑魔法,并打破了generics应该实现的整个想法。
types在方法中声明。 那就是“ <X>
”的意思。 该types的范围仅限于该方法,并且与特定的调用相关。 testing代码编译的原因是编译器试图确定types,只有在不能的时候才会报错。 有些情况下你必须明确。
例如, Collections.emptySet()
的声明是
public static final <T> Set<T> emptySet()
在这种情况下,编译器可以猜测:
Set<String> s = Collections.emptySet();
但如果不行,你必须input:
Collections.<String>emptySet();
我只是想找出一个GXT类相同的东西。 具体来说,我试图调用一个方法的签名:
class Model { public <X> X get(String property) { ... } }
从你的代码调用上述方法,并把它转换为一个string我做到以下几点:
public String myMethod(Data data) { Model model = new Model(data); return model.<String>get("status"); }
上面的代码将调用get方法,并告诉它返回的types应该返回为String。
如果这个方法和你在同一个类中,我发现我必须用“this”来调用它。 例如:
this.<String>get("status");
正如其他人所说,这是GXT团队相当sl and和危险。
BaseModelData在编译时引发未经检查的警告,因为它是不安全的。 像这样使用,你的代码将在运行时抛出一个ClassCastException,尽pipe它本身没有任何警告。
public String getExpireDate() { return get("expiredate"); }
有趣的是,从RpcMap(GXT API 1.2)
得到的标题:
public java.lang.Object get(java.lang.Object key)
在那里有一个通用的参数<X>
没有实际的效果,除了你不需要在所有的地方说“对象”。 我同意另一张海报,这是马虎,有点危险。
是的,这是危险的。 通常情况下,你会保护这样的代码:
<X> getProperty(String name, Class<X> clazz) { X foo = (X) whatever(name); assert clazz.isAssignableFrom(foo); return foo; } String getString(String name) { return getProperty(name, String.class); } int getInt(String name) { return getProperty(name, Integer.class); }