3

I want to parameterize a class with an enum, then in the constructor of the class create an Array having the size of the number of elements in the enum.

I created the class like this:

public class LogLine <T extends Enum<T>> {

And then in the constructor I tried writing this:

public LogLine(){
numberOfElementsInEnum = T.values().length;
//then I would create the Array based on the numberOfElementsInEnum variable

It doesn't work. The compiler doesn't see the values method. I tried with T extending String instead of Enum. All static method are then accessible. What is the issue here?

3
  • values is not a static method on Enum. Commented Feb 7, 2019 at 13:24
  • I know it is generated at runtime. But is there any way I can access it like this? I have a workaround, T extends Enum & MyInterface, but I hoped I have some other way to do it. Commented Feb 7, 2019 at 13:26
  • 1
    "But is there any way I can access it like this? I" ... No, not in a type safe way. Generics are implemented in Java by erasure. Generic type information exists mostly at compile time only and is erased at run time. Expressions like new T or instanceof T are illegal in Java because generic type information is largely absent at run time. It seems, though, that your use case does not absolutely require the generic type at run time. Commented Feb 7, 2019 at 13:54

2 Answers 2

5

You have to declare a constructor that accepts the Class:

public LogLine(Class<T> c) {
    numberOfElementsInEnum = c.getEnumConstants().length;
}

See also here: https://docs.oracle.com/javase/tutorial/reflect/special/enumMembers.html

Sign up to request clarification or add additional context in comments.

2 Comments

This works, what I personally don't like is that it seems to duplicate information, T is already declared. If T was a class extending String , for example, this constructor wouldn't be necessary. But indeed, in the doc it says otherwise it is not possible, so I guess this has to do.
"what I personally don't like is that it seems to duplicate information, T is already declared." ... The above is actually a very common pattern in Java (11 and earlier). The Class<T> object is being used as a type token. It is a way to provide run time type information for reifiable types (since generic type information is largely erased at run time).
3

You don't strictly "have to" pass the class to the constructor. In some cases this is a needless inconvenience for the person instantiating your class.

It all depends on your interface.

If your interface is purely a consumer of items (and given that you're logging, I suspect it might be), then you can get away with lazily calculating the number of values at the point when you're actually consuming the item.

class LogLine<T extends Enum<T>>
{
    public void add(T item)
    {
        int numberOfElementsInEnum = item.getDeclaringClass().getEnumConstants().length;
    }
}

We would need know your requirements and to see the rest of your implementation of LogLine to say whether this approach is suitable.

3 Comments

I personally prefer this solution and in my case it would work. Thanks!
you should use .getDeclaringClass() instead of .getClass(), because enum values which have their own overridden method implementations are instances of anonymous subclasses of the enum class
@newacct Good spot! Thank you. If you see a problem like that in one of my answers in future, feel free to edit it yourself.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.