0

标题基本上说明了一切:如果我有一个在 T 中通用的 java 方法,我能找到关于 T 的任何信息吗?特别是,我可以检查 T 是否实现了某个接口或扩展了某个类?

我想做类似的事情

public <T> List<T> doSth(List<T> l) {

  if(T extends Comparable) {
    // do one thing
  } else {
    // do another
  }

  return l;
}

有什么提示吗?

非常感谢,

约翰内斯

4

6 回答 6

10

不清楚您是要在编译时还是在运行时执行检查。如果您只是想确保传递给方法的列表参数包含某些类型的对象,那么请T适当地重新定义。

例如,要确保编译器只允许将 aList<Comparable>传递给此方法,请重新定义T为:

public <T extends Comparable<? super T>> List<T> doSth(List<T> l) {
    // Method body omitted
}

然后,您可以使用方法重载(而不是 if-else 语句)来确保为T. 换句话说,替换这个:

public <T> List<T> doSth(List<T> l) {

    if(T extends Comparable) {
        // do one thing
    } else {
        // do another
    }

    return null
}

用这些:

public <T extends Comparable<? super T>> List<T> doSth(List<T> l) {
    // do one thing
    return null;
}

public <T> List<T> doSth(List<T> l, Class<T> clazz) {
    // do another
    return null;
}

但是,您需要记住选择要调用的重载方法,并且泛型类型检查仅在编译时进行!例如,下面的代码:

List<? extends Serializable> alist = new ArrayList<Integer>();
doSth(alist);

实际上会调用第二种doSth方法,因为编译时类型参数 ( ? extends Serializable) 没有实现Comparable,即使运行时类型参数 ( Integer) 实现了。

于 2009-10-13T16:58:23.743 回答
4

否 - 由于类型擦除。在执行时,您根本不知道 T 的类型。

一种选择是将类型指定为另一个参数:

public <T> List<T> doSth(List<T> l, Class<T> clazz) {
    if (Comparable.class.isAssignableFrom(clazz)) {
        ...
    }
}
于 2009-10-13T16:52:55.943 回答
1

您应该在(甚至之前!:) 编译时就已经知道 T 是否扩展了 Comparable,那么为什么不创建两个方法呢?

public <T extends Comparable<T>> List<T> doSthComp(List<T> l) {
  // do one thing
  return l;
}

public <T> List<T> doSth(List<T> l) {
  // do another
  return l;
}
于 2009-10-13T17:06:25.870 回答
1

是的你可以:

public <T> List<T> doSth(List<T> l) {
  //You could also check every element, if there is a chance only some will be comparable
  if (l.size() >0 && l.get(0) instanceof Comparable) {
    // do one thing
  } else {
    // do another
  }

  return l;
}

请注意,您正在检查“l”中的元素是什么类型,而不是 T - 这是关键。

编辑:更改了代码以处理它是一个列表的事实——我在原来的阅读中错过了这一点。

于 2009-10-13T16:54:04.157 回答
0

你可以做一个

public <T extends Comparable<T>> List<T> doSth(List<T> l)

这将允许您在项目中使用 Comparable 接口'l'

于 2009-10-13T16:59:57.787 回答
0

对于编译时检查,Don 已经给出了答案。对于运行时,只有当您还传递一个表示 T 的显式对象时才有可能,例如:
static <T> List<T> doSth(List<T> l, Class<T> tClass) 让 tClass 对象表示 T 的真实类,您可以检查它是否已通过反射实现可比较。但是从我的角度来看,编译时检查要好得多。

于 2009-10-13T17:04:33.607 回答