Java 该方法如何推断<;T>;
下面的方法可以完美地工作Java 该方法如何推断<;T>;,java,generics,gson,Java,Generics,Gson,下面的方法可以完美地工作 public <T> void fromJsonArray(String jsonString,Type tToken) { Gson g = new Gson(); T list = g.fromJson(jsonString,tToken); System.out.println(list); } 再次修改源代码并对其进行测试,结果导致编译时错误 public <T> List<T> getT(T s) { Li
public <T> void fromJsonArray(String jsonString,Type tToken) {
Gson g = new Gson();
T list = g.fromJson(jsonString,tToken);
System.out.println(list);
}
再次修改源代码并对其进行测试,结果导致编译时错误
public <T> List<T> getT(T s) {
List<T> list = new ArrayList<T>();
list.add(s);
return list;
}
public <T> void test(){
T list = getT("test"); //incompatible types compilation error here
System.out.println(list);
}
公共列表getT(ts){
列表=新的ArrayList();
列表。添加(s);
退货清单;
}
公开无效测试(){
T list=getT(“test”);//此处存在不兼容的类型编译错误
系统输出打印项次(列表);
}
Sample1.java:13:错误:不兼容的类型
T list=getT(“测试”);
^
必填项:T
找到:列表
其中T是一个类型变量:
T扩展方法测试()中声明的对象
它是从g.fromJson()的返回类型推断出来的。
该方法如何推断
没有。泛型方法不会推断它们的泛型类型-这就是为什么t
被称为类型参数的原因。方法的调用方为T
提供类型参数。当它这样做时,编译器可能会根据方法调用的参数和目标类型的上下文来推断它
例如:
Set<String> c = Collections.emptySet();
Collections.singleton("asdf");
singleton
声明一个类型参数T
,获取一个T
,并返回一个Set
。这里没有目标类型,但是编译器根据参数“asdf”
推断T
为String
但是泛型类型推断只是一种方便。没有它,我们仍然可以使用类型见证来显式提供类型参数:
Set<String> c = Collections.<String>emptySet();
Collections.<String>singleton("asdf");
但这并不重要,因为
对方法调用或其编译的行为没有影响T
没有意义,可以从jsonarray的声明中删除
编译器如何将fromJson
方法返回的值分配给变量list
,我尚未指定该变量的类型?
以下是数据来源:
但是tToken
表示HashSet
,在运行时,您将在该行上得到一个ClassCastException
。更糟糕的是,如果用tToken
表示ArrayList
,它甚至不会在该行失败,因为JVM只会看到列表
,并允许分配发生。当您的代码试图将列表中的Integer
元素处理为String
s时,稍后会抛出ClassCastException
(该异常会使调试混淆)
因此,为了回答您关于赋值的问题,编译器允许您将fromJson
的结果赋值给您想要的任何内容。正确与否取决于你
您可能会问,为什么Gson会执行未经检查的强制转换并允许使用不安全的代码?答案是这是一种方便,源于语言限制。他们的另一个签名更安全:
public <T> T fromJson(String json, Class<T> classOfT)
public T fromJson(字符串json,类ClassSoft)
但是没有办法用Class
-noList.Class
来表示泛型类型。只有类型
可以做到这一点,而且它本身不是泛型的<来自JSON的code>fromJson
可能需要TypeToken
,但是还有其他方法可以获得类型,因此这是有限制的
返回Object
并强制调用方执行未经检查的强制转换将更加透明,但Gson开发人员可能希望避免这种“丑陋”。可能它将变量内联,因为它在这里没有用处。类型变量可以是您指定的任何非基本类型:任何类类型,任何接口类型,任何数组类型。这是一个很好的问题。我不明白如何从这些论点中推断出来<代码>类型
是一个非通用接口,目前没有任何方法。我想知道编译器是否能够根据返回类型进行推断。类型推断的JLS很难理解。“我个人不知道答案。”黑豹说。好的,您如何调用该方法fromJsonArray
?@RohitJain因为它是空的,我想知道他们调用它时是否没有类型参数(然后最终为完整调用推断对象…)。我已经尝试过了,但我想不是这样的。。。请看我的编辑。。感谢您的回复:)g.fromJson的返回类型是从方法参数“tToken”(type)推断出来的@Ritesh:我知道方法fromJson
的返回类型是从type参数推断出来的,我想知道的是,在我的方法中,这种推断如何帮助推断T
的类型?我不确定我是否得到了它。根据定义,泛型方法使用类型参数来表示一个或多个参数的类型和/或其返回类型之间的依赖关系。如果你看到fromJson的签名,你会发现它使用类型参数来表示它的参数(typeOfT)决定返回类型T。你的fromJsonArray方法也是一个泛型方法——它的第二个参数是typeOfT,它的签名表示返回类型是同一类型。当然是这样。仅仅因为您无法编译自己的错误示例,这证明不了什么。fromJson()方法进行编译。在代码之后,我看到TypeSoft被转换为类。代码在TypeUtils类中。@Ritesh您介意链接到该类吗?我没看到。@Ritesh抱歉,我只是想理解你所说的“进一步跟踪代码”是什么意思-什么是调用层次结构链接toRawClass
返回到fromJson
?我只是在你添加的链接上浏览(或单击)了源代码,找到了引用。我不熟悉Gson,但总体而言(从javadocs和诸如TypeToken、JsonDeserializationContext、JsonDeserializationVisitor、ParameterizedTypeHandlerMap和ParameterizedTypeImpl之类的类来看),似乎有大量代码为任何参数化类型(除了简单的类之外)提供特性这不是一种类型推断。新的
Set<String> c = Collections.<String>emptySet();
Collections.<String>singleton("asdf");
public <T> void fromJsonArray(String jsonString, Type tToken)
myObj.<String>fromJsonArray(jsonString, tToken);
@SuppressWarnings("unchecked")
public <T> T fromJson(String json, Type typeOfT) throws JsonParseException {
StringReader reader = new StringReader(json);
T target = (T) fromJson(reader, typeOfT);
return target;
}
List<String> list = g.fromJson(jsonString, tToken);
public <T> T fromJson(String json, Class<T> classOfT)