有没有办法定义检查null然后创建对象的泛型方法?

时间:2010-11-04 15:38:41

标签: java generics generic-method

我想编写一个方法来检查参数为null的位置,如果是,则返回该类型的新对象。它看起来像:

public static <T> T checkNull(T obj) {
    if (null == obj) return someHowCreateTheObjectWithTypeT();
    else return obj;
}

经过一番挣扎和挖掘,我仍然无法找到实现这一目标的方法,它在java中是否可行?

我开始考虑反思。但是,当对象为null时,我无法获取Class实例,并且如果没有类型T的名称,则无法创建类...

更新

我考虑过将一个Class作为参数传递,但这不是最好的解决方案,如下面的答案所示:)

我的解决方案是使用defaultValue参数:

public static <T> T checkNull(T obj, T defaultValue) {
    if (null == obj) return defaultValue;
    return obj;
}

这比反射解决方案更快更安全,并且是相同的详细信息; 但是我必须为所有感兴趣的类型系统地指定一个DEFAULT_VALUE,这不是一件容易的事。

4 个答案:

答案 0 :(得分:3)

通用信息仅为编译时,在运行时不可用。您必须将对象的Class作为提示传递,并且该类必须具有公共默认构造函数。 e.g。

public static T checkNull(Object o, Class<T> c) {
  try {
    return (o == null) ? c.newInstance() : o;
  } catch (Exception e) {
    return null;
  }
}

答案 1 :(得分:3)

这是不可能的。为了使泛型以这种方式工作,它必须在编译时捕获它将被调用的类型。但是,null没有类型,因此您无法找出T来实例化它。

现在,你可以解决这个问题,同时传递Class实例,但是你需要使用Reflection来进行一些相当强大的错误处理,以确保类型T是一个具体的类,并且有一个可以调用的公共无参数构造函数

答案 2 :(得分:2)

无法完成。您必须添加Class<T>的其他参数,然后将其用于反射新的参数。类型T在编译过程中不存在。

答案 3 :(得分:1)

正如其他人所指出的那样,这是不可能做到的。但是,Guava提供的等价物与您发布的方法的默认值相同:

String foo = Objects.firstNonNull(someString, "default");

这与您的方法略有不同,因为如果两个参数都是firstNonNullNullPointerException将抛出null

另一个选择是创建一个使用Guava的Supplier<T>接口或类似的方法:

public static T firstNonNull(T first, Supplier<? extends T> defaultSupplier) {
  return first != null ? first : Preconditions.checkNotNull(defaultSupplier.get());
}

然后,您可以使用Supplier创建并返回一个新的默认实例,当且仅当第一个参数为null时。