How would one go about dealing with generic enums in Java? - java

So, I have an abstract class like:
public abstract class AbstractParent <E extends Enum<E>> {...}
Somewhere in a non-abstract method inside AbstractParent, I would like to iterate over the values of E. Is this possible?
For a better example:
public abstract class AbstractParent <E extends Enum<E>> {
...
protected void doSomething() {
//iterate over the values of E and perform an action using them
}
}
public class Child extends AbstractParent<Child.Index> {
public static enum Index {
...
}
public Child() {
super();
this.doSomething(); //this should iterate over Index's values
}
}
EDIT:
So, thanks to mdma, this works awesomely:
public abstract class AbstractParent <E extends Enum<E>> {
...
protected void doSomething() {
//iterate over the values of E and perform an action using them
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
Type t = pt.getActualTypeArguments()[0];
E[] enumValues = ((Class<E>)t).getEnumConstants();
// enumValues is now an iterable array of the values inside Index
}
}
public class Child extends AbstractParent<Child.Index> {
public static enum Index {
...
}
public Child() {
super();
this.doSomething(); //this should iterate over Index's values
}
}
Thanks LOADS to mdma, you deserve more points than I can give.

EDIT2: Generics on superclasses and interfaces are not erased. You can get the generic type at runtime and use that to fetch the enum values. See Class.getGenericSuperclass. This will save you having to pass the value or a class in the constructor.
Original:
You cannot do this with generics. However, if you pass in the corresponding class also, e.g. a constructor like
AbstractParent(Class<E> enumClass)
{
this.enumClass = enumClass;
}
Then you can use that to fetch the corresponding enum values via
public E[] getValues()
{
return this.enumClass.getEnumConstants();
}
EDIT: Although the clients are not professional programmers, the compiler will ensure the correct class is passed. You can also make the usage clear by providing examples, and unit tests.
You could also have the constructor take and actual value of the Enum, and derive the class from that. This might be simpler to use, since the parameter is then an E rather than the more "scary" Class<E>.
E.g.
AbstractParent(E enumValue)
{
this.enumClass = enumValue.getClass();
}

Since generics are erased at runtime, the only way this is possible is by having a constructor that requires a Class<E> parameter on which you can then call getEnumConstants().

Related

How do I implement a generic class with a generic type parameter without specifying the value for the type

