Reputation: 8903
I read the document on Java Generics, and it said that the java 'extends' keyword in connection with Generics means and class which implements that interface.
Based on this, i tried to create generic classes to understand this further. Here is my sample code.
Interface code:
package com.vipin.generics.doubtclear;
public interface DemoInterface1<T> {
void display(T t);
}
Now, I created few simple classes which implements this interface:
package com.vipin.generics.doubtclear;
class myClass<T> implements DemoInterface1<T> {
public myClass(T t) {
}
@Override
public void display(T t) {
System.out.println("Inside display method of myClass, object is ---> "+t);
}
}
class myClass1<T> implements DemoInterface1<T> {
public myClass1(T t) {
}
@Override
public void display(T t) {
System.out.println("Inside display method of myClass1, object is ---> "+t);
}
}
Here is the class which has main, which tries to create objects:
public class DoubtClear1 {
static <T extends DemoInterface1<T>> void myFunc(T t) {
t.display(t);
}
public static void main(String[] args) {
myClass<Integer> iObj = new myClass<Integer>(1);
myClass1<Integer> iObj1 = new myClass1<Integer>(1);
DoubtClear1.myFunc(iObj);
}
}
In main I am creating myClass<Integer>
and myClass1<Integer>
objects.
As per my understanding of 'extends' keyword when applied to Generics myFunc()
is capable of taking any object reference which implements DemoInterface1
interface .
This is what i am doing in call ==> DoubtClear1.myFunc(iObj);
However, this is giving me compile-time error:
The method myFunc(T) in the type DoubtClear1 is not applicable for the arguments (myClass<Integer>)
This is really confusing. I am doing what is written in the documentation on this topic and it is failing. I am not sure if my understanding of this topic is correct.
From what I feel, Generics is confusing, and it takes repeated study to really get what this is.
Any information to clear this point really appreciated.
Upvotes: 1
Views: 1606
Reputation: 81539
Currently you are evaluating the condition
static <myClass1<Integer> extends DemoInterface1<myClass1<Integer>> void myFunc(myClass1<Integer> t) {
Which is not true, myClass1<Integer>
does not match DemoInterface1<myClass1<Integer>>
, because Integer
generic condition of myClass1
is not myClass1<Integer>
(because it is Integer
).
You should instead do the following
static <T> void myFunc(DemoInterface1<T> interface, T t) {
interface.display(t);
}
As such, the following should work
myClass<Integer> iObj = new myClass<Integer>(1);
myClass1<Integer> iObj1 = new myClass1<Integer>(1);
DoubtClear1.myFunc(iObj, 1);
EDIT: If you wanted to add a new interface that extends from DemoInterface1
then that would change the myFunc
parameters like so
static <T, N extends DemoInterface1<T>> void myFunc(N interface, T t) {
interface.display(t);
}
Which I assume is originally what you wanted.
EDIT2:
The error in your code didn't happen because of this:
<T extends XYZ>
This indeed means that T
implements or extends from XYZ
.
The error was because you used it like this:
/*
T extends from DemoInterface1, okay - this is myClass1
|
| the generic parameter of that
| DemoInterface1 is bound to T,
| which as mentioned,
| extends from DemoInterface1
| (in your case, it means this is myClass1<Integer>, NOT Integer)
| |
| |
| |
| | here you receive a bound for T
| | where T is meant to extend from
| | DemoInterface1<T>
| | in your example, T is myClass1<Integer>, and NOT `Integer` that is the <T> of DemoInterface1<T> (myClass1<Integer>)
| |
| | |
\|/ \|/ \|/ */
static <T extends DemoInterface1<T>> void myFunc(T t) {
t.display(t);
}
Basically, the T
that your display
method receives is not Integer
, it's myClass1
EDIT3:
I got your point
we have to pass object like myClass1<Integer>
and NOT Integer. However, when we do like:
myClass1<Integer> iObj1 = new myClass1<Integer>(1),
isn't iObj1 of myClass1<Integer> type, and NOT Integer.
This i am passing to myFunc().
Does <T> gets replaced with Integer?
or with the object with which we are calling it?
May be, this is the cause of confusion.
Please explain. Thanks a lot!
Yes, you are giving myFunc
your iObj1
instance. As such, the <T>
in static <T extends DemoInterface1<T>> void myFunc(T t) {
is resolved to be myClass1<Integer>
.
However, you are also using this as the parameter for display
in t.display(__)
. As a result, you are trying to give a myClass1<Integer>
to the method of iObj1.display(__)
, which however awaits Integer
. Essentially, you're pretty much calling iObj1.display(iObj1)
, and display(T)
awaits Integer
, not myClass1<Integer>
.
Upvotes: 2
Reputation: 6188
What you have is this function:
static <T extends DemoInterface1<T> > void myFunc(T t) {
t.display(t);
}
Then you call it like such:
myClass<Integer> iObj = new myClass<Integer>(1);
DoubtClear1.myFunc(iObj);
Now, myClass<Integer>
does not match the type T extends DemoInterface1<T>
but the type T extends DemoInterface1<Integer>
. So maybe you want something like this:
static <T extends DemoInterface1<?> > void myFunc(T t) {
t.display(t);
}
That would work. (Unless I misunderstood your intentions.)
Upvotes: 1