2016-06-23 10 views
6

W jednej z moich klas Java mam te 2 bardzo podobne funkcje. Czy w Javie jest sposób na połączenie ich w jedną funkcję, więc nie muszę utrzymywać 2 funkcji?Jak łączyć podobne funkcje Java w jedną (w C++ używam szablonów)

public static boolean areValuesValid(double [] values, int numElements) { 
    if(values == null || values.length != numElements) { 
     return false; 
    } 
    for(int i = 0; i < numElements; ++i) { 
     if(Double.isNaN(values[i])) { 
      return false; 
     } 
    } 
    return true; 
} 

public static boolean areValuesValid(float [] values, int numElements) { 
    if(values == null || values.length != numElements) { 
     return false; 
    } 
    for(int i = 0; i < numElements; ++i) { 
     if(Float.isNaN(values[i])) { 
      return false; 
     } 
    } 
    return true; 
} 
+0

Rozważ skorzystanie z generatora kodu, np. https://github.com/square/javapoet – midor

+0

Należy zauważyć, że C++ nie łączy podobnych funkcji w jedną za pomocą szablonów; szablony generują nową funkcję dla każdego innego typu. –

+0

@ Mniejszy Bloch, tak to prawda, ale ja c + h Potrzebuję tylko jednej funkcji szablonu w moim kodzie źródłowym zamiast dwóch. –

Odpowiedz

4

To nie jest idealny scenariusz, z powodów wyjaśnionych przez @ericbn. Ale tutaj jest jeden sposób na uniknięcie większości powielania przy użyciu lambda:

public static boolean areValuesValid(double [] values, int numElements) { 
    return areValuesValid(values, numElements, i -> !Double.isNaN(values[i])); 
} 

public static boolean areValuesValid(float[] values, int numElements) { 
    return areValuesValid(values, numElements, i -> !Float.isNaN(values[i])); 
} 

private static boolean areValuesValid(Object values, int numElements, IntPredicate tester) { 
    if(values == null || Array.getLength(values) != numElements) { 
     return false; 
    } 
    for(int i = 0; i < numElements; ++i) { 
     if(!tester.test(i)) { 
      return false; 
     } 
    } 
    return true; 
} 
+0

Wygląda świetnie dzięki! Tylko mała korekta logiczna potrzebna w pętli for. Deklaracja if nie powinna być zanegowana. –

+0

@ MarekKnows.com Naprawiono, dzięki. – shmosel

5

Twoje pytanie jest trudne, w pewnym sensie dla Java:

  1. double i float są prymitywne typy, i jako takie nie są częścią hierarchii klas. Owijka Double i Float klasy rozciąga Number, która rozciąga Object, ale
  2. Tablica typów pierwotnych nie jest taki sam jak układ obiektów i Java nie AUTOBOX float[] do Float[], na przykład.
  3. Nie ma metody isNan(Number n) lub isNan(Object o) w Java API, ale te powyżej, których użyłeś, które oczekują double lub float. Można jednak wykonać numer Double.isNan(n.doubleValue()) dla dowolnej wersji Number n.

TL; DR W Javie powszechną praktyką dla prymitywnych typów jest mieć oddzielne implementacje dla każdego z nich, podobnie jak ty.

EDIT: W @azurefrog zasugerował:

public static boolean areValuesValid(Number[] values, int numElements) { 
    if (values == null || values.length != numElements) { 
     return false; 
    } 
    for (Number value : values) { 
     if (Double.isNaN(value.doubleValue())) { 
      return false; 
     } 
    } 
    return true; 
} 

I wtedy trzeba by użyć Apache Commons ArrayUtils:

public static boolean areValuesValid(double[] values, int numElements) { 
    return areValuesValid(ArrayUtils.toObject(values), numElements); 
} 

public static boolean areValuesValid(float[] values, int numElements) { 
    return areValuesValid(ArrayUtils.toObject(values), numElements); 
} 

EDIT2: @ rozwiązania shmosel za mija tablicę jako Object, a stamtąd unika konwersji całej tablicy do typu pudełkowego. Rozwiązanie warte rozważenia, aby uniknąć tego narzutu.

+0

Jeśli chodzi o twój trzeci punkt, istnieje metoda 'Number # doubleValue()', więc możesz po prostu wyciągnąć podwójne z dowolnego 'Number' i wywołać' Double.isNaN() 'na tym. – azurefrog

+0

Odnosząc się do drugiego punktu, apache [ma klasę ArrayUtils] (http://commons.apache.org/proper/commons-lang/javadocs/api-3.1/org/apache/commons/lang3/ArrayUtils.html#toObject (double [])), które będą dla ciebie autoboxem dla prymitywów, jeśli chcesz ściągnąć biblioteki stron trzecich. – azurefrog

-3

Aby uprościć, użyłbym instancję:

public static boolean areValuesValid(Object[] values) { 
    if (values == null) { 
     return false; 
    } 
    for(int i = 0; i < values.length; ++i) { 
     //if not Float and not Double return false 
     if (values[i] instanceof Float || values[i] instanceof Double) { 
      return true; 
     } 
    } 
    return false; 
} 

Nie jestem pewien, czy naprawdę musi przejść w numElements.

+0

'float []' nie jest podklasą 'Object []'. – shmosel

+0

Sprawdzasz inne kryteria sprawdzania poprawności niż OP, który testuje, czy długość tablicy jest zgodna z oczekiwaniami i czy zawiera wartości nieliczbowe. – azurefrog

Powiązane problemy