简体   繁体   中英

type T parameters in generic method arguments

Suppose the following classes are defined:

class Shape { }
class Circle extends Shape {  }
class Rectangle extends Shape { }  //  1

You can write a generic method to draw different shapes:

public static <T extends Shape> void draw(T shape) { }   // 2

The Java compiler replaces T with Shape:

public static void draw(Shape shape) {  } // 3

My Question is, if we define directly // 3 in our class then we still be able to pass Shape , Circle and Rectangle reference to method at //3. Then why do we need to write // 2 generic method with type parameter <T extends Shape> which is untimately going to be same as //3 ?

You can refer this link with same example : http://docs.oracle.com/javase/tutorial/java/generics/genMethods.html

You may or may not need it. You need it if your method has to deal with other objects of the type T that must match the type of T extends Shape exactly, for example:

public static <T extends Shape> void drawWithShadow(T shape, Class<T> shapeClass) {
    // The shadow must be the same shape as what's passed in
    T shadow = shapeClass.newInstance();
    // Set the shadow's properties to from the shape...
    shadow.draw(); // First, draw the shadow
    shape.draw();  // Now draw the shape on top of it
}

Above, passing Shape would not be enough, because we wouldn't be able to make the shadow of the exactly same type.

In case when there is no such requirement, a simple Shape would be sufficient.

In this particular case, you don't need a generic method.

But you can do more in a generic method than call a dynamically linked method on its arguments.

For example, you might have a generic method that accepts and returns a collection of T elements. Parameterizing it by type allows you to use it on multiple collection types.

Other examples where generic methods are useful are in this Java tutorial .

In your example, //3 is indeed the same as //2. But in other usecases, generic type may be useful:

  • you want to return value from the method, of the same type as the argument

  • you have 2 or more parameters and want to set restriction that they must be of the same type

The main interest is that you can restrict the usage of your method to a specific type of shape in different part of the code.

At some point you may want to parametrize it to draw only Rectangle and in another place only Circle and this will be checked at compile time even if, at runtime, you will pass something of type Shape

The difference is that the kind of polymorphism you are using.

In the generic case you are using parametric polymorphism while in the second one you are using polymorphism by subtype . Actually you first case uses both kind of polymorphism.

Now, they could be similar in some aspects but they are not the same. A practical example:

List<Shape> shapes;
List<T extends Shape> specificShapes;

You can see that in the first case, not having a type parameter, I can't manage a list of a specific subtype of Shape, I can only manage an eterogeneous list of shapes but I'm unable to force any specific one on it. So I don't have any compile time juice that forbids me from adding a Triangle and a Rectangle to the shapes .

class ShapeDecorator {
  private Shape shape;

  ..

  Shape get() { return shape; }
}

class ShapeDecorator<T extends Shape> {
  private T shape;

  T get() { return shape; }
}

Here is another example, in this case you could write a generic decorator which is able to return a type T without the need of any cast. This can be useful in many situations in which having the common ancestor as subtype is not enough.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM