3

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

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

经过一番挣扎和挖掘,我仍然无法实现这一点,在java中它真的可能吗?

一开始我想到了反思。但是当对象为空时,我无法获得 Class 实例,并且如果没有类型 T 的名称,您将无法创建 Class...

更新:

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

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

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

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

4

4 回答 4

3

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

public static T checkNull(Object o, Class<T> c) {
  try {
    return (o == null) ? c.newInstance() : o;
  } catch (Exception e) {
    return null;
  }
}
于 2010-11-04T15:43:13.783 回答
3

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

现在,您也可以通过传入 Class 实例来解决这个问题,但是您将需要使用反射进行一些相当健壮的错误处理,以确保类型 T 是一个具体的类并且具有可以调用的公共无参数构造函数。

于 2010-11-04T15:43:21.583 回答
2

无法完成。您必须添加一个额外的参数Class<T>,然后使用它来反射新。类型 T 在编译过程中不存在。

于 2010-11-04T15:43:29.513 回答
1

正如其他人指出的那样,这是无法做到的。但是,Guava提供了与您发布的方法的默认值等效的值:

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

firstNonNull这与您的方法略有不同,NullPointerException如果两个参数都是null.

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

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

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

于 2010-11-04T16:06:07.757 回答