Tuesday, January 25, 2011

Chapter 11: Legal Return Types

In the previous chapters we have seen many methods and classes. Every method in java has a return type which specifies the kind of data that would be returned by the current method. It is mandatory for all java methods to return something and if it is not going to return anything, we have to mark the method with a “void” return type to let the JVM know that it must not expect anything from the method. The purpose of this article is to take a look at what you can declare as a return type and as values. We will also cover a few other nuances of returning data with respect to other scenarios that we had covered in the previous chapters.

Return Type Declarations

This section looks at what you’re allowed to declare as a return type, which depends primarily on whether you are overriding, overloading, or declaring a new method.

Return Types on Overloaded Methods

Remember that method overloading is nothing more than name reuse. The overloaded method is a completely different method from any other method of the same name in the current class. So if you inherit a method but overload it in a subclass, you’re not subject to the restrictions of overriding. This essentially means that you can declare any return type you want. What you can’t do is change only the return type. To overload a method, remember, you must change the arDriveent list. The following code shows an overloaded method:

public class Car{
void go() { }
}

public class Ferrari extends Car {
String go(int x) {
return null;
}
}

Notice that the Ferrari version of the method uses a different return type. That’s perfectly fine. As long as you’ve changed the arDriveent list, you’re overloading the method, so the return type doesn’t have to match that of the superclass version. What you’re NOT allowed to do is this:

public class Car{
void go() { }
}
public class Ferrari extends Car {
String go() { //Illegal! Can't change only the return type
return null;
}
}

Overriding and Return Types, and Covariant Returns

When a subclass wants to change the implementation of an inherited method (override), the subclass must define a method that matches the inherited version exactly. Or, as of Java 5, you’re allowed to change the return type in the overriding method as long as the new return type is a subtype of the declared return type of the super-class method. (This is called Co-variant Returns)

Let’s look at a covariant return in action:

class Car {
Car drive(char c) {
return new Car();
}
}

class Lamborghini extends Car {
Lamborghini drive(char c) { // legal override as of Java 1.5
return new Lamborghini();
}
}

As of Java 5, this code will compile. If you were to attempt to compile this code with a 1.4 compiler or with the source flag as follows:
javac -source 1.4 Lamborghini.java

You would get a compiler error something that would look simething like this:
attempting to use incompatible return type

There are many other rules that apply to overriding, including those for access modifiers and declared exceptions, but those rules aren’t relevant to the return type discussion and we have already seen them in the chapter where we discussed about Overriding.
For the exam, be sure to remember that overloaded methods can change the return type, but overriding methods can do so only within the bounds of covariant returns.

Returning a Value

There are 6 golden rules for returning values from a method. Be sure to remember these clearly:
1. You can return NULL in a method that has an Object as return type
public Button drive() {
return null;
}

2. An Array is a perfectly legal return type
public String[] go() {
return new String[] {"Anand", "Rocky", "Austin"};
}

3. In a method with a primitive return type, you can return any value or variable that can be implicitly converted to the declared return type.
public int Car() {
char c = 'c';
return c; // char is compatible with int
}

4. In a method with a primitive return type, you can return any value or variable that can be explicitly cast to the declared return type.
public int Car () {
float f = 32.5f;
return (int) f;
}

5. You must not return anything from a method with a void return type.
public void Ferrari() {
return "this is it"; // You cant do this. Code wont compile
}

6. In a method with an object reference return type, you can return any object type that can be implicitly cast to the declared return type.
public Car getCar() {
return new BMW(); // Assume BMW extends Car
}

public Object getObject() {
int[] nums = {1,2,3};
return nums; // Return an int array,
// which is still an object
}

public interface Drivable { }
public class Drive implements Drivable { }

public class TestDrivable {
// Method with an interface return type
public Drivable getDrivable() {
return new Drive(); // Return interface implementer
}
}

Exam Tip:
Watch for methods that declare an abstract class or interface return type, and know that any object that passes the IS-A test (in other words, would test true using the instanceof operator) can be returned from that method—for example:
public abstract class Car { }
public class Lexus extends Car { }
public class Test {
public Car go() {
return new Lexus(); // OK, Lexus "is-a" Car
}
}
This code will compile, the return value is a subtype.


Previous Chapter: Chapter 10 - Implementing an Interface

Next Chapter: Chapter 12 - Constructors and Instantiation

No comments:

Post a Comment

© 2013 by www.inheritingjava.blogspot.com. All rights reserved. No part of this blog or its contents may be reproduced or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without prior written permission of the Author.

ShareThis

Google+ Followers

Followers