Let's say I have
public abstract class GenericClass<T> {
abstract T getValue(T value);
}
I want to sub-class this with a class that works for any List<U>. Is it possible to implement this without having to do #SuppressWarnings("rawtypes") and #SuppressWarnings("unchecked")? For example, this works:
public class ListClass extends GenericClass<List> {
#Override
List getValue(List value) {
return value;
}
}
but I have to use #SuppressWarnings("rawtypes") to get ride of the compiler warnings. I want to avoid doing ListClass<U> extends GenericClass<List<U>> because my ListClass doesn't actually care what U is so client's shouldn't have to have separate instances for ListClass<Double> and ListClass<Integer> (for example).
Note: my real code uses CompletableFuture and is obviously more complicated and I end up having to add ugly casts and #SuppressWarnings("unchecked") when I try to use the extension methods off of CompletableFuture such as future.exceptionallyAsync((e) -> handleException((Throwable) e)).
Ideally I would want something like this to work (but it doesn't recognize the method as a valid override):
public class ListClass extends GenericClass<List> {
#Override
<U> List<U> getValue(List<U> value) {
return value;
}
}

Using self-referential generic types in Java

Consider the following Java method:
<T extends List<T>> List<T> getMyList() {
return Collections.emptyList();
}
I can assign its output to a variable with a raw type, like so:
List x = getMyList();
List<List> y = getMyList();
But, I can't think of any way to assign its output to a fully parameterized type. In particular, I can't think of a non-raw, concrete type T that would satisfy List<T> z = getMyList();
Can we create such a T ?
If not, why not?
For context, I created this question while trying to understand how Enums are implemented in Java.
Here's an example of a concrete type that both works and starts to hint at a possible use-case (registration of some sort). The type consists acts like both an instance of some type, and as a container for all instances of that type.
public class WeirdEnum extends AbstractList<WeirdEnum> {
private static List<WeirdEnum> underlyingList = new ArrayList<>();
#Override
public WeirdEnum get(int index) { return underlyingList.get(index); }
#Override
public int size() { return underlyingList.size(); }
static <T extends List<T>> List<T> getAList() {
return Collections.emptyList();
}
public WeirdEnum() {
underlyingList.add(this); // Sufficient for our example but not a good idea due to concurrency concerns.
}
static List<WeirdEnum> foo = WeirdEnum.getAList();
}
Not sure if I fully understand your question, but here's an example:
class Example<T> implements List<Example<T>> {
...
}
...
List<Example<String>> list = getMyList();
Every enum in Java extends from the base-enum-class Enum<T extends Enum<T>>, where T is the actual type of the implementing enum.
When writing SomeClass<T extends SomeClass<T>> you can enforce that the type-parameter is always the implementing class itself.
Let's say you have this interface:
public interface MyInterface<T extends MyInterface<T>> {
T getSelf();
}
And this implementing class:
public class MyClass implements MyInterface<MyClass> {
public MyClass getSelf() {
return this;
}
}
In MyClass it is not possible to use any other type-parameter than MyClass itself.

Please help me understand "Class Foo<E extends Foo<E>>" [duplicate]

I thought I understood Java generics pretty well, but then I came across the following in java.lang.Enum:
class Enum<E extends Enum<E>>
Could someone explain how to interpret this type parameter? Bonus points for providing other examples of where a similar type parameter could be used.
It means that the type argument for enum has to derive from an enum which itself has the same type argument. How can this happen? By making the type argument the new type itself. So if I've got an enum called StatusCode, it would be equivalent to:
public class StatusCode extends Enum<StatusCode>
Now if you check the constraints, we've got Enum<StatusCode> - so E=StatusCode. Let's check: does E extend Enum<StatusCode>? Yes! We're okay.
You may well be asking yourself what the point of this is :) Well, it means that the API for Enum can refer to itself - for instance, being able to say that Enum<E> implements Comparable<E>. The base class is able to do the comparisons (in the case of enums) but it can make sure that it only compares the right kind of enums with each other. (EDIT: Well, nearly - see the edit at the bottom.)
I've used something similar in my C# port of ProtocolBuffers. There are "messages" (immutable) and "builders" (mutable, used to build a message) - and they come as pairs of types. The interfaces involved are:
public interface IBuilder<TMessage, TBuilder>
where TMessage : IMessage<TMessage, TBuilder>
where TBuilder : IBuilder<TMessage, TBuilder>
public interface IMessage<TMessage, TBuilder>
where TMessage : IMessage<TMessage, TBuilder>
where TBuilder : IBuilder<TMessage, TBuilder>
This means that from a message you can get an appropriate builder (e.g. to take a copy of a message and change some bits) and from a builder you can get an appropriate message when you've finished building it. It's a good job users of the API don't need to actually care about this though - it's horrendously complicated, and took several iterations to get to where it is.
EDIT: Note that this doesn't stop you from creating odd types which use a type argument which itself is okay, but which isn't the same type. The purpose is to give benefits in the right case rather than protect you from the wrong case.
So if Enum weren't handled "specially" in Java anyway, you could (as noted in comments) create the following types:
public class First extends Enum<First> {}
public class Second extends Enum<First> {}
Second would implement Comparable<First> rather than Comparable<Second>... but First itself would be fine.
The following is a modified version of the explanation from the book Java Generics and Collections:
We have an Enum declared
enum Season { WINTER, SPRING, SUMMER, FALL }
which will be expanded to a class
final class Season extends ...
where ... is to be the somehow-parameterised base class for Enums. Let's work
out what that has to be. Well, one of the requirements for Season is that it should implement Comparable<Season>. So we're going to need
Season extends ... implements Comparable<Season>
What could you use for ... that would allow this to work? Given that it has to be a parameterisation of Enum, the only choice is Enum<Season>, so that you can have:
Season extends Enum<Season>
Enum<Season> implements Comparable<Season>
So Enum is parameterised on types like Season. Abstract from Season and
you get that the parameter of Enum is any type that satisfies
E extends Enum<E>
Maurice Naftalin (co-author, Java Generics and Collections)
This can be illustrated by a simple example and a technique which can be used to implement chained method calls for sub-classes. In an example below setName returns a Node so chaining won't work for the City:
class Node {
String name;
Node setName(String name) {
this.name = name;
return this;
}
}
class City extends Node {
int square;
City setSquare(int square) {
this.square = square;
return this;
}
}
public static void main(String[] args) {
City city = new City()
.setName("LA")
.setSquare(100); // won't compile, setName() returns Node
}
So we could reference a sub-class in a generic declaration, so that the City now returns the correct type:
abstract class Node<SELF extends Node<SELF>>{
String name;
SELF setName(String name) {
this.name = name;
return self();
}
protected abstract SELF self();
}
class City extends Node<City> {
int square;
City setSquare(int square) {
this.square = square;
return self();
}
#Override
protected City self() {
return this;
}
public static void main(String[] args) {
City city = new City()
.setName("LA")
.setSquare(100); // ok!
}
}
You are not the only one wondering what that means; see Chaotic Java blog.
“If a class extends this class, it should pass a parameter E. The parameter E’s bounds are for a class which extends this class with the same parameter E”.
This post has totally clarified to me these problem of 'recursive generic types'.
I just wanted to add another case where this particular structure is necessary.
Suppose you have generic nodes in a generic graph:
public abstract class Node<T extends Node<T>>
{
public void addNeighbor(T);
public void addNeighbors(Collection<? extends T> nodes);
public Collection<T> getNeighbor();
}
Then you can have graphs of specialized types:
public class City extends Node<City>
{
public void addNeighbor(City){...}
public void addNeighbors(Collection<? extends City> nodes){...}
public Collection<City> getNeighbor(){...}
}
If you look at the Enum source code, it has the following:
public abstract class Enum<E extends Enum<E>>
implements Comparable<E>, Serializable {
public final int compareTo(E o) {
Enum<?> other = (Enum<?>)o;
Enum<E> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
#SuppressWarnings("unchecked")
public final Class<E> getDeclaringClass() {
Class<?> clazz = getClass();
Class<?> zuper = clazz.getSuperclass();
return (zuper == Enum.class) ? (Class<E>)clazz : (Class<E>)zuper;
}
public static <T extends Enum<T>> T valueOf(Class<T> enumType,
String name) {
T result = enumType.enumConstantDirectory().get(name);
if (result != null)
return result;
if (name == null)
throw new NullPointerException("Name is null");
throw new IllegalArgumentException(
"No enum constant " + enumType.getCanonicalName() + "." + name);
}
}
First thing first, what does E extends Enum<E> mean? It means the type parameter is something that extends from Enum, and isn't parametrized with a raw type (it's parametrized by itself).
This is relevant if you have an enum
public enum MyEnum {
THING1,
THING2;
}
which, if I know correctly, is translated to
public final class MyEnum extends Enum<MyEnum> {
public static final MyEnum THING1 = new MyEnum();
public static final MyEnum THING2 = new MyEnum();
}
So this means that MyEnum receives the following methods:
public final int compareTo(MyEnum o) {
Enum<?> other = (Enum<?>)o;
Enum<MyEnum> self = this;
if (self.getClass() != other.getClass() && // optimization
self.getDeclaringClass() != other.getDeclaringClass())
throw new ClassCastException();
return self.ordinal - other.ordinal;
}
And even more importantly,
#SuppressWarnings("unchecked")
public final Class<MyEnum> getDeclaringClass() {
Class<?> clazz = getClass();
Class<?> zuper = clazz.getSuperclass();
return (zuper == Enum.class) ? (Class<MyEnum>)clazz : (Class<MyEnum>)zuper;
}
This makes getDeclaringClass() cast to the proper Class<T> object.
A way clearer example is the one that I answered on this question where you cannot avoid this construct if you want to specify a generic bound.
According to wikipedia, this pattern is called Curiously recurring template pattern.
Basically, by using the CRTP pattern, we can easily refer to subclass type without type casting, which means by using the pattern, we can imitate virtual function.

