简体   繁体   中英

Method Generics Without Arguments

Let's say I have a method like this:

static class Example 
{
    public static <N extends Number> Number getOddBits(N type)
    {
        if (type instanceof Byte) return (byte)0xAA;
        else if (type instanceof Short) return (short)0xAAAA;
        else if (type instanceof Integer) return 0xAAAAAAAA;
        else if (type instanceof Float) return Float.intBitsToFloat(0xAAAAAAAA);
        else if (type instanceof Long) return 0xAAAAAAAAAAAAAAAAL;
        else if (type instanceof Double) return Double.longBitsToDouble(0xAAAAAAAAAAAAAAAAL);
        throw new IllegalArgumentException();
    }
}

The actual specifics of the method isn't really important. However, to call this method we use:

Example.<Float>getOddBits(0f);

My question is, is it possible to write such a method without conventional parameters. Without overloading, and ultimately without Boxing.

Ideally invoked by:

Example.<Byte>getOddBits();

How about just take a .class ?

public static Number getOddBits(Class<? extends Number> cls)
{
    if (cls == Byte.class) {
        return (byte)0xAA;
    } else if (cls == Short.class) {
        return (short)0xAAAA;
    } else if (cls == Integer.class) {
        return 0xAAAAAAAA;
    } else if (cls == Float.class) {
        return Float.intBitsToFloat(0xAAAAAAAA);
    } else if (cls == Long.class) {
        return 0xAAAAAAAAAAAAAAAAL;
    } else if (cls == Double.class) {
        return Double.longBitsToDouble(0xAAAAAAAAAAAAAAAAL);
    }
    throw new IllegalArgumentException();
}

...

Example.getOddBits(Float.class);

As an enhancement to KennyTM's suggestion, you could combine a Class argument with method generics to return the specialised type:

@SuppressWarnings("unchecked")
public static <N extends Number> N getOddBits(Class<N> cls) {
    Number out;
    if (cls == Byte.class) {
        out = (byte)0xAA;
    } else if (cls == Short.class) {
        out = (short)0xAAAA;
    } else if (cls == Integer.class) {
        out = 0xAAAAAAAA;
    } else if (cls == Float.class) {
        out = Float.intBitsToFloat(0xAAAAAAAA);
    } else if (cls == Long.class) {
        out = 0xAAAAAAAAAAAAAAAAL;
    } else if (cls == Double.class) {
        out = Double.longBitsToDouble(0xAAAAAAAAAAAAAAAAL);
    } else {
        throw new IllegalArgumentException();
    }
    return (N)out;
}

This will allow you to assign the following, and avoid a cast on each invocation:

    float result = Example.getOddBits(Float.class);

Im not sure if this will help you, but I have used this in the past for deserializing and returning an Object of the appropriate type.

public <T> T deserialize(String xml){
    T object=null;
    ...
    //pull type information from method param
    ...
    return object=(T)type.newInstance(); //helper to instantiate class
}

However, I am not entirely sure on what you need to do. A simpler and cleaner way to accomplish this could be to make a Converter interface for the given types that you need and have whatever classes need to use it implement it. Then what ever type you need, could be called directly on the Object itself. for example:

inerface Convertor<T>{

    T convert();

    void set(T value);

}





class Something implements Converter<Long,ByteArray>{

    ...

    public ByteArray convert(){...}

    public void set(ByteArray value){...}

}

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