I'm trying to make a map of objects that both implement and extend. The class they are extending (JPanels) I have no control over. I do, however, have control over the interface.
This is what I've tried
Map<MyEnum, ? extends JPanel & MyInterface> myMap;
That, however, is a compile time error.
I could make an abstract class and then make the subclasses extend it, but that seems a bit heavy handed (or is it?).
For the record, I'm using Java 6
That, however, is a compile time error.
Yes. You can't give multiple bounds to wildcards. There is some restriction on where you can use wildcards, and where you can use type parameters. Type parameters can have multiple bounds, but they can't have lower bounds. Wildcards on the other hand, can have lower bounds, but they don't have multiple bounds.
One option is to have the type parameter declared as a part of your class, and give multiple bounds to it:
class MyClass<T extends JPanel & MyInterface> {
Map<MyEnum, T> myMap; // This would work fine now
}
See also:
What is difference between <? extends Object> and <E extends Object>?
References:
Angelika Langer's - Java Generics FAQs
What is a type parameter bound?
What is the difference between a wildcard bound and a type parameter bound?
I could make an abstract class and then make the subclasses extend it, but that seems a bit heavy handed (or is it?).
Not at all: this should work just fine.
Another approach is to add an interface that combines the methods of JPanel of interest to your methods that use myMap, and use it like this:
interface MyPanelInterface extends MyInterface {
void updateUI();
}
...
class MySpecialPanel extends JPanel implements MyPanelInterface {
...
// Implementation for updateUI() comes from JPanel
// You are responsible for implementing the remaining methods.
}
...
Map<MyEnum, ? extends MyPanelInterface> myMap;
...
myMap.get(MyEnum.FIRST).updateUI();
You should create your own class that extends the JPanel and implements MyInterface as you too suggested, then use Map<? extends MyNewSuperClass> myMap;
I never had to do this, but as you suggested you may go ahead and create a new class or interface (based on your need) implementing/extending the interfaces/classes you need and then use it in your Map.
Public Interface IWhatIneed implements Jpanel, MyInterface{
...
}
and then:
Map<MyEnum, ? extends JPanel & MyInterface> myMap;
I hope this would help
Related
I want to have a Class object, but I want to force whatever class it represents to extend class A and implement interface B.
I can do:
Class<? extends ClassA>
Or:
Class<? extends InterfaceB>
but I can't do both. Is there a way to do this?
Actually, you can do what you want. If you want to provide multiple interfaces or a class plus interfaces, you have to have your wildcard look something like this:
<T extends ClassA & InterfaceB>
See the Generics Tutorial at sun.com, specifically the Bounded Type Parameters section, at the bottom of the page. You can actually list more than one interface if you wish, using & InterfaceName for each one that you need.
This can get arbitrarily complicated. To demonstrate, see the JavaDoc declaration of Collections#max, which (wrapped onto two lines) is:
public static <T extends Object & Comparable<? super T>> T
max(Collection<? extends T> coll)
why so complicated? As said in the Java Generics FAQ: To preserve binary compatibility.
It looks like this doesn't work for variable declaration, but it does work when putting a generic boundary on a class. Thus, to do what you want, you may have to jump through a few hoops. But you can do it. You can do something like this, putting a generic boundary on your class and then:
class classB { }
interface interfaceC { }
public class MyClass<T extends classB & interfaceC> {
Class<T> variable;
}
to get variable that has the restriction that you want. For more information and examples, check out page 3 of Generics in Java 5.0. Note, in <T extends B & C>, the class name must come first, and interfaces follow. And of course you can only list a single class.
You can't do it with "anonymous" type parameters (ie, wildcards that use ?), but you can do it with "named" type parameters. Simply declare the type parameter at method or class level.
import java.util.List;
interface A{}
interface B{}
public class Test<E extends B & A, T extends List<E>> {
T t;
}
I know in Java Generics, there is T extends something, but I want T implements something.
Is there any way to achieve this other than using the explicit cast?
For instance, I want to make sure everything passed to sorting algorithm implements Comparable. Implements, not extends.
Thank you.
For generic type bounds, extends isn't limited to classes; you can also use it for interfaces. For example, <T extends Runnable> is OK.
I would like to store a type called App inside a set. App needs to be an enum that implements the App interface.
Set<App> myApps;
I have defined the interface like so...
interface App<T extends Enum<T>> {}
This is almost working, for example, you cannot do this...
class MyClass implements Application<MyClass> {}
However, you can do this...
enum MyEnum implements Application<MyEnum> {}
class Myclass implements Application<MyEnum> {}
Which is wrong. I only want enums to be able to implement this interface, how can I enforce this?
Define a method that allows you to add Elements into the set, BUT use a constraint for that parameter...
public <E extends Enum<E> & IMyInterface> void addToSet(final E value) { }
now after that
addToSet(MyEnum.K) will compile
but
addToSet(new Myclass()) will NOT compile
AFAIK it is not possible to enforce an implementor of an interface to have certain properties such as being an enum.
However, depending on your code and how you use that interface you can make it hard for someone not to make the implementor an enum:
Require T to implement App<T> as well to prevent passing any enum to the class declaration (i.e. App<T extends Enum<T> & App<T>>)
Use additional boundaries when possible (see ΦXocę 웃 Пepeúpa's answer)
Add methods that are already implemented by Enum such as name(), ordinal(), getDeclaringClass() etc.
Let App<T ...> extend Comparable<T>.
When possible call getClass().isEnum() to check that property at runtime. This is not ideal but there are similar solution's that are commonly used such as Collections.unmodifiableSet().
When I extend a class, say class A in class B, i'm implementing all interfaces that class A implements.
In the following,
interface INTF { ... }
class A implements INTF { ... }
class B extends A { .... }
class B, being a descendant of class A, is implementing INTF.
So, what's my gain in declaring class B as
class B extends A implements INTF { .... }
?
//===========================
EDIT:
Java APIs are doing this. Eg.:
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> { ...
what for ?
TIA
There is no difference if your sub class restates that it implements an interface.But there is a huge gain when it comes to Reflection API.I have personally faced it..
When you call B.class.getInterfaces() ,it returns a Class[] containing only those interfaces explicitly declared by the class and not its superclasses,although in reality it is implementing interfaces which are implemented by its superclasses.
To solve it,you need to recursively call the super class and get all the interfaces implemented.Declaring an interface explicitly in your sub class will help you in this case
You don't have to re-declare the interface again. However, there will be differences if you using Java reflections - B.class.getInterfaces().
If you don't re-declare the interface again. B.class.getInterfaces() -- return zero interface
If you re-declare the interface B.class.getInterfaces() - Return one interface
So deciding to re-declare the interface again or Not depending on how you use java reflections on it. For most case, we don't re-declare it again.
You don't have to specify the interface again. You could specify all the implemented methods again, but you don't have to do that either.
If A changes the interface it implements in future B might not need to know about it.
It makes no difference whether you specify that B implements INTF or not, since it must implement it anyway, since A is implementing it.
I'm not sure why Java APIs are doing it. I'm assuming they simply want to make it more clear to the user of LinkedHashMap that it implements Map (otherwise the user would have to look at the declaration of HashMap to find this out).
This question is a follow up from Java Generics Wildcarding With Multiple Classes.
I'm writing an interface like this:
public interface SomeInterface {
public Class<? extends SomeClass implements OtherInterface> getClassForObject(Object object);
}
I know that this is wrong syntax, as is Class<? extends SomeClass & OtherInterface>, and it seems all options.
I can't have the interface do what was suggested in the answer to the question linked above (public interface SomeInterface<T extends SomeClass & OtherInterface>) because implementations of this interface might want to return different things for different inputs.
I also can't create an abstract class that extends SomeClass and implements OtherInterface and have everything extend from that because there are many existing implementations of SomeClass that clients may want to extend from.
Is there any way to force implementations of this interface to return a type that fits both constraints? Besides throwing a runtime exception somewhere else in the code?
You cannot impose multiple restrictions on a wildcard. You can declare a generic type parameter on the method instead of the interface itself, and you can impose multiple restrictions on it. Try:
public interface SomeInterface {
public <T extends SomeClass & OtherInterface> Class<T>
getClassForObject(Object object);
}