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
-no
List.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)