Hello I'm working on some interesting code and a thought has crossed my mind.
Here is some simplified code:
public interface SomeInterFace<T>
{
public List<T> doSomething();
}
Now, I got another interface which should extend this one for various Objects for instance
public interface OtherInterface extends SomeInterface<Integer>,
SomeInterFace<String>, SomeInterface<Number>, ...
Is there a possiblity to write this "OtherInterface" in a manner where it implements "SomeInterface" with a list of objects?
If you are able to handle any type of type argument for OtherInterface, then as others have suggested, you can write:
public interface OtherInterface<T> extends SomeInterface<T>
However, if you need to implement SomeInterface only for a particular list of type arguments (say, String and Number), then you cannot do that. At compile time, SomeInterface<(anything)> just becomes SomeInterface due to type erasure, and the casting is inserted for you after the compiler makes sure you aren't trying to do any unsafe casts (or you've told it not to check). Therefore, you would be trying to write a class that looked something like this:
public interface OtherInterface extends SomeInterface, SomeInterface {
public List doSomething();
public List doSomething();
}
...which is invalid for obvious reasons!
Hope that helps!
Related
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>");
}
It was stated in comments that, question was creating confusion. So, i have edited the question, let me know, if it is still creating confusion.
Consider below code:
class Employee{}
class ContractEmployee extends Employee{
}
class PermanentEmployee extends Employee{
}
...
Can any one provide the basic difference between below two cases and
when to use which one
Case:1
public <T extends Employee> void empTest(ArrayList<T> list)
public <? extends Employee> void empTest(ArrayList<?> list)
Case:2
public void empTest(ArrayList<? extends Employee> list)
public void empTest(ArrayList<T extends Employee> list)
Not full explanation but you will get starting over here. We need to follow PECS pattern in generics.
PECS stands for Producer Extends and Consumer Super.
in your line below,
public void empTest(ArrayList list)
You are basically giving list which will act as a producer in further use inside that method. Now as you might know, generic is just compile time illusion and will get erased at runtime, your code in mrthod empTest is expecting the List of particular Employee. for example, if you have Fruit as superclass for Orange and Apple, you should not give list of both Orange and Apple to consumer and restrict it to either Apple or Orange. Does it make sense? I guess yes.
First of all, your question is quite legitimate, although with your examples, it's hard to explain / understand the differences.
In all the variants, you want to define a method empTest() that accepts an ArrayList of Employees or subclasses of Employee. You do this with
public void empTest(ArrayList<? extends Employee> list) { ... }
So, what are the other syntax variants meant for? Let's use a different example, as your empTest() method doesn't need anything else.
Say, we want to add an employee to a list using something like addEmp(list, emp);. First idea might be:
public void addEmp(ArrayList<Employee> list, Employee emp) { ... }
But that won't do the job, as you won't be able to pass an ArrayList<ContractEmployee> into the method. Next attempt:
public void addEmp(ArrayList<? extends Employee> list, Employee emp) { ... }
Now it accepts the list, but it also allows you to pass an ArrayList<ContractEmployee> in combination with a PermanentEmployee, and adding a PermanentEmployee to an ArrayList<ContractEmployee> isn't allowed. The compiler will flag the line in the method body where you add the employee, as illegal.
So, what we need here, is to check for using the same type of employee in both places, and that's what the named type parameters can be used for.
public <T extends Employee> void addEmp(ArrayList<T> list, T emp) { ... }
This says: it's ok to pass in an ArrayList of any subtype of Employee, and we call that subtype T. Then the emp argument must also come from the same subtype T (or from a sub-subtype because of normal class inheritance).
If being an Employee or not doesn't make a difference to the method, you can even write
public <T> void addEmp(ArrayList<T> list, T emp) { ... }
To summarize it:
Use the <... extends SomeClass> constructs if need more variability than the plain <SomeClass> construct.
If it's just one place where you need that variability, there's often no need to introduce a name for the subclass, so <? extends SomeClass> in the method's parameter list does the job.
If you need the same subclass in multiple places, you need to give it a name, so use something like <T extends SomeClass> in front of the return-type declaration and use T without the angle brackets in the parameters list.
Regarding syntax:
- If you need to introduce a name for the type parameter, this is done before the return type.
- In the method return type or the method parameter list, you can only use names that already exist, or use unnamed wildcard constructs.
Say I have generics interface :
public interface MyContainer<E>{
E someMethod();
}
Now I have another interface that I want it to be something like this:
public interface MyService<T extends MyContainer<E>>{
// someMethod goes here
}
It doesn't compile of course, it only compiles like this :
public interface MyService<E,T extends MyContainer<E>>{
// someMethod goes here
}
but I don't like it since MyService interface doesn't care about E it only cares that its type parameter extends MyContainer. Any ideas how to solve it?
but I don't like it
Start liking it.
You must declare type parameters before referencing them, just as you would declare variables before using them.
If you care about the type of E, then you must declare it. The interface MyService does care about E if it's referencing it with T extends MyContainer<E>.
If your interface doesn't care about what E is at all, then you could use an unbounded wildcard.
public interface MyService<T extends MyContainer<?>>
However, every implementation of this interface would need to either redeclare T exactly like this or supply a type argument that satisfies this constraint exactly. You wouldn't be able to get rid of that ?.
Your declaring E and using it as you are is the best solution I can see. Having to type an extra E, is no big problem.
I have
1) a basic interface,
2) a few classes that implement this interface,
3) and a generic class that I want to accept, as a parameter, any of the implementing classes
I have tried the following:
public class Foo extends Bar<? extends SomeInterface> {
public Foo(List<? extends SomeInterface> someInterfaceList) {
super(someInterfaceList);
}
...
}
I receive the error No Wildcard Expected. Elsewhere in my code I have statements such as List<? extends SomeInterface> and I receive no errors, so why am I running into problems here? How can I fix this problem and still get the desired results?
I have tried search 'No Wildcard Expected' and 'wildcard in class declaration' to no avail. Thanks in advance!
It sounds like you want to declare a generic type argument that you will reference elsewhere. Wildcards only make sense when the type is used only once, and when declaring a generic type parameter for a class this doesn't make any sense.
Try this instead:
public class Foo<T extends SomeInterface> extends Bar<T> {
public Foo(List<T> someInterfaceList) {
super(someInterfaceList);
}
...
}
As your code was written, there was no way for the user of your class to specify the generic type argument for Bar<>, since Foo wasn't itself a generic type.
Further, if this were possible, it would have been possible for the generic argument to Bar<> to be different than the generic argument to List<> -- as long as both types implemented SomeInterface there would not be a compile-time issue with these definitions, but there could have been a much more confusing error message later when you incorrectly assumed that both types must be the same.
So, declare the generic type once as a generic argument to the Foo class, and then use that type (T in my example) elsewhere to refer to that type instead of accepting some new generic type argument that may not refer to the same type.
I'm not exactly sure what you're looking for, so it might help if you could provide a little more detail. Perhaps you could be a little more specific about how you're planning to instantiate and use these objects?
Anyways, I think you might be looking for something like this:
import java.util.List;
public class Foo<T extends SomeInterface> {
public Foo(List<T> someInterfaceList) {
for (T item : someInterfaceList) {
// do something with each item
}
}
}
class Bar<T> {}
interface SomeInterface<T> {
T x(T y);
}
Or, alternatively, you could just use the following for the constructor:
public Foo(List someInterfaceList) {
but you wouldn't have an easy way of getting the type T of the items in the list.
Good Morning, I am working on some java code and i would like to make something like that:
public class MyClass <E, T extends MyInterface<T<E>>> { }
In this way, T should be both a generic and an instance of a class which implements MyInterface and should be parametric of the type E. But it seems it is not possible in Java, or maybe my approach to the problem is wrong. Thanks in advance.
Update:
First of all thanks to all who replied, now just to make things clear and let You understand what I am trying to achieve, I would like to make a generic container of generic TDAs.
So let's say we need a container of Stacks based on Integers, then I would need to write something like that: MyContainer, of course i need to keep types separated for the insertion part, otherwise i could write MyContainer>. Moreover since all my TDAs implements MyInterface, I would like to set this as bound as well.
So i guess public class MyContainer < E, T extends MyInterface < E>> should do the trick.
This doesn't make sense.
public class MyClass <E, T extends MyInterface<T<E>>> { }
Because of the right-most T. Why would you want to parameterise a class with itself? I think what you really mean is this:
public MyClass<E, T extends MyInterface<E>>
Which essentially means that for every MyClass, you need an E, and a T MyInterface instance which is in turn parameterised to work with E.
I've found beginners can get very carried away with generics, which can result in code which is completely unreadable. Use generics sparingly, and think about whether you really need them in each given instance. If you are finding yourself writing code with multiple levels of nested generics parameterisation, then you're probably doing something wrong in terms of design.
Basically you are trying to do something like this:
class MyClass<T<E>> // T has to be a generic class
or this:
class MyClass<T<Integer>> // T has to be a generic with Integer as parameter
You cannot and shouldnt have to do it, because it's meangingless. It doesn't tell you anything usefull about T. You could use any class as T like this:
DummyClass<T> extends Anything {};
MyClass<DummyClass<Integer>> myClass;
I'm not sure if that's what you want, butI think it could just be
MyClass<E, T extends MyInterface<E>>
T<E> doesn't make much sense to me.
Seems like it should be
public class MyClass <E, T extends MyInterface<E>> { }
Having public class MyClass <E, T extends MyInterface<T<E>>> { }
means that T
should be MyInterface<MyInterface<E>> which doesn't seem likely.
EDIT:
So if you need MyInterface<Class1<Class2>> it seems like it should be something like this:
public class MyClass <A, B extends SomeClass<A>, C extends MyInterface<B> { }
or
public class MyClass <E, T extends MyInterface<SomeOtherClass<E>>> { }