Home of The JavaSpecialists' Newsletter

127Casting like a Tiger

Posted: 2006-06-07Category: LanguageJava Version: 1.5+Dr. Heinz M. Kabutz
 

Abstract: Java 5 adds a new way of casting that does not show compiler warnings or errors. Yet another way to shoot yourself in the foot?

 

Welcome to the 127th edition of The Java(tm) Specialists' Newsletter. I have just returned from a visit to Crete with some friends. It was simply incredible. For example, sitting in a Greek kafeteria sipping iced coffee and discussing the drawbacks and benefits of various design patterns! One of my personal highlights was seeing an octopus whilst snorkelling. What an unforgetable experience ... its entire body changed colour as I approached it. These creatures are beyond weird; you could swear they were dumped in our seas by some alien teenage prankster.

Birthday and Anniversary Special: Since the 30th November 2017 is the 17th anniversary of our newsletter and my birthday is coming up on the 4th December, we are giving away a 30% discount on our new Data Structures for Java 9 Course (Late 2017 Edition). Whether you are a seasoned Java programmer or you just want to get ready for your next job interview, this course will help you. Besides detailed lectures, the course has over 130 questions that will help you discover what you missed.

Casting like a Tiger

Before we start, have you noticed how Java is striving towards the C Programming Language? We now have static imports, enums and varargs. So as a joke, we'll define a Stdio class. This must be in a package, so that we can statically import the functions.

package com.cretesoft.c; // must be in a package

 public class  Stdio {
   public static void  printf(String format, Object... args) {
    System.out.printf(format, args);
  }
}
  

To make the example fun, we make the interface Alien and the concrete classes Octopus and SeaSlug that implement Alien. The 30cm SeaSlug was another incredibly weird creature, flapping various appendages whilst creeping over the rocks.

public interface Alien {
  void swim();
  void glow();
}

import static com.cretesoft.c.Stdio.printf;

public class Octopus implements Alien {
  public void swim() {
    printf("Squirting water from my head.\n");
  }
  public void glow() {
    printf("I'll be brown, no, yellow, no green.\n");
  }
}

import static com.cretesoft.c.Stdio.printf;

public class SeaSlug implements Alien {
  public void swim() {
    printf("Flap various appendages.\n");
  }
  public void glow() {
    printf("Glow with a yellow hue.\n");
  }
}
  

Class.cast()

In the past, the following cast was illegal and caused a compilation error:

    String s = "42";
    Integer i = (Integer)s;
  

Since Java 5, there is a new way of casting that does not emit a warning. Each class has a cast() method that does so without causing compiler errors:

    String s = "42";
    Integer i = Integer.class.cast(s);
  

Pre-Java 5, you would have had to first cast the String to an Object, and then down to an Integer, to get the compiler to shut up:

    String s = "42";
    Integer i = (Integer)((Object)s);
  

Of course, this cast will always fail, and anyone who uses the Class.cast() method in this way is in need of some R&R in Crete.

Where is Class.cast() useful?

The Class.cast() method is used in only one place in JDK 1.5, but in nine places in JDK 1.6. Its popularity is growing! A place where it makes sense is with filtering of collections. Let's say we have a collection of objects, and we want to make a subset of the collection containing only Aliens. Here is a class that does that for you:

import java.util.*;

public class CollectionFilter {
  /**
   * Filters the src collection and puts the objects matching the
   * clazz into the dest collection.
   */
  public static <T> void filter(Class<T> clazz,
                                Collection<?> src,
                                Collection<T> dest) {
    for (Object o : src) {
      if (clazz.isInstance(o)) {
        dest.add(clazz.cast(o));
      }
    }
  }

  /**
   * Filters the src collection and puts all matching objects into
   * an ArrayList, which is then returned.
   */
  public static <T> Collection<T> filter(Class<T> clazz,
                                         Collection<?> src) {
    Collection<T> result = new ArrayList<T>();
    filter(clazz, src, result);
    return result;
  }
}
  

If instead of the Class.cast() method, we do an explicit cast: dest.add((T)o) it causes the following warning:

    CollectionFilter.java:13: warning: [unchecked] unchecked cast
    found   : java.lang.Object
    required: T
            dest.add((T)o);
                        ^
    1 warning
  

Here is an example of how it can be used to filter out the aliens in the sea:

import java.util.*;

public class StavrosLagoon {
  public static void main(String[] args) {
    Collection<Object> sea = new ArrayList<Object>();
    sea.add("seaweed");
    sea.add(new Octopus());
    sea.add("rock");
    sea.add("fish");
    sea.add(new Octopus());
    sea.add("sand");
    sea.add(new SeaSlug());
    sea.add("starfish");

    Collection<Alien> aliens =
        CollectionFilter.filter(Alien.class, sea);
    for (Alien alien : aliens) {
      alien.swim();
      alien.glow();
    }
  }
}
  

There are a few other places where the Class.cast() can be useful. One of these is in generating dynamic proxy instances if you want to avoid having to deal with the unchecked cast warning.

Another interesting new method in Java 5 is the Class.asSubClass() method. We can use that when we have a class object that we want to bind to a specific subclass instance, like this:

public class SeaSlugTest {
  public static void main(String[] args) throws Exception {
    Class<?> someClass = Class.forName("SeaSlug");
    Class<? extends Alien> clz = someClass.asSubclass(Alien.class);
    Alien alien = clz.newInstance();
    alien.glow();
  }
}
  

It is good to be back in Cape Town. Had to take my Alfa Romeo for its 100'000km service, which went smoothly. I still think that the Alfa Romeo is the best value-for-money car that you can buy, especially if you enjoy driving but have to watch your budget. Their reliability has improved drastically in the last few years. Mine has certainly earned her keep. Just a pity about the speeding fines ...

Kind regards

Heinz

 

Related Articles

Browse the Newsletter Archive

About the Author

demo

Java Champion, author of the Javaspecialists Newsletter, conference speaking regular... About Heinz

Java Training

We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.

Java Consulting

Nobody ever wants to call a Java performance consultant, but with first-hand experience repairing and improving commercial Java applications - JavaSpecialists are a good place to start...

Threading Emergency?

If your system is down, we will review it for 15 minutes and give you our findings for just 1 € without any obligation.