
该方法如何推断类型
<T>
没有。泛型方法不推断其泛型类型-这就是为什么
T称为 类型参数 的原因。方法的 调用者 提供的类型参数
T。如果这样做,编译器 可能
会根据方法调用的参数和目标类型的上下文来推断出它。
例如:
Set<String> c = Collections.emptySet();
emptySet声明类型参数
T,不带参数,并返回
Set<T>。在此,编译器推断
T是
String基于目标类型
Set<String>。
另一个例子:
Collections.singleton("asdf");singleton声明一个类型参数
T,使用
T,然后返回
Set<T>。在这里,没有目标类型,但是编译器推断
T是
String基于参数
"asdf"。
但是泛型类型推断只是一种方便。没有它,我们仍然可以使用 类型见证 来显式提供类型参数:
Set<String> c = Collections.<String>emptySet();Collections.<String>singleton("asdf");这将我们带到您的方法签名:
public <T> void fromJsonArray(String jsonString, Type tToken)
fromJsonArray声明类型参数
T,但不返回与类型相关的任何东西
T或接受与类型有关的参数
T。在调用时
fromJsonArray,编译器没有从中进行推断的信息
T。
Object除非使用类型见证,否则其类型参数将默认为其上限。
myObj.<String>fromJsonArray(jsonString, tToken);
但这没关系,因为
<String>对方法调用或其编译的行为没有影响。
T是没有意义的*,可以从的声明中删除
fromJsonArray。
编译器如何将
fromJson方法返回的值分配给list未指定类型i 的变量?
这是来源
Gson.fromJson(String,Type):
@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;}您可以看到它声明了一个任意类型的参数
T,并将反序列化的对象强制转换为
T。这称为 未检查的强制转换
,因为如果出错,它不会快速失败。那是因为在运行时
T已被擦除。您可以看到代码抑制了这样做的警告,因为通常这是一个坏主意。通过不限制
T基于方法参数的内容,Gson代码已有效地将其控制权转让给了调用者。如果您写:
List<String> list = g.fromJson(jsonString, tToken);
但用
tToken表示
HashSet<String>,您将
ClassCastException在运行时在该行上得到一个。更糟糕的是,如果
tToken表示的话
ArrayList<Integer>,它甚至不会在那条线上失败,因为JVM只会看到
List并允许分配发生。
ClassCastException一旦您的代码尝试将列表的
Integer元素处理为
Strings
,便会在以后的某个时间抛出A (并且此异常会导致调试混乱)。
因此,要回答有关分配的问题,编译器可让您将结果分配给所需的
fromJson任何对象。正确无误取决于您。
您可能会问, 为什么Gson会进行未经检查的强制转换并允许使用不安全的代码? 答案是由于语言限制,这很方便。他们的其他签名更安全:
public <T> T fromJson(String json, Class<T> classOfT)
但是没有办法用
Class-
来表示通用类型
List<String>.class。只有一个
Type可以做到这一点,它本身并不是通用的。
fromJson可能需要一个
TypeToken<T>,但是还有其他方法可以获取
Type,因此这是限制性的。
返回
Object并强制调用者进行未经检查的强制转换会更加透明,但是Gson开发人员可能希望避免这种“丑陋”。
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)