2013-04-15 10 views
7

Sagen wir, ich habe eine Methode wie folgt aus:Methode Generics Ohne Argumente

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

Die tatsächlichen Besonderheiten des Verfahrens ist nicht wirklich wichtig. Um jedoch diese Methode aufrufen, die wir verwenden:

Example.<Float>getOddBits(0f); 

Meine Frage ist, ist es möglich, ein solches Verfahren ohne herkömmlichen Parameter zu schreiben. Ohne zu überladen und letztendlich ohne Boxen.

Ideal von aufgerufen:

Example.<Byte>getOddBits(); 
+3

Ich nehme nicht wegen Löschung, aber man könnte die Beseitigung der superflous Instanz Parameter erhalten und ein Class-Objekt als Parameter verwenden: 'getOddBits (Klasse clazz )'. Ich glaube nicht, dass man Boxen umgehen kann, da der Rückgabetyp nicht ausreicht, um unterschiedliche Signaturen zu erzeugen, d.h. "byte getOddBits()" und "int getOddBits()" können ambivalent sein. – Pyranja

+0

Es könnte auch andere Optionen geben. Warum musst du das tun? für Ihr Beispiel, mit im Grunde statischen Werten zurückgegeben werden, könnten Sie einfach eine Aufzählung verwenden. Wenn es etwas spezifischeres gibt, könnte es auch andere Optionen geben. Wenn Sie beispielsweise eine Zahl in ein anderes Formular konvertieren, können Sie eine Konvertierungsschnittstelle wie mit einer toBytes- und fromBytes-Methode erstellen. dann musst du die Klassen, die du brauchst, implementieren. Ich bin mir nicht sicher, ob das hilft, wenn nicht, könntest du ein konkreteres Beispiel näher an das Thema legen, wofür du es brauchst? –

+0

@ JohnKane Das Beispiel war willkürlich, nur um die Verwendung eines Unterklassen-Rückgabetyps zu demonstrieren, der über ein Argument auf die sauberste Weise angegeben wurde. Ich hätte wahrscheinlich mit dem alten 'foo-bar-baz' gehen können, aber ich dachte, dass ein praktisches Beispiel besser geeignet wäre. – azz

Antwort

1

Als Ergänzung zu KennyTM Vorschlag, könnten Sie eine Klasse Argument mit Methode Generika kombinieren, um die spezielle Art zurück:

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

Dies ermöglicht es Ihnen die folgenden zuweisen, und vermeiden Sie eine gossen jeder Aufruf:

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

Es wurde auch ein Edit zur Unterstützung primitiver Werte übergeben ('cls == Integer.Klasse || cls == int.class'). Dies ist definitiv die optimale Lösung aus Sicht der Reinheit der Anrufung. – azz

+0

(Das heißt: int i = Beispiel.getOddBits (int.class); ') – azz

7

Wie wäre es einfach und .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

Das funktioniert definitiv. Ich habe wirklich versucht, Methoden-Generics in vollen Zügen zu pushen, aber ich glaube, das Löschen macht Gebrauch von 'Beispiel. getOddBits() 'unmöglich. – azz

+0

Sie können diesen Ansatz mit Ihrer generischen Methodensignatur kombinieren, um einen speziellen Typ zurückzugeben: 'public static N getOddBits (Klasse cls) {' – seanhodges

+0

Ich habe meinen Kommentar oben auf eine neue Antwort erweitert. – seanhodges

0

ich bin nicht sicher, ob dies wird Ihnen helfen, aber ich habe dies in der Vergangenheit für Deserialisieren und ein Objekt des entsprechenden Typs zurück.

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

Allerdings bin ich mir nicht ganz sicher, was Sie tun müssen. Eine einfachere und sauberere Möglichkeit, dies zu erreichen, könnte darin bestehen, eine Konverterschnittstelle für die angegebenen Typen zu erstellen, die Sie benötigen, und die Klassen zu haben, die für die Implementierung benötigt werden. Dann, was immer Sie benötigen, könnte direkt auf das Objekt selbst aufgerufen werden. zum Beispiel:

inerface Convertor<T>{ 

    T convert(); 

    void set(T value); 

} 





class Something implements Converter<Long,ByteArray>{ 

    ... 

    public ByteArray convert(){...} 

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

}