Wednesday, May 27, 2009

How to achieve covariance in method parameters

Consider the following example:


public interface Toy {
public String getName();
}

public class SuperHeroes implements Toy {
public String getName() {
return "Spiderman";
}
}

public class Dolls implements Toy{
public String getName() {
return "Barbie";
}
}

public interface ChildrenAtPlay{
public void play(Toy toy);
}

public class Boys implements ChildrenAtPlay{
public void play(Toy toy) {
}
}

public class Girls implements ChildrenAtPlay{
public void play(Toy toy) {
}
}


Children play with toys but lets assume boys and girls play with different types of toys. The problem with the code above is that it allows boys to play with Dolls and girls to play with superheroes. If you attempt to change the code and make the play method in Boys to accept a parameter of type SuperHeroes, code will not compile, because the ChildrenAtPlay interface contract is not satisfied. So how can we provide a narrower type for a method parameter. Is it possible to have covariant parameters just like Covariant return types?
DISCLAIMER: This is only an example to illustrate a point about covariant return types. I dont subscibe to the views that boys cannot play with dolls or girls cannot play with super heroes.


You can achieve a covariant parameter using generics. Modify the interface ChildrenAtPlay to actually take a type parameter T extends Toy. Then modify the play method to accept any type of Toy. Then while defining the Boys and Girls classes specify the Toys they can play with.

Here is the code to achieve this:
    public interface ChildrenAtPlay <T extends Toy> {
public void play(T toy);
}

public class Boys implements ChildrenAtPlay <SuperHeroes> {
public void play(SuperHeroes toy) {
}
}

public class Girls implements ChildrenAtPlay <Dolls>{
public void play(Dolls toy) {
}
}

Friday, May 15, 2009

Arrays and final qualifier

One has to be careful regarding arrays which are declared final. It only means that the whole array reference itself cannot be changed to point to a different array. Individual elements of the array can be modified. I have an example below to depict this:

public class TestFinalArray {

final StringBuilder[] array;

TestFinalArray(int size, String... records) {
//Initialize final array
array = new StringBuilder[size];
for (int i = 0; i < size; i++) {
array[i] = new StringBuilder(records[i]);
}

}

public static void main(String[] args) {
TestFinalArray tfa =
new TestFinalArray(3, new String[] {"1","2", "3"});
print("Original array", tfa.array);
//Modify elements of the array
tfa.array[0] = new StringBuilder("Hello");
tfa.array[1] = tfa.array[1].append("World");
print("After Modification", tfa.array);

}

public static void print(String s, StringBuilder[] array) {
if (s != null) {
System.out.println(s);
}
for (StringBuilder elem: array) {
System.out.println(elem);
}
}

}




Output:
Original array
1
2
3
After Modification
Hello
2World
3

Tuesday, May 5, 2009

Nice article...

Today, I was really happy to come across this essay "Teach yourself programming in ten years" by Peter Norvig. He makes very good points, the gist being it takes atleast 10 years and not X days to become an expert in programming in a language - Expert meaning not just understanding how to program but understanding the design aspects and the consequences of writing programs in different ways. I, myself, have been programming in an OO environment for a long time and am still learning.

I have to admit that I have browsed books like "Teach yourself X in Y days" but it is not with the intent of becoming an expert in X. Sometimes one needs to interface with languages and tools in which one lack's expertise especially when one has to customize some small piece of the one's product with customer's code. In such cases, such books help provide relief as they provide just the essentials. With deadlines looming and customers waiting, there is sometimes a rush! But even in the rush, if one has been programming for sometime, hopefully depending on the environment, one is able to make wise choices wrt design and performance.

Anyways the fact remains that, to become an expert in a programming language one has to have the passion, work hard and ofcourse, enjoy. Take it easy!

Monday, May 4, 2009

Preventing serialization of objects

In Java if the parent class is serializable then the child automatically is serializable. If for some reason you don't want the child to be serializable then you have to override the private methods readObject and writeObject to throw NotSerializableException. These are the same private methods which were used to customize serialization in my earlier post.

Example code on how to prevent serialization:
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

//Serializable class
class Animal implements Serializable {

private static final long serialVersionUID = 1L;
private String name;

public Animal(String name) {
this.name = name;
}

public String getName() {
return name;
}
}

//Does not want to be serializable
class Cat extends Animal {

private static final long serialVersionUID = 1L;
private String breed;
private static final String NOT_SERIALIZABLE = "Cat cannot be serialized";

public Cat (String name, String breed) {
super(name);
this.breed = breed;
}

public String getBreed() {
return breed;
}

//To prevent serialization, override this method to throw exception
private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
throw new NotSerializableException(NOT_SERIALIZABLE);
}

//To prevent serialization, override this method to throw exception
private void writeObject(ObjectOutputStream oos) throws IOException {
throw new NotSerializableException(NOT_SERIALIZABLE);
}
}

//Test it
public class MyNonSerializableTest {

public static void main(String[] args) throws FileNotFoundException, IOException {
Animal a = new Animal("Cow");
System.out.println("Serializing animal object");
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("animal.ser"));
out.writeObject(a);
Cat c = new Cat("bo", "Taby cat");
System.out.println("Serializing cat object");
ObjectOutputStream ous = new ObjectOutputStream(new FileOutputStream("cat.ser"));
ous.writeObject(c);
}
}


The output:
Serializing animal object
Serializing cat object
Exception in thread "main" java.io.NotSerializableException: Cat cannot be serialized
....blah blah blah.....

Friday, May 1, 2009

Analysis of McKinsey's report on cloud computing

Last month McKinsey released a report called "Clearing the air on cloud computing" in which they conclude that corporations with large data center's could lose money if they move to the cloud. As per the report, the current cloud offerings are best suited for small and medium sized companies. Obviously these conclusions are based on some assumptions which unfortunately seem to be incorrect. Here are the detailed analysis(read rebuttal) of this report by James Hamilton and Lydia Leong. Very interesting reads.