Running on Java 24-ea+28-3562 (Preview)
Home of The JavaSpecialists' Newsletter

127Casting like a Tiger

Author: Dr. Heinz M. KabutzDate: 2006-06-07Java Version: 5Category: Language
 

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.

javaspecialists.teachable.com: Please visit our new self-study course catalog to see how you can upskill your Java knowledge.

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 5, but in nine places in JDK 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

 

Comments

We are always happy to receive comments from our readers. Feel free to send me a comment via email or discuss the newsletter in our JavaSpecialists Slack Channel (Get an invite here)

When you load these comments, you'll be connected to Disqus. Privacy Statement.

Related Articles

Browse the Newsletter Archive

About the Author

Heinz Kabutz Java Conference Speaker

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

Superpack '23

Superpack '24 Our entire Java Specialists Training in one huge bundle more...

Free Java Book

Dynamic Proxies in Java Book
Java Training

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

Java Consulting

We can help make your Java application run faster and trouble-shoot concurrency and performance bugs...