当前位置: 首页 > 面试题库 >

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

勾炳
2023-03-14
问题内容

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

public void genericMethod<T>(T genericObject)
{
    if (genericObject is IList<String>)
    {
        //Do something...
    }            
}

该方法接受通用类型的对象,并检查该对象是否实现通用接口的 特定 版本IList<>,在这种情况下为IList<String>

现在,在Java中,我可以执行以下操作:

public <T> void genericMethod(T genericObject)
{
    if (genericObject instanceof Set<?>)
    {
       //Do something...
    }
}

Java并 没有 让我做if (genericObject instanceof Set<String>)

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

public <T> void genericMethod(T genericObject)
{
    Class<OurTestingType> testClass = OurTestingType.class;
    if (genericObject.getClass() == testClass)
    {
       //Do something...
    }
}

但是由于我要检查的类型是通用接口,所以您不能这样做:

Class<Set<String>> testClass = Set<String>.class

那么,如何在Java中检查通用对象是否实现的特定类型Set<String>


问题答案:

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

编译时通用界限

使用边界检查,它将在编译时检查:

public <T extends SomeInterface> void genericMethod(Set<? extends T> tSet) {
    // Do something with tSet here
}

Java 8

我们可以使用Java 8中的流在一行中本地完成此操作:

public <T> void genericMethod(T t) {
    if (t instanceof Set<?>) {
        Set<?> set = (Set<?>) t;
        if (set.stream().allMatch(String.class:isInstance)) {
            Set<String> strs = (Set<String>) set;
            // Do something with strs here
        }
    }
}

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.
    }
}

番石榴

根据下面的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
        }
    }
}

该语句Iterables.all(set, Predicates.instanceOf(String.class))本质上与相同setinstanceof Set<String>



 类似资料:
  • 问题内容: 所以我在Java中有这个课程: 在这个类中,我想知道T是否实现某些接口。 以下代码不起作用,但这是我要完成的工作的主意: 所以我想检查传递给Foo 的类是否具有其签名。 可能吗?怎么样? 问题答案: 奇怪的是,泛型也用于接口。1您将要使用: 这实际上是实现的要求, 而不是true / false check 。 为了进行真/假检查,请使用无限制的generics()并确保获得a,以便您

  • 编译时,此代码将产生以下+错误: 问题是访问中的类型T与列表中的T不相同。如何修复此编译问题?

  • 我试图实现一个接受泛型参数的函数定义,只要它扩展了另一个特定的泛型类型。简言之参数A必须扩展参数B,其中A和B都是泛型的。 下面是我的示例 用法示例如下 一些封闭的班级 和函数调用 我不想在抽象类声明中定义E,因为T已经在那里定义了。 我也试着做了以下几点: 将myList定义为接受扩展T的键 将E定义为T类型(无法找到如何指定它在函数中扩展T 但它从来都不起作用。有没有办法做到这一点?我在Sta

  • 考虑一个具有的API,如下所示: 很简单,只有页面大小和跳过计数属性。 此外,现在我还有一些类,它们也包含但未分页。 在我的测试中,我希望他们都能实现一个接口,这样我就可以用一些更基本的测试来生成一个通用的基本测试类。为此,我添加了我认为会起作用的内容: 我将PagedResults更改为: 错误 但现在编译器抱怨PagedResultBase继承的所有地方的使用情况(?)从。 但是,如果我将接口

  • 如何获取这个类的类型?对于上下文,我使用ModelMapper,我需要类类型T从S转换为T。 背景: 我已经尝试了N种方法,其中我放置了“//一些方法来获取类型”,但没有任何效果。例如: 或