I stumbled upon a little problem today. Consider a little wrapper class:
class Event<T> {
T value;
Class<T> type;
// other fields, getters and setters omitted for brevity
}
Now I was in a situation where I wanted to convert a Event<Long> into a Event<String> while preserving the other fields and updating the type member.
Eventually I ended up with the most simple "solution":
Event<String> new = new Event(old.getValue().toString(), String.class, other, fields);
Having worked with Haskell on my pet projects however, I naturally longed for a function like fmap :: Functor f => (a -> b) -> f a -> f b (read: given a function from a to b and a functor containing something of type a give me a result containing the b) and after finding no standard implementation I set out to write one myself:
interface Functor<T> {
Functor<S> fmap( Func1<T,S> f );
}
// ... in Event<T>:
Functor<S> fmap( Func1<T,S> f ) {
S newValue = f.call(this.value);
return new Event( newValue, newValue.getClass(), other, fields);
}
Now there is a problem with this solution: after the call to fmap in Java I am left with an instance of type Functor<String> while the same function in Haskell would return a Event<String>.
Is there a way to get my Event back (without unsafely casting it)?
No, it isn't possible. For this to happen we would need to abstract over the Functor in your interface, something like
interface Functor<T> as F<T> {
F<S> map(f : Function<T, S>);
}
But Java doesn't allow you to abstract over type constructors, just types. This is called Higher Kinded Types (HKT). Only a few (non-dependent) languages have HKTs, Scala and Haskell are the only two I can think of.
In fact HKTs are necessary to express a lot of abstractions,
Control.Monad
Control.Applicative
Data.Traversable
Data.Foldable
Control.Monad.Trans
Any monad transformers, full stop
Free monads
Lenses/Prisms
Streaming libraries (they're monad transformers)
Almost everything that was in category-extras
All of these involve abstracting over type constructors, not just concrete types.
This works reasonably well for me, but it's not quite Functor<T>. It requires that you also specify F, the type for which your functor is an instance:
interface Fn1<A, B> {
B apply(A a);
}
interface Functor<A, F extends Functor<?, ?>> {
<B> F map(Fn1<A, B> f);
}
Your Event<A> class would implement Functor like this:
public class Event<A> implements Functor<A, Event<?>> {
public final A value;
public Event(A _value) {
value = _value;
}
public <B> Event<B> map(Fn1<A, B> f) {
return new Event<B>(f.apply(value));
}
public String toString() {
return "Event<" + value.getClass().getSimpleName() + ">(" + value.toString() + ")";
}
}
If you need a functor for a closed-to-extension class (e.g. Observable from rxjava), you can write one that looks a little more like a type class, however it won't be able to conform to any functor-like interface since Java lacks higher-kinded types:
public class ObservableFunctor {
public static <A,B> Observable<B> map(Observable<A> fa, Fn1<A, B> f) {
return new Observable<B>(f.apply(fa.value));
}
}
Here's a runnable example that uses both Event and Observable from above:
public class FunctorDemo {
interface Fn1<A, B> {
B apply(A a);
}
interface Functor<A, F extends Functor<?, ?>> {
<B> F map(Fn1<A, B> f);
}
static class ObservableFunctor {
public static <A,B> Observable<B> map(Observable<A> fa, Fn1<A, B> f) {
return new Observable<B>(f.apply(fa.value));
}
}
static class Observable<A> {
public final A value;
public Observable(A _value) {
value = _value;
}
public String toString() {
return "Observable<" + value.getClass().getSimpleName() + ">(" + value.toString() + ")";
}
}
static class Event<A> implements Functor<A, Event<?>> {
public final A value;
public Event(A _value) {
value = _value;
}
public <B> Event<B> map(Fn1<A, B> f) {
return new Event<B>(f.apply(value));
}
public String toString() {
return "Event<" + value.getClass().getSimpleName() + ">(" + value.toString() + ")";
}
}
public static void main(String[] args) {
Observable<Event<Long>> oe1 = new Observable(new Event(42L));
System.out.println("oe1: " + oe1.toString()); // oe1: Observable<Event>(Event<Long>(42))
Observable<Event<String>> oe2 = ObservableFunctor.map(oe1,
new Fn1<Event<Long>, Event<String>>() {
public Event<String> apply(Event<Long> e) {
return e.map(
new Fn1<Long, String>() {
public String apply(Long l) {
return l.toString();
}
}
);
}
}
);
System.out.println("oe2: " + oe2.toString()); // oe2: Observable<Event>(Event<String>(42))
}
}
Related
I've tried to do some stuff with generics already but it seems I cannot personally find any simple solution. Still I think it'd be a sin to leave these 3 similar methods alone as they are.
public List<PassengerPlane> getPassengerPlanes() {
List<PassengerPlane> passengerPlanes = new ArrayList<>();
for (Plane plane : planes) {
if (plane instanceof PassengerPlane) {
passengerPlanes.add((PassengerPlane) plane);
}
}
return passengerPlanes;
}
public List<MilitaryPlane> getMilitaryPlanes() {
List<MilitaryPlane> militaryPlanes = new ArrayList<>();
for (Plane plane : planes) {
if (plane instanceof MilitaryPlane) {
militaryPlanes.add((MilitaryPlane) plane);
}
}
return militaryPlanes;
}
public List<ExperimentalPlane> getExperimentalPlanes() {
List<ExperimentalPlane> experimentalPlanes = new ArrayList<>();
for (Plane plane : planes) {
if (plane instanceof ExperimentalPlane) {
experimentalPlanes.add((ExperimentalPlane) plane);
}
}
return experimentalPlanes;
}
What do you need is generic method, but the problem is that instanceof cannot check against type parameter (it is in fact erased during compilation), it requires actual class reference. So, you may provide this to the method explicitly:
public <T extends Plane> List<T> getPlanes(Class<T> claz) {
List<T> result = new ArrayList<>();
for (Plane plane : planes) {
if (claz.isInstance(plane)) {
result.add(claz.cast(plane));
}
}
return result;
}
Note how instanceof and explicit cast changed to calls to .isInstance() and .cast()
Use it like
getPlanes(PassengerPlane.class)
You can make things a bit shorter with Streams, but I'm not sure there's a way to get around using instanceof here:
public List<PassengerPlane> getPassengerPlanes() {
return planes.stream().filter(t -> t instanceof PassengerPlane)
.map(t -> (PassengerPlane) t).collect(Collectors.toList());
}
public List<MilitaryPlane> getMilitaryPlanes() {
return planes.stream().filter(t -> t instanceof MilitaryPlane)
.map(t -> (MilitaryPlane) t).collect(Collectors.toList());
}
public List<ExperimentalPlane> getExperimentalPlanes() {
return planes.stream().filter(t -> t instanceof ExperimentalPlane)
.map(t -> (ExperimentalPlane) t).collect(Collectors.toList());
}
Here's how I would approach the problem using generics:
public <T> List<T> getTPlanes(Class<T> clazz) { //declare the method to take a type generic
List<T> tPlanes = new ArrayList<>(); //initialize an ArrayList of that type
planes.stream() //stream the planes list
.filter(clazz::isInstance) //filter it down to only planes of the type that we want
.forEach((p) -> tPlanes.add((T) p)); //add each plane left in the stream to our new ArrayList, and cast it to the type generic
return tPlanes; //return the ArrayList we just created and populated
}
You do need to do a cast somewhere: Here is a solution with a single method that takes the subtype.
import java.util.*;
import java.util.stream.*;
public class Example {
public static class Plane { }
public static class PassengerPlane extends Plane { }
public static class MilitaryPlane extends Plane { }
public static class ExperimentalPlane extends Plane { }
private static List<Plane> planes =
List.of(new PassengerPlane(),
new MilitaryPlane(),
new ExperimentalPlane());
public static <T extends Plane> List<T> getPlanesOfType(Class<T> type, List<Plane> planes) {
List<T> list =
planes.stream()
.filter(t -> type.isAssignableFrom(t.getClass()))
.map(t -> type.cast(t))
.collect(Collectors.toList());
return list;
}
public static void main(String[] args) throws Exception {
System.out.println(getPlanesOfType(PassengerPlane.class, planes));
System.out.println(getPlanesOfType(MilitaryPlane.class, planes));
System.out.println(getPlanesOfType(ExperimentalPlane.class, planes));
System.out.println(getPlanesOfType(Plane.class, planes));
}
}
[Example$PassengerPlane#7b227d8d]
[Example$MilitaryPlane#7219ec67]
[Example$ExperimentalPlane#45018215]
[Example$PassengerPlane#7b227d8d, Example$MilitaryPlane#7219ec67, Example$ExperimentalPlane#45018215]
You could either use the single method to replace all three or use it to implement.
If your problem is really so short, probably it won't be worthy the effort. However, this is a typical problem for Visitor Pattern (especially if your duplicate code is larger).
Step 1
Create a Visitor interface to visit each type of Plane:
interface Visitor {
void visit(MilitaryPlane militaryPlane);
void visit(ExperimentalPlane experimentalPlane);
void visit(PassengerPlane passengerPlane);
}
... and implement it in a way that starts with a List<Plane> that can be enriched by each of the .visit():
class PlaneVisitor implements Visitor {
private final List<Plane> planes;
PlaneVisitor(List<Plane> planes) {
this.planes = requireNonNull(planes);
}
#Override
public void visit(MilitaryPlane militaryPlane) {
planes.add(militaryPlane);
}
#Override
public void visit(ExperimentalPlane experimentalPlane) {
planes.add(experimentalPlane);
}
#Override
public void visit(PassengerPlane passengerPlane) {
planes.add(passengerPlane);
}
public List<Plane> getPlanes() {
return planes;
}
}
Step 2 - Enable visitors in your classes
Add an abstract method in your base class Plane to accept the visitor:
public abstract class Plane {
//...
abstract void accept(Visitor visitor);
//...
}
Then implement this method in each sub-class to let the Visitor instance visit itself (this). Example for PassengerPlane (same logic for all the other classes):
public class PassengerPlane extends Plane {
//...
#Override
void accept(Visitor visitor) {
visitor.visit(this);
}
//...
}
Step 3 - Adapt your function
Your function can now loop through the list of planes not caring about the type. It will be resolved by the visitor:
public List<Plane> getPlanes() {
PlaneVisitor planeVisitor = new PlaneVisitor(new ArrayList<>());
for (Plane plane : planes) {
plane.accept(planeVisitor);
}
return planeVisitor.getPlanes();
}
Note that you need to add a bit of methods / interfaces to do this. Since your code is very small, you can imagine to leave it like it is even if it's not very "elegant". However, the above example can be of inspiration if your code is actually supposed to do more than what you're showing us.
It can be done in this way by introduced a method that do common part:
private static <T> List<T> createFilteredList(List<Plane> inList, Class<T> clazz) {
List<T> outList = new ArrayList<>();
for (Plane value : inList) {
if (clazz.isInstance(value)) {
outList.add(clazz.cast(value));
}
}
return outList;
}
Then it can be used like this:
public List<PassengerPlane> getPassengerPlanes() {
return createFilteredList(planes, PassengerPlane.class);
}
public List<MilitaryPlane> getPassengerPlanes() {
return createFilteredList(planes, MilitaryPlane.class);
}
public List<ExperimentalPlane> getPassengerPlanes() {
return createFilteredList(planes, ExperimentalPlane.class);
}
So, you have an iterable of Plane as an input.
A Plane can be PassengerPlane, MilitaryPlane or ExperimentalPlane.
What you are trying to do is to filter a collection of planes by a predicate. A predicate is a function that takes a Plane and answers true or false. A filter uses a predicate to figure out whether to include a given item into the result or to skip.
If you are using Java 8 or later version, you can use the Streams API.
https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
Produce a stream from the planes iterable.
Apply filter to it (intermediate operation).
Collect the results to list.
Using Stream API you can convert the methods above into one-liners. Like this:
planes.stream().filter(plane -> plane instanceof MilitaryPlane).collect(toList());
Then, probably, you won't need a separate neat method for it.
But if you want some reusable piece of code, then you have to figure out what is the parameter here. In the code above it is a specific plane implementation:
public List<Plane> filterPlanes(Iterable<Plane> planes, Class<? extends Plane> planeImplementation)
So, you can build a predicate with this parameter:
plane -> planeImplementation.isInstance(plane)
If you have a Plane supertype, you can make the subclasses inherit the getPlanes() method. this.getClass will extract only the planes of the subclass calling the method from the list. This way, you don't have to pass a class to the method, as it can be derived from the subclass that is calling it.
public abstract class Plane {
public Plane(){}
public List<Plane> getPlanes() {
List<Plane> result = new ArrayList<>();
for (Plane plane : planes) {
if (this.getClass().isInstance(plane)) {
result.add(this.getClass().cast(plane));
}
}
return result;
}
}
class PassengerPlane extends Plane {
}
class MilitaryPlane extends Plane {
}
class ExperimentalPlane extends Plane {
}
public class PlaneList {
public String name;
public static ArrayList<Plane> planes = new ArrayList<>();
public PlaneList(){
planes.add(new MilitaryPlane());
planes.add(new MilitaryPlane());
planes.add(new MilitaryPlane());
planes.add(new PassengerPlane());
planes.add(new PassengerPlane());
planes.add(new ExperimentalPlane());
}
}
I tested it like so:
public class Main {
public static void main(String[] args) {
PlaneList list = new PlaneList();
Plane plane = new PassengerPlane();
for(Plane p : plane.getPlanes()){
System.out.println(p.toString());
}
}
}
output:
com.company.PassengerPlane#7dc36524
com.company.PassengerPlane#35bbe5e8
I have the following scenario: two validation Helpers
the StringValidationHelper ...
public class StringValidationHelper {
public static Validation<String> notNull =
SimpleValidation.from(s -> s != null, "must not be null.");
public static Validation<String> moreThan(int size) {
return SimpleValidation.from(
s -> s.length() >= size,
String.format ("must have more than %s chars.", size));
}
... // More methods (lessThan, etc)}
... and NumberValidationHelper.
public class NumberValidationHelper {
public static Validation<Number> notNull =
SimpleValidation.from(n -> n != null, "must not be null");
public static <N extends Number & Comparable<N>> Validation<N> lowerThan(N max){
return SimpleValidation.from(
n -> n.compareTo(max) == -1,
String.format("must be lower than %s.", max));
}
... // More methods like (greaterThan, etc)}
The method from is a static factory method that receives a Predicate and a message to eventual validation fails.
public class SimpleValidation<K> implements Validation<K>{
private Predicate<K> predicate;
private String onErrorMessage;
private SimpleValidation(Predicate<K> predicate, String onErrorMessage) {
this.predicate = predicate;
this.onErrorMessage = onErrorMessage;
}
public static <K> SimpleValidation<K> from(Predicate<K> predicate, String onErrorMessage){
return new SimpleValidation<>(predicate, onErrorMessage);
}
... // Omitted for simplicity
}
Thanks to the Validation interface, you can enjoy a wonderfully smooth interface
#FunctionalInterface
public interface Validation<K> {
... // Omitted for simplicity
default Validation<K> and(Validation<K> other) {
return param -> {
ValidationResult firstResult = this.test (param);
return ! firstResult.isValid()? firstResult: other.test(param);
};
}
... // Omitted for simplicity
}
So I can start, for example, a validation using the closure notNull.
Example: with NumberValidationHelper
public class MyValidate {
void validate(int toValidate) {
notNull.and(lowerThan(100)).test(toValidate).isValid();
}
}
This validation framework I developed based on this article.
Well, notNull enclaves a type-independent behavior, so I'd like to remove the duplication of these two helpers.
I'm not finding an obvious shape without losing the fluid interface.
Because the variable is static, you can not use generics and extend the behavior, for instance.
public abstract class GenericHelper<K> {
public static Validation<K> notNull = SimpleValidation.from(o -> o != null, "must not be null.");
}
Also it does not bother me to type Validation with Object as below:
public abstract class GenericHelper {
public static Validation<Object> notNull = SimpleValidation.from(o -> o != null, "must not be null.");
}
... because in the call chaining, it will give compilation error since the result of notNull will be a Validation< Object > and and will be expecting a Validation< Integer >
notNull.and(lowerThan(100)).test(toValidate).isValid(); //Does not compile
Is there any way to use the Java 8 function features that keep this interface flowing generically, running away from the solutions I've tried above?
thankful
You should relax the generic signature of and, allowing a Validation<T> with a more specific T as parameter, to produce a Validation<T> as result:
default <T extends K> Validation<T> and(Validation<T> other) {
return param -> {
ValidationResult firstResult = this.test(param);
return ! firstResult.isValid()? firstResult: other.test(param);
};
}
Staying with your examples, you still cannot write
void validate(int toValidate) {
notNull.and(moreThan(100)).test(toValidate).isValid();
}
as moreThan returns a Validation<String> which can not test an int, but spotting such errors is what Generics is all about (I suppose, you have another moreThan method in your actual code base which you didn’t include in your question). But the following will now work with your example:
void validate(int toValidate) {
notNull.and(lowerThan(100)).test(toValidate).isValid();
}
Sometimes, you need to test a validation of a more specific type before a more generic validation which still doesn’t work with the method shown above. One solution would be to go the same route as the JDK developers and augment Function.andThen(after) with a Function.compose(before), allowing to swap the roles
default <T extends K> Validation<T> compose(Validation<T> other) {
return param -> {
ValidationResult firstResult = other.test(param);
return ! firstResult.isValid()? firstResult: this.test(param);
};
}
Or you create a static method, which allows both arguments to have a broader type than the resulting Validation:
static <T> Validation<T> and(Validation<? super T> first, Validation<? super T> second) {
return param -> {
ValidationResult firstResult = first.test(param);
return ! firstResult.isValid()? firstResult: second.test(param);
};
}
Note that the static method can be combined with the convenient instance method, so that the caller only needs to resort to the static method when hitting the limitations of the generic signature:
#FunctionalInterface
public interface Validation<K> {
ValidationResult test(K item);
default <T extends K> Validation<T> and(Validation<T> other) {
return and(this, other);
}
static <T> Validation<T> and(Validation<? super T> first,Validation<? super T> second){
return param -> {
ValidationResult firstResult = first.test(param);
return ! firstResult.isValid()? firstResult: second.test(param);
};
}
}
So you can still write
notNull.and(lowerThan(100)).test(toValidate).isValid();
but when hitting the limitation, e.g.
Validation<Object> anotherCriteria;
…
lowerThan(100).and(anotherCriteria).test(toValidate).isValid();
does not work, you can resort to
Validation.and(lowerThan(100), anotherCriteria).test(toValidate).isValid();
Hello I want to do a really simple thing. Just make a template function for any numbers. I actually want as little as ability to "add". In C++ it would be really trivial like this:
template <typename T>
inline T add (T a, T b) {
return a + b;
}
int main(int argc, char** argv){
printf("int: %d\n",add(1,2));
printf("float: %f\n",add(1.1,2.1));
}
In Java I got a tough lesson. I'm new to Java so I believe (and hope) I'm totally wrong and over engineering this. But only thing I come up with was:
public interface IntrfcWowNumbersAdds<T> {
T add(Number v);
}
public class SuperSmartInteger extends Number implements IntrfcWowNumbersAdds<SuperSmartInteger>{
private Integer i;
public SuperSmartInteger(int v) {
i = v;
}
#Override
public String toString(){
return ""+i;
}
#Override
public SuperSmartInteger add(Number v) {
return new SuperSmartInteger(this.intValue()+v.intValue());
}
#Override
public int intValue() {
return i; // thx god for auto(un)boxing
}
#Override
public long longValue() {
return i;
}
#Override
public float floatValue() {
return i;
}
#Override
public double doubleValue() {
return i;
}
}
And note that this crazy wrapper above I would have to do for any number I would like to use template for (eg double, byte etc...)
public class ThreadSafeNum<T extends Number & IntrfcWowNumbersAdds<T>> {
private T num;
public ThreadSafeNum(T n){
num = n;
}
public T add(T v){
// note in here I plan to do some locking...
return num = num.add(v);
}
}
then I can use it as:
SuperSmartInteger i = new SuperSmartInteger(5);
SuperSmartInteger i2 = i.add(6);
System.out.println(""+i2);
ThreadSafeNum<SuperSmartInteger> tsn = new ThreadSafeNum<SuperSmartInteger>(i);
SuperSmartInteger i3 = tsn.add(i2);
I know that when add() would be only adding I can just use + operator and rely on auto(un)boxing. But my add() method is meant to do something extra (like lock).
So how to do it properly? Or is my way correct???
Something like this as the base class:
public abstract class Addable<T extends Number,U extends Addable<T,U>> {
private final T value;
public Addable( final T value ){ this.value = value; }
public T getValue(){ return value; }
public abstract U add( U addend );
}
And this as the sub-class:
public class AddableInteger extends Addable<Integer,AddableInteger> {
public AddableInteger( final Integer value ){
super( value );
}
#Override
public AddableInteger add( final AddableInteger addend ){
java.util.Objects.requireNonNull( addend );
return new AddableInteger( this.getValue() + addend.getValue() );
}
}
Well, the reasons that works in C++ is that the compiler will create as many functions as there are calls in the code, and compile each one independently in order to validate if '+' is a reasonable thing to do in that particular case. This is a little like a case of compiler-assisted duck-typing. In other words, there is no guarantee that type T will have a + operator and only the fact that the compiler will look at the actual call types and create permutations helps you.
Note that there is some risk in letting the compiler "add whatever", since there is no interface or contract that guarantees the semantics to be correct. That is what a class hierarchy brings you.
This is trickier to do in full type safety since inheritance can be complex and the return types need to be somewhat clear. Inheritance is the usual thing so that a virtual method knows how to add its own type, but in this case you can't change the class hierarchy of Number.
You can, nevertheless, do something like this:
public static int addAsInt(Number a, Number b)
{
a.intValue() + b.intValue();
}
And the same for other return types. That will take any two instances of number and generate an output value, assuming which kind of output type you want. Somewhat easier than creating wrapper classes in this particular case.
(I was astonished not to be able to find this question already on stackoverflow, which I can only put down to poor googling on my part, by all means point out the duplicate...)
Here is a toy class that returns the reverse of what you put into it. Currently it works on integers, but would require only very minor changes to work for String.
public class Mirror {
int value;
public int get() {
return reverse(value);
}
private int reverse(int value2) {
String valueString = value + "";
String newString = reverse(valueString);
return Integer.parseInt(newString);
}
private String reverse(String valueString) {
String newString = "";
for (char c : valueString.toCharArray()) {
newString = c + newString;
}
return newString;
}
public void set(int value) {
this.value = value;
}
}
What I'd like to do is make the class generic, but only for, say, two or three possible types. So what I want to write is:
public class Mirror<X, where X is one of Integer, String, or MagicValue {
X value
public X get(){
[...]
What's the correct syntax? My Google-fu is failing me... :(
EDIT: it appears there isn't a correct syntax and it can't appear to be done, so my main question is: why? this seems like the sort of thing that people might want to do before they made the class truly generic...
EDIT EDIT: Managed to work out the why with some labmates today, so added the relevant why answer below.
Unfortunately java does not provide such functionality directly. However I can suggest you the following work around:
Create parametrized class Mirror with private constructor and 3 static factory methods that create instance of Mirror with specific parameter:
public class Mirror<T> {
private T value
private Mirror(T value) {
this.value = value;
}
public static Mirror<Integer> integerMirror(Integer value) {
return new Mirror(value);
}
public static Mirror<String> stringMirror(String value) {
return new Mirror(value);
}
public static Mirror<MagicValue> magicMirror(MagicValue value) {
return new Mirror(value);
}
}
EDIT
Obviously you can (and probably should) separate the class Mirror from its creating, e.g. put the factory methods to separate class MirrorFactory. In this case the constructor should become package protected.
If you want to support large yet limited number of classes you can implement only one generic factory method
public static <T> Mirror<T> createMirror(T value) {
checkTypeSupported(value);
return new Mirror(value);
}
Method checkTypeSupported(value); may use some kind of metadatat (e.g. properties, JSON etc file) to get supported types. In this case however you will not enjoy the compile time validation.
Other solution is to require that all supported types extend certain base class or implement interface:
public class Mirror<T extends MyInterface> {}
But this solution seems does not match your requirements since you need Integer, String and MagicValue.
Various ways to do what you need...Here is another option. No getter or setter.
One instance of Mirror for each type to be handled. One reverse() method.
Tweak as necessary. Add error checking/handling.
public class Mirror<T> {
public T reverse(final T value) {
T result = null;
while (true) {
if (value instanceof String) {
System.out.println("Do for String");
result = value;
break;
}
if (value instanceof Integer) {
System.out.println("Do for Integer");
result = value;
break;
}
if (value instanceof JFrame) {
System.out.println("Do for JFrame");
result = value;
break;
}
throw new RuntimeException("ProgramCheck: Missing handler for type " + value.getClass().getSimpleName());
}
return result;
}
Tester:
final Mirror<String> testerString = new Mirror<>();
testerString.reverse("string");
final Mirror<Integer> testerInteger = new Mirror<>();
testerInteger.reverse(41);
testerInteger.reverse(42);
testerInteger.reverse(43);
final Mirror<JFrame> testerJFrame = new Mirror<>();
testerJFrame.reverse(new JFrame());
Results:
Do for String
Do for Integer
Do for Integer
Do for Integer
Do for JFrame
An alternative would be to just accept the fact that you have no control over the type hierarchy of String/Integer and create an interface to give a common type for the classes you do have control over
public int reverse(int value) {
return Integer.valueOf(new StringBuilder(value + "").reverse()
.toString());
}
public String reverse(String value) {
return new StringBuilder(value + "").reverse().toString();
}
public <T extends Reversible> T reverse(T value) {
value.reverse();
return value;
}
public interface Reversible {
public void reverse();
}
And if you only want one instance of the Mirror class...use a generic method.
public class Mirror {
public <T> T reverse(final T value) {
T result = null;
while (true) {
if (value instanceof String) {
System.out.println("Do for String");
result = value;
break;
}
if (value instanceof Integer) {
System.out.println("Do for Integer");
result = value;
break;
}
if (value instanceof JFrame) {
System.out.println("Do for JFrame");
result = value;
break;
}
throw new RuntimeException("ProgramCheck: Missing handler for type " + value.getClass().getSimpleName());
}
return result;
}
tester:
final Mirror tester = new Mirror();
String s = tester.reverse("string");
Integer i41 = tester.reverse(41);
Integer i42 = tester.reverse(42);
Integer i43 = tester.reverse(43);
JFrame j = tester.reverse(new JFrame());
results:
Do for String
Do for Integer
Do for Integer
Do for Integer
Do for JFrame
You can't bound a generic parameter to range of values. You could however restrict it programatically:
public abstract class AbstractMirror<T> {
T value;
protected AbstractMirror(Class<T> clazz) {
if (clazz != Integer.class && clazz != String.class && clazz != MagicValue.class)
throw new IllegalArgumentException();
}
public abstract T get();
protected abstract T reverse(T value);
}
You can use so-called "witness" types to make the compiler do what you want.
public interface Reversible< T > {
public static final class IntReversible implements Reversible< Integer > {}
public static final class StringReversible implements Reversible< String > {}
public static final class MagicReversible implements Reversible< MagicValue > {}
}
public abstract class Mirror< T, R extends Reversible< T > > {
// ...
}
public class IntMirror extends Mirror< Integer, IntReversible > {
// ...
}
However, the reason your example doesn't make any sense is because you gain virtually nothing from using a generic in this context. What possible algorithm will reverse an integer or a string or a MagicValue without resorting to awful run-time type-checking and casting? The code will be all three reverse algorithms, wrapped with a hideous if-ladder.
So here is the why (worked it out at work)
Generics are always from a subclass, although it looks like
Public class Thing<T> {}
will allow any type in there, really what it's saying is that it will allow any subtype of Object. I.e.
Public class Thing<T extends Object> {}
This is effectively working as inheritance, and indeed, the Oracle Website shows us this happening when the syntactic sugar is removed:
In the following example, the generic Node class uses a bounded type
parameter:
public class Node<T extends Comparable<T>> {
private T data;
private Node<T> next;
public Node(T data, Node<T> next) {
this.data = data;
this.next = next;
}
public T getData() { return data; }
// ...
}
The Java compiler replaces the bounded type parameter T with the first
bound class, Comparable:
public class Node {
private Comparable data;
private Node next;
public Node(Comparable data, Node next) {
this.data = data;
this.next = next;
}
public Comparable getData() { return data; }
// ...
}
...and so the answer turns out that the reason you can't limit the types in this way is because it effectively turns into multiple Inheritance, which is nasty, and which I'm happy to avoid....
Just playing and came up with a sweet way to add functionality to enums in Java Enum toString() method with this.
Some further tinkering allowed me to nearly also add a tidy (i.e. not throwing an exception) reverse look-up but there's a problem. It's reporting:
error: valueOf(String) in X cannot implement valueOf(String) in HasValue
public enum X implements PoliteEnum, ReverseLookup {
overriding method is static
Is there a way?
The aim here is to silently add (via an interface implementation with a default method like I added politeName in the linked answer) a lookup method that does the valueOf function without throwing an exception. Is it possible? It is clearly now possible to extend enum - one of my major problems with Java until now.
Here's my failed attempt:
public interface HasName {
public String name();
}
public interface PoliteEnum extends HasName {
default String politeName() {
return name().replace("_", " ");
}
}
public interface Lookup<P, Q> {
public Q lookup(P p);
}
public interface HasValue {
HasValue valueOf(String name);
}
public interface ReverseLookup extends HasValue, Lookup<String, HasValue> {
#Override
default HasValue lookup(String from) {
try {
return valueOf(from);
} catch (IllegalArgumentException e) {
return null;
}
}
}
public enum X implements PoliteEnum/* NOT ALLOWED :( , ReverseLookup*/ {
A_For_Ism, B_For_Mutton, C_Forth_Highlanders;
}
public void test() {
// Test the politeName
for (X x : X.values()) {
System.out.println(x.politeName());
}
// ToDo: Test lookup
}
You are over-complicating your design. If you are willing to accept that you can invoke a default method on an instance only, there entire code may look like this:
interface ReverseLookupSupport<E extends Enum<E>> {
Class<E> getDeclaringClass();
default E lookup(String name) {
try {
return Enum.valueOf(getDeclaringClass(), name);
} catch(IllegalArgumentException ex) { return null; }
}
}
enum Test implements ReverseLookupSupport<Test> {
FOO, BAR
}
You can test it with:
Test foo=Test.FOO;
Test bar=foo.lookup("BAR"), baz=foo.lookup("BAZ");
System.out.println(bar+" "+baz);
An non-throwing/catching alternative would be:
interface ReverseLookupSupport<E extends Enum<E>> {
Class<E> getDeclaringClass();
default Optional<E> lookup(String name) {
return Stream.of(getDeclaringClass().getEnumConstants())
.filter(e->e.name().equals(name)).findFirst();
}
to use like:
Test foo=Test.FOO;
Test bar=foo.lookup("BAR").orElse(null), baz=foo.lookup("BAZ").orElse(null);
System.out.println(bar+" "+baz);
Here, there's basically two points. Specifically the reason it doesn't compile is 8.4.8.1:
It is a compile-time error if an instance method overrides a static method.
In other words, an enum can't implement HasValue because of the name clash.
Then there's the more general issue we have which is that static methods just cannot be 'overridden'. Since valueOf is a static method inserted by the compiler on the Enum-derived class itself, there's no way to change it. We also can't use interfaces to solve it since they do not have static methods.
In this specific case it's a place where composition can make this kind of thing less repetetive, for example:
public class ValueOfHelper<E extends Enum<E>> {
private final Map<String, E> map = new HashMap<String, E>();
public ValueOfHelper(Class<E> cls) {
for(E e : EnumSet.allOf(cls))
map.put(e.name(), e);
}
public E valueOfOrNull(String name) {
return map.get(name);
}
}
public enum Composed {
A, B, C;
private static final ValueOfHelper<Composed> HELPER = (
new ValueOfHelper<Composed>(Composed.class)
);
public static Composed valueOfOrNull(String name) {
return HELPER.valueOfOrNull(name);
}
}
(Plus, I'd recommend that over catching the exception anyway.)
I realize "you can't do it" is not really a desirable answer but I don't see a way around it due to the static aspect.
The case is the same as you can not create default toString() in interface. The enum already contains signature for static valueOf(String) method therefore you can not override it.
The enum are compile time constant and because of that it really doubtful that they will be extensible someday.
If you want to get the constant via name you can use this:
public static <E extends Enum<E>> Optional<E> valueFor(Class<E> type, String name) {
return Arrays.stream(type.getEnumConstants()).filter( x -> x.name().equals(name)).findFirst();
}
I think I have an answer - it's hacky and uses reflection but seems to fit the brief - i.e. reverse lookup without methods in the enum and without throwing exception.
public interface HasName {
public String name();
}
public interface PoliteEnum extends HasName {
default String politeName() {
return name().replace("_", " ");
}
}
public interface Lookup<P, Q> {
public Q lookup(P p);
}
public interface ReverseLookup<T extends Enum<T>> extends Lookup<String, T> {
#Override
default T lookup(String s) {
return (T) useMap(this, s);
}
}
// Probably do somethiong better than this in the final version.
static final Map<String, Enum> theMap = new HashMap<>();
static Enum useMap(Object o, String s) {
if (theMap.isEmpty()) {
try {
// Yukk!!
Enum it = (Enum)o;
Class c = it.getDeclaringClass();
// Reflect to call the static method.
Method method = c.getMethod("values");
// Yukk!!
Enum[] enums = (Enum[])method.invoke(null);
// Walk the enums.
for ( Enum e : enums) {
theMap.put(e.name(), e);
}
} catch (Exception ex) {
// Ewwww
}
}
return theMap.get(s);
}
public enum X implements PoliteEnum, ReverseLookup<X> {
A_For_Ism,
B_For_Mutton,
C_Forth_Highlanders;
}
public void test() {
for (X x : X.values()) {
System.out.println(x.politeName());
}
for (X x : X.values()) {
System.out.println(x.lookup(x.name()));
}
}
prints
A For Ism
B For Mutton
C Forth Highlanders
A_For_Ism
B_For_Mutton
C_Forth_Highlanders
Added
Inspired by #Holger - this is what I feel is most like what I was looking for:
public interface ReverseLookup<E extends Enum<E>> extends Lookup<String, E> {
// Map of all classes that have lookups.
Map<Class, Map<String, Enum>> lookups = new ConcurrentHashMap<>();
// What I need from the Enum.
Class<E> getDeclaringClass();
#Override
default E lookup(String name) throws InterruptedException, ExecutionException {
// What class.
Class<E> c = getDeclaringClass();
// Get the map.
final Map<String, Enum> lookup = lookups.computeIfAbsent(c,
k -> Stream.of(c.getEnumConstants())
// Roll each enum into the lookup.
.collect(Collectors.toMap(Enum::name, Function.identity())));
// Look it up.
return c.cast(lookup.get(name));
}
}
// Use the above interfaces to add to the enum.
public enum X implements PoliteName, ReverseLookup<X> {
A_For_Ism,
B_For_Mutton,
C_Forth_Highlanders;
}