2013-04-15 16 views
7

powiedzmy mam metody takie jak to:Metoda rodzajowych bez argumentów

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(); 
    } 
} 

Rzeczywiste specyfika metoda ta jest bardzo ważna. Jednakże, aby wywołać tę metodę używamy:

Example.<Float>getOddBits(0f); 

Moje pytanie brzmi, czy jest możliwe, aby napisać taki sposób bez konwencjonalnych parametrów. Bez przeciążania, a ostatecznie bez Boxing.

Idealnie wywołany przez:

Example.<Byte>getOddBits(); 
+3

przypuszczam nie z powodu usunięcia, ale można pozbyć się superflous parametru instancji i użyć obiektu klasy jako parametr: 'getOddBits (klasa clazz )'. Nie sądzę, żebyś mógł obejść boks, ponieważ typ zwrotu nie wystarcza do stworzenia odrębnych sygnatur, tzn. 'Byte getOddBits()' i 'int getOddBits()' mogą być niejednoznaczne. – Pyranja

+0

Mogą być również inne opcje. Dlaczego musisz to zrobić? dla przykładu, przy zwracaniu zasadniczo wartości statycznych można użyć wyliczenia. Jeśli jest coś bardziej konkretnego, mogą być również inne opcje. Na przykład, jeśli konwertujesz numer do innego formularza, możesz utworzyć interfejs konwersji, np. Za pomocą metody toBytes i fromBytes. następnie musisz mieć wszystkie klasy, których potrzebujesz, aby to zaimplementować. Nie jestem pewien, czy to pomaga, czy nie mógłbyś podać bardziej konkretnego przykładu bliżej tego, co potrzebujesz? –

+0

@JohnKane Przykład był arbitralny, tylko po to, aby zademonstrować użycie typu zwrotnego podklasy, jak określono za pomocą argumentu w najczystszy możliwy sposób. Prawdopodobnie mogłem pojechać ze starym 'foo-bar-baz', ale pomyślałem, że praktyczny przykład będzie lepiej pasował. – azz

Odpowiedz

1

Jako akcesorium do sugestii KennyTM użytkownika, można połączyć argument Ćwiczenia metodą generycznych, aby powrócić rodzaj specjalistycznego:

@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; 
} 

To pozwoli Ci przypisać następujące polecenie, a uniknąć oddanych na każde wezwanie:

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

Po prostu przesłano edycję obsługującą również prymitywne wartości ('cls == Integer.klasa || cls == int.class'). Jest to zdecydowanie optymalne rozwiązanie z punktu widzenia czystości inwokacji. – azz

+0

(To znaczy, int i = Example.getOddBits (int.class);) – azz

7

Jak o prostu wziąć .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); 
+0

To zdecydowanie działa. Naprawdę starałem się w pełni zastosować metody generyczne, ale domyślam się, że wymazanie używa przykładu. getOddBits() 'niemożliwe. – azz

+0

Możesz połączyć to podejście z generycznym podpisem metody, aby zwrócić typ specjalistyczny: 'public static N getOddBits (klasa cls) {' – seanhodges

+0

Rozszerzyłem mój komentarz powyżej o nową odpowiedź. – seanhodges

0

nie jestem pewien, czy to pomoże, ale użyłem tego w przeszłości do deserializacji i powrocie przedmiot odpowiedniego typu.

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

Jednak nie jestem do końca pewien, co należy zrobić. Prostszym i czystszym sposobem na osiągnięcie tego może być stworzenie interfejsu konwertera dla potrzebnych typów i posiadanie jakiejkolwiek klasy potrzebnej do jej implementacji. Wtedy to, czegokolwiek potrzebujesz, można wywołać bezpośrednio w samym obiekcie. na przykład:

inerface Convertor<T>{ 

    T convert(); 

    void set(T value); 

} 





class Something implements Converter<Long,ByteArray>{ 

    ... 

    public ByteArray convert(){...} 

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

}