Skip to main content

Covariant Return Types - Java 6 or Greater

In OOP, a covariant return type of a method is one that can be replaced by a "specialized" type when the method is overridden in a subclass. 
C# does not support return type covariance. Covariant return types have been (partially) allowed in the Java language since the release of JDK5.0, so the following example wouldn't compile on a previous release:
 // Classes used as return types:
 class Person {
 }
 
 class Guy extends Person {
 }
 
 // "Class Guy is more specific than class Person"
 // Classes demonstrating method overriding:
 class Department {
     public Person getPerson() {
         return new Person();
     }
 }
 
 class DepartmentOfGuys extends Department {

     public Guy getPerson() {
         return new Guy();
     }
 }
More specifically, covariant (wide to narrower) or contravariant (narrow to wider) return type refers to a situation where the return type of the overriding method is changed to a type related to (but different from) the return type of the original overridden method. The relationship between the two covariant return types is usually one which allows substitution of the one type with the other, following the Liskov substitution principle. This usually implies that the return types of the overriding methods will be subtypes of the return type of the overridden method. The above example specifically illustrates such a case. If substitution is not allowed, the return type is invariant and causes a compile error.
This might be very useful while overriding the clone method, because instead of returning an object, you can override the method clone to return a more specific type, preventing you from casting to your type. 
The convariant type rule can also be applied to Exceptions in methods siganture, for instance the close method in AutoCloseable Interface throws Exception, and the close method in the Closable Interface throws a specialized exception: IOException. You can implement the interface AutoCloseable to throw the Exception of your needs. For example:

class ProcessException extends Exception{
      public ProcessException(String message) {
            super(message);
      }
}
class Processor implements AutoCloseable{
      @Override //Throws our Custom Exception
public void close() throws ProcessException {
            System.out.println("Closing resources...");
      }
      public void initiateProcess() {
            System.out.println("start process...");
      }
}
class MainTest{
//Finnally block automatically 
//called with your clos method and specific exception
      public static void main(String args[]){
            try(Processor p = new Processor()){
                  p.initiateProcess();
                  throw new ProcessException("You can catch in the 
try-with-resources statement your specific exception");
            } catch(ProcessException e) {
                  e.printStackTrace();
            }
      }    
}
To close our topic remember that Generics are not covariant, they are invariant, therefore, the following code will not compile:

class A{
      List<Object> test(){
            return Collections.emptyList();
      }
}
class B extends A{
      @Override  List<String> test() {
            return super.test();
      }
}

Comments

Popular posts from this blog

The Scala's Equivalent of Java ArrayList

ArrayList   is a widely misused "default"  List  in Java. It has terrible performance when elements are added/removed frequently, but works pretty well as a replacement for  Array .  But what about Scala? What is Scala's default collection? What Scala collection has characteristics similar to  ArrayList ? What's a good replacement for  Array   in Scala? So here are the answers for these: What is Scala's default collection? Scala's equivalent of Java's  List  interface is the  Seq . A more general interface exists as well, which is the  GenSeq  -- the main difference being that a  GenSeq  may have operations processed serially or in parallel, depending on the implementation. Because Scala allows programmers to use  Seq  as a factory, they don't often bother with defining a particular implementation unless they care about it. When they do, they'll usually pick either Scala's List  or  Vector . They are both immutable, and  Vector

Always Use StringBuilder while concatenating Strings within loops

A common tendency of Java programmers is to always concatenate Strings using + operator. Which is actually very good, and simplifies the code by improves readability, since we would have to use StringBuilder.append(String), if the single + operator was not allowed. In fact if we look in byte code generate from such concatenation style, we will see a StringBuilder being used to perform the action. Check the JSL:    JLS Now , the point is, although this facility, you should not use the + operator in loop concatenation. Why? A new  StringBuilder  Object will be constructed at every single loop iteration (with initial value of str) and at the end of every iteration there will be concatenation with initial String (actually  StringBuilder  with initial value of  str ). So you need to create StringBuilder by yourself only when you work with String concatenation in loop. Let us procuce the evidence First, run this code, and see how long it takes to be executed: Now, bellow is th

Maven Tips... and Tricks

Maven, one of the central actors in the Java World, resposible for managing the building life-cycles of many projects, is full of little features, that sometimes we forget to explore. Let us go straight away and take a look at some very useful Maven features that will make your builds shine. From where it stopped Sometimes it is needed to build a bunch of projects all together, artifact-a , artifact-b and so on. What do we usually do when one of them fail? Build it all again! But not anymore: By using this option you can run the build from the project that failed. Two out of ten Ok, suppose you have 10 projects, and you only want to build 2 of them, how would you do? The option -pl will do the job Multi-threaded Build If in the machine you run the build you have many Cores, tou can take advantage of them by using the following option(it means 2 Threads per Core): It is also possible to define 3 Threads per Core(T3C) Skip your Tests when you want to With a lot of test