Variable containg a class extending Enum and implementing an interface - java

I'd like to do something like this:
private Class<? extends Enum<?> implements IMultiBlockEnum> typeEnum;
How would I do that? The "&" instead of "implements" doesn't work, but Eclipse doesn't give a proper explanation either.
Christopher Klinge

You can only use & when declaring an inferred parameter type, like this:
<T extends Enum & IMultiBlockEnum> void x(T a) {}
Wildcard types may not specify a type intersection as an upper bound.
If you start wondering why it is so, consider what would be the return type of typeEnum.newInstance(). It would have to be both Enum<?> and IMultiBlockEnum at the same time.
For the relevant JLS quote please refer to this answer.
P.S. Another thing that makes little sense in your example is that you end up using two independent wildcards, but obviously want it to be captured as the same type.

You can't extend Enum
Enum types are final by design.

You can create your own class using the original Enum as you like without extend it

If you want to require that the implementation be a certain enum, but also implement an interface, you need to define your own enum "class" implementing the interface(s) , e.g.
public enum MyFancyEnum implements IMultiBlockEnum {
A,B,C,D;
// put code to implement IMultiBlockEnum here, e.g.
public void doTheMultiBlockEnumStuff(String input) {
...
}
}
and then declare your variable as a MyFancyEnum, e.g.
private MyFancyEnum typeEnum = MyFancyEnum.C;

Related

Return class of generic type in default interface method

I have the following interface:
public interface Message<T> {
//some other methods
Class<T> getType();
}
Each implementation is always returning the class of T. For example:
public class StringMessage implements Message<String> {
//other overrides
#Override
Class<String> getType() {
return String.class;
}
}
I would like to make this getType a default method of the interface, but that's not possible since I can't call T.class because of type erasure:
public interface Message<T> {
//some other methods
default Class<T> getType() {
return T.class; //<-- not allowed
}
}
Do you know any trick to avoid having to repeat the return XXX.class on each implementation?
Note that I can't bound T to anything, it must remain unbounded.
Note 1: if the answer is no and well explained, I'll accept it.
Note 2: I found many questions that "sound like this" but are not exactly the same (they usually refer to instances and not to the static interface itself). If you find the right duplicate, don't hesitate to mark it as such and I'll delete it.
Yes. And No. It's complicated.
Before we go down this path, are you sure?
Generally, caring about the <T> in Class<T> is a code smell and means your API design is bad. For example, the T in generics can not represent primitives, but it can represent parameterized types; for example, Stream<List<? extends Foo & Bar>> is fine. An instance of java.lang.Class on the other hand can represent primitives (return int.class;), but cannot represent parameterized types. List<String>.class is not a thing, and there is no instance of j.l.Class that represents "a list of strings". List is as far as it goes.
Generally if you think you want a Class instance what you really wanted is a factory. A factory is the way to abstract away a constructor. Instead of returning a Class<T> this code should probably be wanting a Supplier<T> perhaps or some other interface-of-T that does the job of whatever you're currently using Class<?> for. If you're using that class instance for invoking .getConstructors(), then move that logic into an interface instead. Etcetera.
You've considered all that and still insist.
Generics are erased at runtime, yes, but they still exist in those places where they are part of signatures. In other words, in the extends and implements clauses of class definitions, in the types of fields, and in the parameters and return type of any method definition. The JVM considers these comments (the JVM does not know or care about generics in the slightest, it is purely something javac and editors worry about), but they are available in the class file and therefore you can theoretically at least query it.
But, and this is very important, only the literal thing that is there, at compile (write) time, is available.
So, yes, you CAN retrieve the String bit in public class StringMsg implements Message<String>. But what if you write public class GeneralMsg<T> implements Message<T>? Then all you get is T. What if you write public class ListOfStringsMessage implements Message<List<String>>? You can obtain List<String> here, but that notion cannot be conveyed in terms of a value of type java.lang.Class.
The way to do this, is to use the method .getGenericInterfaces(). But, this is a very low level method that just gets you literally what you asked for: The list of interfaces (with any type params preserved) that the class you invoked this on directly implements. Therefore, you need to write a ton of code. After all, maybe you have this:
class StringMessage implements Message<String> {}
class UnicornStringMessage extends StringMessage {}
or even
interface StringMessage implements Message<String> {}
class MyStringMessage implements StringMessage {}
You need to write lots of code to trawl through the entire class hierarchy. Hence, writing it all out in this answer is a bridge too far. This merely handles the very simplest case, and will fail on all others. So, you need to take this code and expand on it, and add:
Detect a misuse, such as writing class GenericMsg<T> implements Message<T>.
Detect hierarchy usage (or alternatively, disallow it with a proper message, if you prefer that) by way of having an interface that extends Message<Concrete>, and then having a class that implements the subinterface.
Same, but for interface SubIntf<T> implements Message<T> and then having a class Foo implements SubIntf<String>.
Same, but with the class hierarchy: class MyMsg implements Message<String> + class MySubMsg extends MyMsg.
Taking that into consideration:
default Class<T> getType() {
for (Type i : getClass().getGenericInterfaces()) {
if (!(i instanceof ParameterizedType pt)) continue;
if (!pt.getRawType().equals(Message.class)) continue;
Type param = pt.getActualTypeArguments[0];
if (param instanceof Class<?> paramC) return paramC;
}
throw new IllegalArgumentException("Programmer bug: " + getClass() + " must implements Message<ConcreteType>");
}

Angelika Langer Enum<E extends Enum<E>> decoding

As per my Previous Question, I am reading the article from Angelika Dissecting Enum. Except for the points that a type can only be instantiated for its subtypes and the subtypes do inherit some common methods, I am not able to understand the article.
What is the meaning of abstract Enum class declared in this way? How is it helpful?
The document in the last part has described three aspects, can someone explain them in easier terms to me?
I do see in the code sketch the Enum class is declaring the compareTo method. When Enum is implicitly implementing Comparable interface. Why do it needs to define its own compareTo method?
Seems like it is a concept of recursive generics. What does recursive generics exactly mean? After doing a bit of R&D and understanding my last question answer, I understand that it forces the class to be parameterized on itself.
Still, a detailed explanation would be useful.
I think the main benefit of declaring generic types as Type<E extends Type<E>> is that such generic classes will make subclasses to inherit methods which return or accept arguments with subtype's type. Such methods in java.lang.Enum are:
public final int compareTo( E o) { ... }
public final Class< E > getDeclaringClass() { ... }
So, if we declare the enum Color, that implicitly means:
public class Color extends Enum<Color>
so in this instantiation of Enum the type paramater E is assigned the type argument Color, so the above methods will look like these:
public final int compareTo(Color o) { ... }
public final Class<Color> getDeclaringClass() { ... }
When saying something like Enum<Color extends Enum<Color>>, that sounds like you are declaring a generic type parameter Color that makes sure that it extends Enum with a type parameter matching Color.
But that isn't where generic type parameters for a class are declared. You must declare them next to the class name; you can only use them later in the extends clause. E.g.
// Use "extends" here ... not here.
public class MyClass<E extends MyClass<E>> extends MySuperClass<E>
In this example, you are declaring the class Color to be the value of the generic type parameter that is already defined on Enum.

Clarification about wildcards (Generics) in Java

I have recently started reading Core Java. But I am having a hard time grasping the concept of wildcards.
Specifically, I'm confused about the difference between the following:
public class A<T extends {some_class}> {/*...*/}
and
public class A<? extends {some_class}> {/*...*/}
Can anyone help me understand the difference if there is at all?
The difference is that you cannot use the ? elsewhere while you can use T. For example:
public class Foo<T extends Number> {
T value; // you can declare fields of type T here
int foo() {
// Since you said T extends Number, you can call methods of Number on value
return value.intValue();
}
}
So why would you use ? at all? If you don't need the type. It wouldn't make sense to use it in a class definition any way that I can think of. But you could use it in a method like this:
int getListSize(List<?> list) {
return list.size();
}
Any kind of method where you're more interested in the overall class and it has a method that doesn't involve the paramaterized type would work here. Class.getName() is another example.
They are the same, except with the wildcard you can't refer to the type in the code of your class. Using T names the type.
In generic code, the question mark (?), called the wildcard, represents an unknown type. The wildcard can be used in a variety of situations: as the type of a parameter, field, or local variable; sometimes as a return type (though it is better programming practice to be more specific). The wildcard is never used as a type argument for a generic method invocation, a generic class instance creation, or a supertype.
The Type T is a defined type or known type
Hope this helps
? extends some class or T extends some_class
means some_class itself or any of its children and anything that would work with instanceof some_class.
As per conventions T is meant to be a Type and ? is unknown type.

Access class name of parameterized type

I have a parameterized class. I would like to get the name of the class represented by the class name. For instance, what I want to do is this:
public T foo(){
System.out.println(T.class.getName());
}
You can't do it this way, since T isn't known at compile time. You could achieve something similar like so:
public void foo(T t) {
System.out.println(t.getClass().getName());
}
Note that this takes an instance of T and would print out the name of its dynamic type.
Whether or not this is a good enough substitute depends on your use case.
Java generics don't work that way. If you have any bounds on T, you can access the bounds by querying the type variable definition. E.g.:
public class Foo<T extends Bar>{}
will let you get at Bar, but not at the subtype of Bar you are actually using. It doesn't work, sorry.
Read the Java Generics FAQ for more info.
BTW: One common solution to this problem is to pass the subtype of T into your class, e.g.
public T foo(Class<? extends T> tType){
System.out.println(tType.getName());
}
I know it's cumbersome, but it's all Java generics allow.
public T foo(T t){
System.out.println(t.getClass().getName());
}

Java formal type parameter definition (Generics)

I'd like to define a generic type, whose actual type parameter can only be
One of the numeric primitive wrapper classes (Long, Integer, Float, Double)
String
I can meet the first requirement with a definition like this
public final class MyClass<T extends Number> {
// Implementation omitted
}
But I can't figure out how to meet both of them. I suspect this is not actually possible, because AFAIK there's no way to specify "or" semantics when defining a formal type parameter, though you can specify "and" semantics using a definition such as
public final class MyClass<T extends Runnable & Serializable > {
// Implementation omitted
}
Cheers,
Don
Java generics does not support union types (this parameter can be A OR B).
On a related note that may be of interest to some, it does support multiple bounds, if you want to enforce multiple restrictions. Here's an example from the JDK mentioned in the Java generics tutorial:
public static <T extends Object & Comparable<? super T>> T max(Collection<? extends T> coll)
You could use factory methods for all supported types and make the constructor private/protected. You have to fix the generic type in the constructor anyway so that it makes sense, so you could probably code it like this:
public final class MyClass<T> {
public static MyClass<Integer> newInstance(int i) {
return new MyClass<Integer>(i);
}
public static MyClass<String> newInstance(String s) {
return new MyClass<String>(s);
}
//More factory methods...
protected MyClass(T obj) {
//...
}
}
Or if you do not want the constructor parameter, something like this:
public final class MyClass {
public static MyClass newIntegerInstance() {
return new MyClass();
}
//...
}
As erickson stated, the common implementation can rely only on Object anyway, so the only restriction is, that you can create other implementations for other types besides the primitive and String.
While generics won't work here, a base type with derived types for Number and String will. Since a generic type would have erased to Object anyway, any functionality you would have put there can go in an abstract base class. You're likely to need only a type-specific accessor on the subclass to get the value.
Also, be careful with the Number class. It's not limited to boxing the primitive types, as anyone can extend it—e.g., BigInteger.
Interesting question, it boggled me a bit. However apparently this is impossible. I tried several different hacks, none really work.
Maybe you could do what follows:
Make MyClass<T> a package-default class, invisible to other components, or at least with a package-default ctors only, so that it cannot extended or instantiated outside the package.
Create two public classes in the package of MyClass<T>:
MyNumericClass<T extends Number> extends MyClass<T>
MyStringClass extends MyClass<String>
This way all subclasses of MyClass will be limited to those parametrized with a Number subclass or String.

Categories