How do I properly extend this abstract class?

Hi I'm inexperience with Java. I understand the concepts of inheritance but I think the syntax is eluding me. I'm seeking some help to get me started in extending this abstract class:
I need to create a concrete object from it.
What this class should do is take in a type during initialization and store a list of objects of that type. Sort them and then return a list of n top objects when showTopN is called.
I have not started implementing the logic yet.
abstract class Foo<T extends Comparable<T>> {
int n;
Foo(int n){ // constructor; sets object property n
this.n = n;
}
abstract void push(T object); //object method to store a new object in the list
abstract List<T> showTopN(); // object method to return top n entries in the list, sorted.
}
I've tried to extend this into a concrete object this way:
class ConcreteFoo extends Foo {
private List<Foo> fooList;
public void push(Foo object) {
}
#Override
public List<Foo> showTopN() {
return fooList;
}
#Override
public int compareTo(ConcreteFoo other) {
return 0;
}
}
But the compiler is complaining that I have not overridden the push method.
What is wrong?
There are two things going on here. One is the "abstractness" of Foo, but the other is the Generics. You have neglected the generics aspect.
If you know the type of object that your Concrete foo cares about, you can just use that:
class ConcreteFoo extends Foo<SomeKnownClass> {
private List<SomeKnownClass> list = new ArrayList<SomeKnownClass>();
void push(SomeKnownClass skc) {}
List<SomeKnownClass> showTopN() { return list; }
}
Now, if you don't know the type of it, you can still use generics:
class ConcreteFoo<T extends Comparable<T>> extends Foo<T> {
private List<T> list = new ArrayList<T>();
void push(T skc) {}
List<T> showTopN() { return list; }
}
Note that neither Foo nor ConcreteFoo implement Comparable, so you don't need the compareTo method.
The push method specifies that it will accept a T object, which is Foo's generic type, which you haven't declared. If you want Foo to be a List of itself, which I'm not certain that you do, you'd have to declare it as
class ConcreteFoo extends Foo<Foo> {
But I think you need to re-examine your basic principles.
You're conflating a container with the objects that it contains. The class structure that you want is something like:
class Foo implements Comparable<Foo> { ... }
abstract class GenericContainer<T> {
abstract void push(T object); //object method to store a new object in the list
abstract List<T> showTopN(); // object method to return top k entries in the list, sorted.
}
class FooContainer extends GenericContainer<Foo> {
private List<Foo> fooList;
...
}
Your showTopN method can then be something like:
public List<Foo> showTopN() {
return Collections.sort(fooList).subList(0, n);
}

Avoiding Java Type Erasure

Is there a way one could avoid type erasure and get access to a type parameter?
public class Foo<T extends Enum<?> & Bar> {
public Foo() {
// access the template class here?
// i.e. :
baz(T.class); // obviously doesn't work
}
private void baz(Class<T> qux) {
// do stuff like
T[] constants = qux.getEnumConstants();
...
}
}
I need to know about T, and do things with it. Is it possible, and if so, how can it be done without passing in the class in the constructor or anywhere besides the parameter?
EDIT: The main purpose of this question is to find out if there is any practical way around type erasure.
AFACT, there is no practical way around type erasure because you can't ask for something which the runtime doesn't have access to. Assuming of course you agree that sub-classing generic classes for each enum which implements Bar interface is a practical work around.
enum Test implements Bar {
ONE, TWO
}
class Foo<T> extends FooAbstract<Test> {
public Foo() {
ParameterizedType genericSuperclass =
(ParameterizedType) getClass().getGenericSuperclass();
baz((Class<T>) genericSuperclass.getActualTypeArguments()[0]);
}
private void baz(Class<T> qux) {
T[] constants = qux.getEnumConstants();
System.out.println(Arrays.toString(constants)); // print [ONE, TWO]
}
}
interface Bar {
}
class FooAbstract<T extends Enum<?> & Bar> {
}
If you're willing/able to hand a class token to the constructor:
public Foo(Class<T> clazz) {
baz(clazz);
}
private void baz(Class<T> qux) {
// ...
}
That way, you can produce objects of type T with Class.newInstance(), attempt to cast arbitrary objects to T using Class.cast(), etc.
What do you intend to do in baz()?
As pholser points out in his answer, the only way to achieve this is by passing in the Class object representing the type T. It's because of Type Erasure that something like T.class isn't possible because T is erased before runtime.
You seem resistant against passing in the Class object, but it's the only way to use the method getEnumConstants(). Here is a self contained example:
public class Foo<T extends Enum<?> & Bar> {
final Class<T> clazz;
public Foo(Class<T> clazz) {
this.clazz = clazz;
}
public void baz() {
T[] constants = clazz.getEnumConstants();
System.out.println(Arrays.toString(constants));
}
public static void main(String[] args) {
new Foo<MyEnum>(MyEnum.class).baz(); //prints "[A, B, C, D]"
}
}
public interface Bar { }
public enum MyEnum implements Bar { A, B, C, D; }
Use a super type token as proposed by Neil Gafter and used by libraries like guice for this purpose.
See http://gafter.blogspot.com/2006/12/super-type-tokens.html for the original description and I've check out the guice source for CA radio life working implementation.
there is another q which has an answer with worked example inline here How can I pass a Class as parameter and return a generic collection in Java?
In some cases you can use a workaround suggested by Richard Gomes.
When creating instances of anonymous classes, the type parameter class info is available.
class A<T>
{
A()
{
java.lang.reflect.ParameterizedType parameterizedType = (java.lang.reflect.ParameterizedType) (this.getClass().getGenericSuperclass());
System.out.println(parameterizedType.getActualTypeArguments()[0]);
}
}
public class Example {
public static void main(String[] args) {
A<String> anonymous = new A<String>() {}; // prints java.lang.String
}
}
Note that multiple instances created this way will be of different anonymous classes, and if that's a problem you might want a class A_String_Factory with a createNew() function based on clone to replace the calls to new.

Categories

Resources