Java 8 functional constructor from templated object

╄→尐↘猪︶ㄣ 提交于 2019-12-22 05:10:42

问题


I am using Eclipse Luna Service Release 2 (4.4.2), Java 8 u51.

I'm trying to create a method which will create instances of a passed object based on another method parameter. The prototype is simplified to

public <T> T test(Object param, T instance) {
    Constructor<?> constructor = instance.getClass().getConstructors()[0]; // I actually choose a proper constructor

    // eclipse reports "Unhandled exception type InvocationTargetException"
    Function<Object, Object> createFun = constructor::newInstance;

    T result = (T) createFun.apply(param);
    return result;
}

On line with Function declaration eclipse reports Unhandled exception type InvocationTargetException compiler error. I need the Function to later use in a stream.

I tried to add various try/catch blocks, throws declarations, but nothing fixes this compiler error.

How to make this code work?


回答1:


You can't throw a checked exception from a lambda with a Function target type because its apply method does not throw an exception. So you need to make it into an unchecked exception, for example by wrapping it:

Function<Object, Object> createFun = o -> {
  try {
    return constructor.newInstance(o);
  } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
    throw new RuntimeException(e);
  }
};

An alternative is to lead the compiler to think it's an unchecked exception, which produces a cleaner stack trace vs. the option above:

Function<Object, Object> createFun = o -> {
  try {
    return constructor.newInstance(o);
  } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
    return uncheck(e);
  }
};

With the following utility method:

@SuppressWarnings("unchecked")
public static <E extends Throwable, T> T uncheck(Throwable t) throws E {
  throw ((E) t);
}



回答2:


This is because the Method Reference is to a Method with the Exceptions named in the compile time error. The single abstract Method R apply(T t ) in java.util.Function does not throw these Exceptions. So there is a mismatch between the functional type of java.util.Function and the type of your Method-Reference.

Using a functional type with a matching method works ... for example :

    interface MyFunction<T,R> {
        /**
         * Applies this function to the given argument.
         *
         * @param t the function argument
         * @return the function result
         */
        R apply(T t) throws  Throwable;

    }

    public <T> T test(Object param, T instance) throws InstantiationException, IllegalAccessException,
           IllegalArgumentException, InvocationTargetException {
        Constructor<?> constructor = instance.getClass().getConstructors()[0]; // I actually choose a proper constructor

        // eclipse reports "Unhandled exception type InvocationTargetException"
            MyFunction<Object,Object> createFun = constructor::newInstance;

        T result = (T) createFun.apply(param);
        return result;
    }


来源:https://stackoverflow.com/questions/31470817/java-8-functional-constructor-from-templated-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!