/* * Copyright (c) 2016 Mockito contributors * This program is made available under the terms of the MIT License. */ package org.mockito.internal.util; import org.mockito.internal.creation.instance.InstantiationException; import java.lang.reflect.Method; /** * Helper class to work with features that were introduced in Java versions after 1.5. * This class uses reflection in most places to avoid coupling with a newer JDK. */ public final class JavaEightUtil { // No need for volatile, these optionals are already safe singletons. private static Object emptyOptional; private static Object emptyOptionalDouble; private static Object emptyOptionalInt; private static Object emptyOptionalLong; private JavaEightUtil() { // utility class } /** * Creates an empty Optional using reflection to stay backwards-compatible with older JDKs. * * @return an empty Optional. */ public static Object emptyOptional() { // no need for double-checked locking if (emptyOptional != null) { return emptyOptional; } return emptyOptional = invokeNullaryFactoryMethod("java.util.Optional", "empty"); } /** * Creates an empty OptionalDouble using reflection to stay backwards-compatible with older JDKs. * * @return an empty OptionalDouble. */ public static Object emptyOptionalDouble() { // no need for double-checked locking if (emptyOptionalDouble != null) { return emptyOptionalDouble; } return emptyOptionalDouble = invokeNullaryFactoryMethod("java.util.OptionalDouble", "empty"); } /** * Creates an empty OptionalInt using reflection to stay backwards-compatible with older JDKs. * * @return an empty OptionalInt. */ public static Object emptyOptionalInt() { // no need for double-checked locking if (emptyOptionalInt != null) { return emptyOptionalInt; } return emptyOptionalInt = invokeNullaryFactoryMethod("java.util.OptionalInt", "empty"); } /** * Creates an empty OptionalLong using reflection to stay backwards-compatible with older JDKs. * * @return an empty OptionalLong. */ public static Object emptyOptionalLong() { // no need for double-checked locking if (emptyOptionalLong != null) { return emptyOptionalLong; } return emptyOptionalLong = invokeNullaryFactoryMethod("java.util.OptionalLong", "empty"); } /** * Creates an empty Stream using reflection to stay backwards-compatible with older JDKs. * * @return an empty Stream. */ public static Object emptyStream() { // note: the empty stream can not be stored as a singleton. return invokeNullaryFactoryMethod("java.util.stream.Stream", "empty"); } /** * Creates an empty DoubleStream using reflection to stay backwards-compatible with older JDKs. * * @return an empty DoubleStream. */ public static Object emptyDoubleStream() { // note: the empty stream can not be stored as a singleton. return invokeNullaryFactoryMethod("java.util.stream.DoubleStream", "empty"); } /** * Creates an empty IntStream using reflection to stay backwards-compatible with older JDKs. * * @return an empty IntStream. */ public static Object emptyIntStream() { // note: the empty stream can not be stored as a singleton. return invokeNullaryFactoryMethod("java.util.stream.IntStream", "empty"); } /** * Creates an empty LongStream using reflection to stay backwards-compatible with older JDKs. * * @return an empty LongStream. */ public static Object emptyLongStream() { // note: the empty stream can not be stored as a singleton. return invokeNullaryFactoryMethod("java.util.stream.LongStream", "empty"); } /** * Invokes a nullary static factory method using reflection to stay backwards-compatible with older JDKs. * * @param fqcn The fully qualified class name of the type to be produced. * @param methodName The name of the factory method. * @return the object produced. */ private static Object invokeNullaryFactoryMethod(final String fqcn, final String methodName) { try { final Class type = Class.forName(fqcn); final Method method = type.getMethod(methodName); return method.invoke(null); // any exception is really unexpected since the type name has // already been verified } catch (final Exception e) { throw new InstantiationException( String.format("Could not create %s#%s(): %s", fqcn, methodName, e), e); } } }