2

I am trying to use the lambda expression to simplify the below code snipped. A detailed info can be found here: Could not serialize object cause of HibernateProxy.

public class HibernateProxyTypeAdapter extends TypeAdapter<HibernateProxy> {
    public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {
        @Override
        @SuppressWarnings("unchecked")
        public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
            return (HibernateProxy.class.isAssignableFrom(type.getRawType())
                    ? (TypeAdapter<T>) new HibernateProxyTypeAdapter(gson)
                    : null);
        }
    };
    ...
    ...
    ...
}

I changed the code to this:

public static final TypeAdapterFactory FACTORY = (gson, type) -> HibernateProxy.class.isAssignableFrom(type.getRawType())
                    ? (TypeAdapter<T>) new HibernateProxyTypeAdapter(gson)
                    : null;

But I am getting an error in Eclispe: Illegal lambda expression: Method create of type TypeAdapterFactory is generic

I also tried this one but throws me the same error.

public static final TypeAdapterFactory FACTORY = (gson, type) -> HibernateProxy.class.isAssignableFrom(type.getRawType())
                    ? (TypeAdapter<Hibernate>) new HibernateProxyTypeAdapter(gson)
                    : null;

Is it possible to use the lambda expression in this situation? How should I modify my code?

Michał Ziober
  • 31,576
  • 17
  • 81
  • 124
  • See [Lambda Expression and generic method](https://stackoverflow.com/questions/22588518/lambda-expression-and-generic-method) – Michał Ziober Mar 13 '19 at 23:58

1 Answers1

0

I don't think it can be "simplified", but being rather even more complicated. The reason of the error is that the method is generic and you have to use generic (functional) interfaces, like this:

@SuppressWarnings("rawtypes")
private static final BiFunction<Gson, TypeToken, TypeAdapter> GENERIC_FACTORY = (gson, typeToken)
        -> HibernateProxy.class.isAssignableFrom(typeToken.getRawType()) ? new HibernateTypeAdapter(gson) : null;

static final TypeAdapterFactory FACTORY = GENERIC_FACTORY::apply;

Well, so-so looking, right? If inlined, then even more uglier:

static final TypeAdapterFactory FACTORY = ((BiFunction<Gson, TypeToken, TypeAdapter>) (gson, typeToken)
        -> HibernateProxy.class.isAssignableFrom(typeToken.getRawType()) ? new HibernateTypeAdapter(gson) : null)::apply;

If you really believe lambda expressions are what you need in such a scenario, here are two ways:

Generic type adapter factory adapter

@FunctionalInterface
public interface GenericTypeAdapterFactory
        extends TypeAdapterFactory {

    TypeAdapter<?> createUnchecked(Gson gson, TypeToken<?> typeToken);

    @Override
    default <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
        @SuppressWarnings("unchecked")
        final TypeAdapter<T> castTypeAdapter = (TypeAdapter<T>) createUnchecked(gson, typeToken);
        return castTypeAdapter;
    }

}

with

static final TypeAdapterFactory FACTORY = (GenericTypeAdapterFactory) (gson, typeToken)
        -> HibernateProxy.class.isAssignableFrom(typeToken.getRawType()) ? new HibernateTypeAdapter(gson) : null;

or

Generic wrapper

interface GsonTypeAdapterFactory<T>
        extends BiFunction<Gson, TypeToken<T>, TypeAdapter<T>> {
}

static <TF> TypeAdapterFactory wrap(final GsonTypeAdapterFactory<TF> factory) {
    return new TypeAdapterFactory() {
        @Override
        public <T> TypeAdapter<T> create(final Gson gson, final TypeToken<T> typeToken) {
            @SuppressWarnings("unchecked")
            final TypeToken<TF> castTypeToken = (TypeToken<TF>) typeToken;
            @SuppressWarnings("unchecked")
            final TypeAdapter<T> castTypeAdapter = (TypeAdapter<T>) factory.apply(gson, castTypeToken);
            return castTypeAdapter;
        }
    };
}

with

static final TypeAdapterFactory FACTORY = GenericTypeAdapterFactory.wrap((GenericTypeAdapterFactory.GsonTypeAdapterFactory<HibernateProxy>) (gson, typeToken)
        -> HibernateProxy.class.isAssignableFrom(typeToken.getRawType()) ? new HibernateTypeAdapter(gson) : null
);

Having at least 3-4 ways of working around that, I would not recommend any of them, but stick with your initial way.