如何检查泛型类型是否在java中实现了特定类型的泛型接口?

如何检查泛型类型是否在java中实现了特定类型的泛型接口?,java,generics,collections,Java,Generics,Collections,可能重复: 我是Java泛型新手,来自.NET世界,我习惯于编写如下方法: public void genericMethod<T>(T genericObject) { if (genericObject is IList<String>) { //Do something... } } public void genericMethod(T genericObject) { if(genericObj

可能重复:

我是Java泛型新手,来自.NET世界,我习惯于编写如下方法:

public void genericMethod<T>(T genericObject)
{
    if (genericObject is IList<String>)
    {
        //Do something...
    }            
}
public void genericMethod(T genericObject)
{
if(genericObject为IList)
{
//做点什么。。。
}            
}
该方法接受泛型类型的对象,并检查该对象是否实现了泛型接口的特定版本
IList
,在本例中为
IList

现在,在Java中,我可以做到:

public <T> void genericMethod(T genericObject)
{
    if (genericObject instanceof Set<?>)
    {
       //Do something...
    }
}
public void genericMethod(T genericObject)
{
if(集合的genericObject实例)
{
//做点什么。。。
}
}
但是

Java不允许我执行
if(genericObject instanceof Set)

据我所知,由于类型擦除,通常在Java中,这将由类对象处理,我们将执行以下操作:

public <T> void genericMethod(T genericObject)
{
    Class<OurTestingType> testClass = OurTestingType.class;
    if (genericObject.getClass() == testClass)
    {
       //Do something...
    }
}
public void genericMethod(T genericObject)
{
Class testClass=OurTestingType.Class;
if(genericObject.getClass()==testClass)
{
//做点什么。。。
}
}
但由于我要检查的类型是泛型接口,因此无法执行以下操作:

Class testClass=Set.Class


那么,在Java中,我如何检查泛型对象是否实现了特定类型的
Set

Java实现了擦除,因此在运行时无法判断
generiobject
是否是
Set
的实例。保证这一点的唯一方法是对泛型使用边界,或者检查集合中的所有元素

编译时泛型边界 使用将在编译时检查的边界检查:

public <T extends SomeInterface> void genericMethod(Set<? extends T> tSet) {
    // Do something with tSet here
}
public void genericMethod(Set){
Set=(Set)t;
if(set.stream().allMatch(String.class:isInstance)){
Set strs=(Set)Set;
//在这里用str做点什么
}
}
}
Java 7及更高版本 对于Java 7及更早版本,我们需要使用迭代和类型检查:

public <T> void genericMethod(T t) {
    Set<String> strs = new HashSet<String>();
    Set<?> tAsSet;
    if (t instanceof Set<?>) {
        tAsSet = (Set<?>) t;
        for (Object obj : tAsSet) {
            if (obj instanceof String) {
                strs.add((String) obj);
            }
        }
        // Do something with strs here
    } else {
        // Throw an exception or log a warning or something.
    }
}
public-void-genericMethod(T){
Set strs=newhashset();
设置tAsSet;
if(集合的t实例){
tAsSet=(Set)t;
用于(对象对象对象:tAsSet){
if(字符串的obj实例){
标准添加((字符串)对象);
}
}
//在这里用str做点什么
}否则{
//抛出异常或记录警告或其他内容。
}
}
番石榴 根据Mark Peters在下面的评论,如果您可以将Guava添加到您的项目中,Guava也可以为您提供这样的方法:

public <T> void genericMethod(T t) {
    if (t instanceof Set<?>) {
        Set<?> set = (Set<?>) t;
        if (Iterables.all(set, Predicates.instanceOf(String.class))) {
            Set<String> strs = (Set<String>) set;
            // Do something with strs here
        }
    }
}
public-void-genericMethod(T){
if(集合的t实例){
Set=(Set)t;
if(Iterables.all(set,Predicates.instanceOf(String.class))){
Set strs=(Set)Set;
//在这里用str做点什么
}
}
}

语句,
Iterables.all(set,Predicates.instanceOf(String.class))
本质上与
set instanceOf set

相同,遗憾的是,Java中没有这个选项。在Java中,
列表
列表
之间没有运行时的区别。正是编译器确保您永远不会
整数添加到
列表
。即使编译器的强制执行并不严格,所以您也可以“合法地”使用未经检查的强制类型转换来执行这种讨厌的操作

总而言之,对于(几乎)任何运行时类型识别问题,您都必须了解它的实际情况:只是一个原始的
列表
。这就是所谓的类型擦除

也就是说,没有什么可以阻止您检查
列表中的内容,查看其类型:

public boolean isListOf(List<?> list, Class<?> c) {
    for (Object o : list) {
        if (!c.isInstance(o)) return false;
    }

    return true;
}
public boolean isListOf(列表,c类){
用于(对象o:列表){
如果(!c.isInstance(o))返回false;
}
返回true;
}
要使用此方法,请执行以下操作:

    // ...
    if (genericObject instanceof List<?>) {
        if (isListOf((List<?>) genericObject, String.class)) {
            @SuppressWarnings("unchecked")
            List<String> strings = (List<String>) genericObject;
        }
    }
/。。。
if(通用对象实例列表){
if(isListOf((列表)genericObject,String.class)){
@抑制警告(“未选中”)
列表字符串=(列表)genericObject;
}
}

一个有趣的观察结果是:如果
列表
为空,那么对于所有给定类型,该方法都返回true。实际上,空的
列表
和空的
列表
在运行时没有任何区别。

泛型是一种编译时功能,因此不能简单地获取运行时使用的特定泛型类型。您可以从内容或附加参数(例如,番石榴中的
Class tClass
)推断出它。您可以使用
Iterables.all(tAsSet,Predicates.instanceOf(String.Class))
检查
Iterable
是否只包含字符串。或者使用
Iterables.filter(tAsSet,String.class)
@MarkPeters-Guava总是有这样整洁的小方法,很好的发现。如果有一个没有实例的方法会很方便。。。我的例子是一个函数
funcname(T obj)
,我想对K类型做一些检查。因为Java 8不需要Guava来检查
集合是否只包含字符串:
Set.stream().allMatch((o)->o instanceof String)
@farsil:true!更好的是:
set.stream().allMatch(String.class::isInstance)
。我会更新我的答案。
    // ...
    if (genericObject instanceof List<?>) {
        if (isListOf((List<?>) genericObject, String.class)) {
            @SuppressWarnings("unchecked")
            List<String> strings = (List<String>) genericObject;
        }
    }