Last active
May 16, 2020 18:58
-
-
Save manoelcampos/36c0b64b1664feb8b7dfb765c6747220 to your computer and use it in GitHub Desktop.
A generic class that uses reflection to show how to get String values from an array and return such values converted to the generic type.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.lang.reflect.Constructor; | |
import java.util.Arrays; | |
import java.util.stream.Collectors; | |
import java.lang.reflect.Array; | |
import java.lang.reflect.InvocationTargetException; | |
public class Option1<T>{ | |
private int length; | |
private String defaultValue; | |
private Class<T> klass; | |
private Constructor construct; | |
public Option1(final Class<T> klass){ | |
this.klass = klass; | |
try{ | |
this.construct = klass.getConstructor(new Class[]{String.class}); | |
} catch(NoSuchMethodException e){ | |
throw new RuntimeException( | |
"There is no way to convert option values from String to " + klass.getSimpleName() + | |
": " + e.getMessage()); | |
} | |
} | |
public T getFirstValue(final String[] values){ | |
return getValues(values)[0]; | |
} | |
/** | |
* Gets the values of the option, excluding the option name (the 0th element). | |
* @return an array containing the values (without the 0th element), if the values' length isn't as expected; | |
* or an array containing the default value if the length isn't as expected and there is a default value. | |
* @throws IllegalStateException when the length of values isn't as expected and there isn't a default value | |
*/ | |
public T[] getValues(final String[] values){ | |
if(defaultValue == null && values.length != length){ | |
throw new IllegalStateException("Wrong option line passed, string options do only have 2 values"); | |
} | |
if(values.length == length) { | |
return createGenericArray(values, 1); | |
} | |
return createGenericArray(new String[]{defaultValue}); | |
} | |
private T[] createGenericArray(final String[] values){ | |
return createGenericArray(values, 0); | |
} | |
@SuppressWarnings("unchecked") | |
private T[] createGenericArray(final String[] values, final int startInclusive){ | |
final T[] array = (T[])Array.newInstance(klass, values.length-startInclusive); | |
//It was required to convert to list then to array in order to get an array of the generic type. | |
Arrays | |
.stream(values, startInclusive, values.length) | |
.map(this::convertFromString) | |
.collect(Collectors.toList()) | |
.toArray(array); | |
return array; | |
} | |
@SuppressWarnings("unchecked") | |
private T convertFromString(final String value){ | |
//if the generic type is already String, there is not need for conversion | |
if(klass == String.class){ | |
return (T)value; | |
} | |
try { | |
return (T)construct.newInstance(value); | |
} catch(InstantiationException|IllegalAccessException|InvocationTargetException e){ | |
throw new RuntimeException( | |
"Error trying to convert option value '"+value+"' from String to " + klass.getSimpleName() + | |
": " + e.getMessage()); | |
} | |
} | |
/* Trying the implementation. */ | |
public static void main(String[] args) { | |
System.out.println(); | |
Option1<String> strOpt = new Option1<>(String.class); | |
strOpt.length = 3; | |
String[] values = new String[]{"-o", "1", "2"}; | |
System.out.println("First String Value: " + strOpt.getFirstValue(values)); | |
System.out.println("String Values: " + Arrays.toString(strOpt.getValues(values))); | |
try{ | |
values = new String[]{"-o", "1"}; | |
//Error because the length of values isn't equal to 3 | |
System.out.println("First String Value: " + strOpt.getFirstValue(values)); | |
} catch(Exception e){ | |
System.out.println("\nError: " + e.getMessage() + "\n"); | |
} | |
strOpt.length = 2; | |
strOpt.defaultValue = "default value"; | |
values = new String[]{"-o"}; | |
System.out.println("First String Value: " + strOpt.getFirstValue(values)); | |
System.out.println("String Values: " + Arrays.toString(strOpt.getValues(values)) + "\n"); | |
Option1<Integer> intOpt = new Option1<>(Integer.class); | |
intOpt.length = 3; | |
values = new String[]{"-o", "1", "2"}; | |
System.out.println("\nFirst Int Value: " + intOpt.getFirstValue(values)); | |
Integer[] intValues = intOpt.getValues(values); | |
System.out.println("Int Values: "); | |
for(Integer i: intValues){ | |
System.out.println(i); | |
} | |
System.out.println(); | |
values = new String[]{"-o", "99", "this value isn't a number and will throw an exception"}; | |
try { | |
System.out.println("First Int Value: " + intOpt.getFirstValue(values)); | |
intValues = intOpt.getValues(values); | |
System.out.println("Int Values: "); | |
for(Integer i: intValues){ | |
System.out.println(i); | |
} | |
}catch(RuntimeException e){ | |
System.out.println(e.getMessage()); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment