1

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.

7
  • it's because you are evaluating the condition static <Integer extends DemoInterface1<Integer> > void myFunc(Integer t) { which is not true, as Integer is not a DemoInterface1. Commented Apr 17, 2015 at 13:29
  • From what I feel, Generics is confusing, and it takes repeated study to really get what this is. Yes, it can be confusing at first but it all makes sense, you just need to work out the logic. Stick with it and you'll master it. Commented Apr 17, 2015 at 13:40
  • You should look at this example I wrote a while ago, although I'm not sure if it's the best possible explanation (I wrote it a while ago): stackoverflow.com/questions/24574478/… Commented Apr 17, 2015 at 13:43
  • @EpicPandaForce: Is this statement wrong then wrt Java Generics. <T extends XYZ> --> as per the book that i referred, this means T can take any class which implements interface XYZ? I was trying to do so in my code. Commented Apr 17, 2015 at 14:15
  • 1
    @EpicPandaForce: 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! Commented Apr 17, 2015 at 15:11

2 Answers 2

2

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>.

Sign up to request clarification or add additional context in comments.

1 Comment

isn't he currently evaluating <myClass<Integer> extends DemoInterface1<myClass<Integer>>?
1

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.)

3 Comments

What you are doing is side stepping type erasure. It is a valid solution, but not explain why the original did not work
I think you misunderstood, I deleted my post temporarily too as such because he intends to receive the T parameter that is within the DemoInterface1 to give it to the DemoInterface1's display(T) method, as such the parameter should not be bound to <T extends DemoInterface1>
Exactly, because documentation of Generics says that <T extends DemoInterface1<T> > means T can be any class which IMPLEMENTS this interface. In my code these two classes implement this interface and hence should work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.