Java对象返回类型与泛型方法
我看到了几个关于泛型返回类型的问题,但没有一个回答我的问题。Java对象返回类型与泛型方法,java,generics,Java,Generics,我看到了几个关于泛型返回类型的问题,但没有一个回答我的问题。 如果任何参数都没有绑定,例如中的以下方法: 但是我真的看不出有什么不同…我不想去的主要原因是什么 JsonPath.<Boolean>read(currentRule, "$.logged") 两者在功能上没有什么不同。字节码可能是相同的 核心区别在于,一个使用cast,而另一个使用泛型 如果有任何替代机制,我通常会尽量避免使用强制转换,因为通用形式是一种非常有效的替代方式,所以我会选择它 // The right wa
如果任何参数都没有绑定,例如中的以下方法:
但是我真的看不出有什么不同…我不想去的主要原因是什么
JsonPath.<Boolean>read(currentRule, "$.logged")
两者在功能上没有什么不同。字节码可能是相同的 核心区别在于,一个使用cast,而另一个使用泛型 如果有任何替代机制,我通常会尽量避免使用强制转换,因为通用形式是一种非常有效的替代方式,所以我会选择它
// The right way.
JsonPath.<Boolean>read(currentRule, "$.logged");
//正确的方法。
JsonPath.read(currentRule,“$.logged”);
有一个从未设置过的类型参数(当调用JsonPath.read(currentRule,“$.logged”)
时),实际上会使编译器完全忽略方法中的所有泛型信息,并将所有类型参数替换为:
,如果类型参数没有上限。(就像你的情况一样)对象
,如果类型参数像U
一样有界。例如,如果您将一个
作为类型参数,并通过调用
忽略它,那么编译器将用JsonPath.read(…)
替换该类型参数数字
(boolean)JsonPath.read(…)
),类型参数将替换为对象
。然后,通过首先返回一个boolean
(可能),然后将此包装自动取消装箱为boolean
,将此类型安全地转换为boolean
。这根本不安全。事实上,每一个强制转换都是不安全的——你可以告诉编译器:“我知道这种类型在运行时是什么,所以请相信我,让我将它强制转换为与之兼容的其他类型。”。你卑微的仆人,编译器,允许这样做,但如果你错了,那是不安全的
你的方法还有一点。类型参数从未在方法体或参数中使用-这使得它非常冗余。因为通过对boolean
进行强制转换,您坚持要知道new JsonReader().parse(json).read(jsonPath,filters)的返回类型
,那么您只需将返回类型设置为boolean
(或boolean
):
泛型通过编译器在代码中插入不可见的强制转换来工作 例如,在将泛型添加到语言之前,您必须这样做
List list = new ArrayList();
list.add("Foo");
list.add("Bar");
String str0 = (String) list.get(0);
String str1 = (String) list.get(1);
这很烦人。因为get()
返回了Object
,所以每次想从列表中获取字符串时都必须强制转换
现在,List
是通用的,get()
返回T
,所以您可以这样做
List<String> list = new ArrayList<>();
list.add("Foo");
list.add("Bar");
String str0 = list.get(0);
String str1 = list.get(1);
或者它返回对象
,而您确实这样做了
Boolean a = JsonPath.<Boolean>read(currentRule, "$.logged");
Boolean a = (Boolean) JsonPath.read(currentRule, "$.logged");
两个版本都可能在运行时抛出一个ClassCastException
,因此我认为最好是强制执行cast,这样至少你会意识到你正在做一些可能失败的事情
我认为,如果方法参数没有,则返回类型的泛型方法涉及类型参数<代码> t>代码>的不良做法,除非返回的对象不能以破坏类型安全的方式使用。比如说,
public static <T> List<T> emptyList()
公共静态列表emptyList()
在集合中
正常(列表为空,因此不能包含错误类型的元素)
在你的例子中,我认为read
方法不应该是泛型的,应该在类型擦除后返回Object
,我不认为有什么区别。方法体中表面上没有使用类型变量t
。JsonPath.read(currentRule,$.logged)
如何安全地返回一个Boolean
,而JsonPath.read(currentRule,$.logged)
如何安全地返回一个String
?您是否愿意将强制转换更改为Boolean
,以避免将自动装箱拖入问题?实际上,我看不出泛型在这里有什么优势。如前所述,T从未被使用。@JFMeier主要的缺点是未经检查的强制转换隐藏在方法中,而不是当着你的面告诉你你正在做一些类型不确定的事情。那么你实际上是在说,该方法最好返回一个对象
,而不是泛型,因为施法是可入侵的?@Nati-yes。正如我在上面所评论的,除了执行未经检查的强制转换之外,您实际上没有使用t
。按照方法的声明方式,他可以这样做:String value=JsonPath.read(currentRule,“$.logged”)代码>无论您是否提供显式类型见证,它都将以任何方式在内部执行未经检查的强制转换。这不是我的代码,我只是想知道使用它的最佳方式是什么。无论您是否提供,我希望我能有所帮助。干杯:)我的意思是-这是我使用的一个依赖项,一个第三方代码。你会自己投还是作为泛型通过?我会设置
。我的想法完全正确。我认为它看起来更干净,尽管JayWay内部确实对(T)…@Nati进行了强制转换-它们都进行了运行时强制转换,因此在功能上没有区别。read
方法是我正在使用的第三方库。如果你在我的位置,你会怎么用它?您可以自己强制转换,也可以在内部强制转换,并捕获ClassCastException
?@Nati我会使用doBoolean a=JsonPath.read
或Boolean a=JsonPath.read
,并在代码中留下注释,说明//警告:此方法涉及不安全的强制转换
。这个建议与AndyTurner的(留下评论并使用@SuppressWarnings(“unchecked”)
)几乎相同,只是实际上没有对Suppress的警告。从我到目前为止看到的情况来看,没有太大的区别,如果有的话。Invable中的unchecked casting,所以它几乎是一个样式化的iss
public static Boolean read(String json, String jsonPath, Filter... filters) {
return new JsonReader().parse(json).read(jsonPath, filters);
}
List list = new ArrayList();
list.add("Foo");
list.add("Bar");
String str0 = (String) list.get(0);
String str1 = (String) list.get(1);
List<String> list = new ArrayList<>();
list.add("Foo");
list.add("Bar");
String str0 = list.get(0);
String str1 = list.get(1);
Boolean a = JsonPath.<Boolean>read(currentRule, "$.logged");
Boolean a = (Boolean) JsonPath.read(currentRule, "$.logged");
public static <T> List<T> emptyList()