Class<? extends Something>
Here's my interpretation, it's class template but the class ? means the name of the class is undetermined and it extends the Something class.
if there's something wrong with my interpretation, let me know.
There are a few confusing answers here so I will try and clear this up.
You define a generic as such:
public class Foo<T> {
private T t;
public void setValue(T t) {
this.t = t;
}
public T getValue() {
return t;
}
}
If you want a generic on Foo to always extend a class Bar you would declare it as such:
public class Foo<T extends Bar> {
private T t;
public void setValue(T t) {
this.t = t;
}
public T getValue() {
return t;
}
}
The ? is used when you declare a variable.
Foo<? extends Bar>foo = getFoo();
OR
DoSomething(List<? extends Bar> listOfBarObjects) {
//internals
}
You are almost right.
Basically, Java has no concept of templates (C++ has).
This is called generics.
And this defines a generic class Class<> with the generics' attribute being any subclass of Something.
I suggest reading up "What are the differences between “generic” types in C++ and Java?" if you want to get the difference between templates and generics.
You're right
Definition is that the class has to be subtype of Something
It's the same as Class<T>, but there is a condition that T must extends Something
Or implements Something as Anthony Accioly suggested
It can also be class Something itself
You're correct.
In Java generics, the ? operator means "any class". The extends keyword may be used to qualify that to "any class which extends/implements Something (or is Something).
Thus you have "the Class of some class, but that class must be or extend/implement Something".
You're correct.
However usually you will want to name the class that extends Something and write e.g. <E extends Something>. If you use ? you can't do anything with the given type later.
Related
I have a class like this :
public class MyClass <T extends Model1, X extends Model2> {
private CommonMessage<T,X> someMethod() {
....
}
}
Now I have a customized message type MyMessage extends CommonMessage, so I want to know how to have generic type that still having T and X as parameters ? For example :
public class MyClass <M extends CommonMessage, T extends Model1, X extends Model2> {
private M<T,X> someMethod() {
....
}
}
Short answer:
First of all as CommonMessage is generic, extending it in a non-generic way is very bad so you should have done M extends CommonMessage<T, X> And this way because type parameter passed to CommonMessage at class declaration you should not mention this parameter type again at method return type so method return type should be M.
Long answer:
I know you do know this definitions but sometimes we as human forget simple things. First we should consider what generics are created for, with generics we can create classes with different parameter types, this parameter types will be provided when they are extended by another class or when we create new instance of them with new() operator, so when we are writing our class we don't know the exact type for those parameter and we want to delay this decision until later, it is contradictory to something you are doing in your class because here your method is private and you can't change its implementation in your child class(the class which inherited from your class). But know we can change your implementation to something like this which will be compiled well:
public class MyClass<M extends CommonMessage<T, X>, T extends Model1, X extends Model2> {
private M method1(){
...
}
}
public class CommonMessage<T, X>{
}
public class MyMessage<T, X> extends CommonMessage<T, X>{
}
public class Model1{
}
public class Model2{
}
although this implementation will be compiled the problem is that when you are writing your private method(method1) you don't know what is the type of M at the time of writing this class because it will be passed when we want to create new instance of this class or when we inherit another class from this class. so what type of Object do you want to create and return in your method1? the only thing that you know here is that its type is M which extends CommonMessage but you don't know what the exact type of M is at the time of writing your private method(method1)!
And on the top of that you can't delegate this decision to your subclass(because this method is private). Now the question is that why it is allowed and compiled well when we don't know the exact type of M? for a moment forget this question I will make it clear after explaining correct approach. so what is the correct approach? Think about it, the person who write subclass does know exactly what the type of parameter M is and they can create appropriate instance of M in implementation of method1 to return from this method. so why not delegate this decision to subclass and making this method abstract? This completely make senses. in a nutshell we have some implementation like this:
public abstract class MyClass<M extends CommonMessage<T, X>, T extends Model1, X extends Model2> {
public abstract M method1();
}
public class CommonMessage<T, X>{
}
public class MyMessage<T, X> extends CommonMessage<T, X>{
}
public class Model1{
}
public class Model2{
}
now lets get back to our question why first program that I suggested to you compiled well? why we are allowed to have private method that its return type is generic that will be passed at instanciation or inheritance time?
because there are a lot of situations that make it correct and appropriate.
one situation is that our private method call another public method which return the appropriate type, like this:
public abstract class MyClass<M extends CommonMessage<T, X>, T extends Model1, X extends Model2> {
private M method1(){
return method2();
}
abstract M method2();
}
public class CommonMessage<T, X>{
}
public class MyMessage<T, X> extends CommonMessage<T, X>{
}
public class Model1{
}
public class Model2{
}
I've found a number of questions about the java limitation of not being able to implement the same interface twice with different type paramters. (e.g., you can't be Iterable<String> and Iterable<Integer>), but I haven't found any discussion of the following case.
I can say
public class A implements Iterable<Integer> {
public Iterator<Integer> iterator() {
throw new UnsupportedOperationException();
}
}
and I can say
public class A<T> {
T getFoo() {
throw new UnsupportedOperationException();
}
void setFoo(T foo) {
throw new UnsupportedOperationException();
}
}
But it's not clear to me why the following isn't allowed. [See correction below.] It seems like the first case already "drops" the type Integer from the generic specification of A (I didn't have to say A<Integer> in case #1.) So why can't we give A a new type T like this?
public class A<T> implements Iterable<Integer> {
T getFoo() {
throw new UnsupportedOperationException();
}
void setFoo(T foo) {
throw new UnsupportedOperationException();
}
public Iterator<Integer> iterator() {
throw new UnsupportedOperationException();
}
}
By the way, if I change the first case to
public class A<Integer> implements Iterable<Integer> {
I get a "hiding" warning, that the Integer (on the left I presume) is hiding the other type Integer.
Actually, that's not quite right! Changing it to
public class A<String> implements Iterable<Integer> {
says that String is hiding String, not hiding Integer. I'm not even sure what that means. A<String> is allowed with Iterable<Integer> while A<T> is not — that's the crux of my question.
Edit:
I found the problem with my example. For the example, I changed to Iterable<Integer> from our own interface LinkableVertex<OurLinkClass>, thinking it didn't make a difference. OurLinkClass already implemented LinkableEdge<A>. The actual error in Eclipse is:
Bound mismatch: The type OurLinkClass is not a valid substitute for the
bounded parameter <E extends LinkableEdge<? extends LinkableVertex<E>>> of
the type LinkableVertex<E>
(In case it's relevant, this is a recursive pair of interfaces: LinkableVertex<E extends LinkableEdge<? extends LinkableVertex<E>>> and LinkableEdge<V extends LinkableVertex<? extends LinkableEdge<V>>>)
That said, while I haven't got it all cleared up, and I'm not sure why the extra type is required instead of just a raw type warning, the problem may be as simple as changing OurLinkClass to implement LinkableVertex<A<?>>
Sorry about that!
The hiding means that the name used for your generic may be hiding a class: java.lang.String.
There's a huge difference between using generics for class definition and using it for variable (local, parameter, field, etc) definition.
It's not the same to define this:
public class A<String> {
//^----^----- name of your generic used in the class
public String getFoo() {
}
}
Than declaring this:
A<String> a; //here A will work with generics but using java.lang.String class
Also, your class can implement an interface that use generics but that doesn't mean your class must use generics as well. Here's an example:
class MyClass<T> implements Iterable<T> {
//this means MyClass will use a generic of name T and implements Iterable
//to support the same generic T used in the class
}
class AnotherClass implements Iterable<String> {
//this means that AnotherClass doesn't support generics
//and implements Iterable for java.lang.String only.
}
There's not much to add to my question, basically:
class A {}
interface I {}
// how can I get a Set<> of object of type A that implements I?
I tried a few things <A & I>, <A extends I>, <? super A extends I> and a few other but didn't find anything that works, so I'm wondering if this is possible at all. If it isn't I'm curious about the reasoning behind it.
Thanks
Java does not support intersection types, it only supports multiple bounds (as in extends A & I) when declaring type parameters. That is, we can not use a notation like A & I to denote the family of types that extend both A and I, but we can declare a type parameter <T extends A & I> to refer to a specific such type.
If the latter is what you want, a type parameter is a great fit. But if your collection should admit unrelated subtypes of A and I, no nice solutions seem to exist. My best idea is a hack like:
class AISetWrapper {
Set<A> set = new HashSet<>();
<T extends A & I> Set<T> getSet() {
return (Set<T>) set; // unchecked cast that only works because generics are not reified
}
}
which would allow us to write:
class AI1 extends A implements I { }
class AI2 extends A implements I { }
public static void main(String[] args) {
AISetWrapper aiSet = new AISetWrapper();
aiSet.get().add(new AI1()); // compiles
aiSet.get().add(new AI2()); // compiles
aiSet.get().add(new A()); // does not compile
aiSet.get().add(new I() {}); // does not compile
}
You'll have to make A implement I:
interface I {}
class A implements I {}
Set<A> setOfA;
Possible is alsp
class SubA extends A implements I { }
Set <SubA> setOfSubA;
Usage of a class A cannot make it change it's behaviour, as would be indicated by its sudden "implmentation" of I. Where should the implementations of the interface methods come from?
I was able to do the following:
public class MyClass<T extends String & Iterable>{
private Set<T> mySet;
}
And
public <T extends String & Iterable> void myFancyMethod(Set<T> mySet){}
However when I did
private Set<? extends String & Iterable>
I got a compile error of Syntax error on token "&". Seems that you can do the & syntax when declaring a type <T> but not for wildcards <? ...>.
A better discussion of this can be found at: Java Generics Wildcarding With Multiple Classes
You can write your own class:
public class MySet<E extends A & I> extends HashSet<E> {
// blank
}
This will simply ensure that any instances of MySet will contain only objects that extend A and implement I.
// how can I get a Set<> of object of type A that implements I?
You cannot guarantee both in a single generic statement. You can do something like
public void addToSet(I iInstance) {
if(iInstance instanceof A){
//logic to add to your set
}
}
I have written a class which is a base class of Class A and implements an interface of Class B.
Now my compiler is giving a wierd kind of error saying that "The return types of functiona from Class A is not compatible with return type of functiona in class B."
My Code is as below,
public class X extends A implements B
{
}
public class A
{
public Enumeration<String> test(){}
}
public interface B
{
public Enumeration<Object> test();
}
Now I can't understand why the compiler is giving such an error since already String is a type of an object, so what i understood is that automatic type conversion should happen in runtime because of that. Am i right? or my conceptual understanding has gone wierd on me?
If you can change the definition of the interface, you can broaden it and get what you want. The return type would be Enumeration<? extends Object>
What you're trying to do is possible in Java. As Ernest stated, an Enumeration is not a subclass of Enumeration, since Java genercis lacks the concept of variance.
Anyway, you can express you intention using type wildcard. You have to change you interface this way:
public interface B
{
public Enumeration<?> test();
}
Now your code compile fine. Just to let you know, you can also restrict your interface to some other type than Object. For example, if you have to build an interface that return Enumerations
of Number:
class X extends A implements B
{
}
class A
{
public Enumeration<Long> test(){return null;}
}
class C
{
public Enumeration<String> test(){return null;}
}
//This doesn't compile! String does not extend Number
/*class Y extends C implements B
{
}*/
interface B
{
public Enumeration<? extends Number> test();
}
String is a subclass of Object, but Enumeration<String> is not a subclass of Enumeration<Object>. If it were, then I could cast an Enumeration<String> to an Enumeration<Object>, then cast it to an Enumeration<Integer>, all without a warning; but when I tried to use it as an Enumeration<Integer>, I'd get ClassCastExceptions.
Note that Java arrays behave as I've described above, and this is widely considered a significant flaw in the design of the language.
I'm having a problem understanding Java generics and I've simplified to this example
class A<T extends B> {
public void fun(T t) {
}
}
class B {
A a;
public void event() {
a.fun(this);
}
}
The problem is that this generates a warning because A is defined inside B but A is already using it as a generic type.
My first instinct would be that my design is wrong, but in this case I can't change it. A is like a collection and B is like a node in the collection that users are supposed to override. Certain events can happen in B that require reporting back to the parent A.
But since A is defined generically with B, how do I avoid the compile warning inside B.event()
Thanks
The problem is that you're using a raw type on this line:
A a;
You need to specify a type for A's type parameter (T).
You could do something like this:
A<B> a;
but then A might as well not be generic at all, if I'm understanding your statement of the problem. You probably want to do something like this:
class A<T> {
public void fun(T t) {
}
}
class B<T extends B<T>> {
A<B<T>> a;
public void event() {
a.fun(this);
}
}
or even this:
class A<T extends B<? extends T>> {
public void fun(T t) {
}
}
class B<T extends B<T>> {
A<? super B<T>> a;
public void event() {
a.fun(this);
}
}
There are a couple of variations in-between these that are possibly useful as well. The latter example is the most generic (but obviously, also the most complicated).
The class A<T extends B<? extends T>> is ensuring that the type parameter to A is a B. Since B is itself generic, and has that cyclic type parameter, you end up needing to say B<? extends T> (simply saying T won't work here).
The class B<T extends B<T>> is as close as you can get to emulating a "self type" in Java. This lets B talk about the (almost) concrete subtype of itself. When subclassing B you'd say something like "class C extends <B<C>>". This is useful because now the type of C.a is actually A<? super B<C>>.
The ? super bit in the latter example is only useful if you plan on connecting a B with an A that isn't for exactly the same type of B. Thinking in concrete terms, suppose you had an A<Shape> and a Circle (which extends Shape which extends B). The super-wildcard lets you use them together. Without it you'd need an A<Circle> rather than an A<Shape> for your Circle.
Code
public class A<T extends B> {
public void fun(T t) {
}
}
public class B {
A<B> a;
public void event() {
a.fun(this);
}
}
The warning is vanquished.
Reason
Variables of type A should be declared using a specific class type, as suggested by the generic class signature (A<T extends B>).
Resolution
While this resolves the compiler warning, the underlying problem remains. Laurence provides an excellent explanation and solution to the core issue.