简体   繁体   中英

Is there a way to define a generic method that checks for null and then create the object?

I'd like to write a method that checks where the argument is null, and if it is, returns a new object of that type. it looks like:

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

After some struggling and digging, I still can't get a way to achieve this, is it atually possible in java?

I thought about reflection at first. But I just can't get a Class instance when the object is null, and you can't create a Class without the type T's name...

Update:

I thought about passing a Class as a parameter, but that's not the best solution, as the following answers shows :)

My currunt solution is to use a defaultValue parameter:

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

Which is faster and safer than a reflection solution, and is the same verbose; But then I have to systematically specify a DEFAULT_VALUE for all types of interest, which is not an easy work.

Generic information is compile time only and not available at runtime. You'd have to pass the Class of the object in as a hint, and the class would have to have a public default constructor. eg

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

This is not possible. For generics to work in this manner, it has to capture at compile-time the type that it will be called with. However, null has no type so you won't be able to figure out T to instantiate it.

Now, you may be able to work around this also passing in the Class instance, but you will need some rather robust error handling using Reflection to ensure that type T is a concrete class and has a public parameterless constructor that you can invoke.

Cannot be done. You must add an additional parameter of Class<T> , and then use it to reflectively new. The type T does not survive the compilation process.

As others have pointed out, this can't be done. However, Guava provides an equivalent to the default value you method you posted:

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

This differs slightly from your method in that firstNonNull will throw a NullPointerException if both arguments are null .

Another option would be to create a method that makes use of Guava's Supplier<T> interface or something similar:

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

You could then use a Supplier that creates and returns a new default instance when and only when the first argument is null.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM