Skip to main content

Stupid question: Why the creation of array of parametrized type is unsafe ?

Posted by forax on November 9, 2006 at 2:19 AM PST

I don't understand why array creation of array of parametrized
type is forbidden by the JLS.

Let me take an example :

  public class Holder<E> {
    public void set(E element) {
      this.element=element;
    }
    public E get() {
      return element;
    }
    private final E element;
  }
  ...
  Holder<String>[] holders=new Holder<String>[4];
  for(int i=0;i    holders[i]=new Holder();

Why the array creation new Holder[4]
is rejected by all java compiler as unsafe ?

The JLS3 clearly doesn't allow that
in section 10.3, about array creation
"It is a compile-time error if the element type is not a reifiable type".
Okay, the JLS prohibits that but i don't understand why.
Is there a Java guru that can explain me why ?

The
generics tutorial
written by Gilad Bracha
provides an example that show that there is a problem
when an array is assigned to an Object.
In short, the following code is unsafe :

  Object[] array=holders; 
  holders[0]=new Object();
  System.out.println(holder[0].get()); // try to call get on an Object

That's true, but i don't agree with the diagnostic.
For me, it's the convertion to Object[] (Object[] array=holders)
which is unsafe and not the array creation.

I wonder if the spec can't be change to something like this :

It's unsafe to convert an array of parametrized type
to Object, Object[], Serializable and Cloneable.

This condition is far less restrictive and permits
to use parametrized array in lot of usefull
use cases.
By example, the following code will be safe.

 public static void main(String[] args) throws Throwable {
   final InetAddress host=InetAddress.getByName("www.playboy.com");
   
   int poolSize=4;
   ExecutorService executor =
     Executors.newFixedThreadPool(poolSize);
   Future<Long>[] futures=new Future<Long>[poolSize]; //ok
   for(int i=0;i<poolSize;i++) {
     futures[i]=executor.submit(new Callable<Long>() {
       public Long call() throws Exception {
         long time=System.nanoTime();
         host.isReachable(2000);
         return System.nanoTime()-time;
       }
     });
   }
   executor.shutdown();
   for(Future<Long> future:futures)
    System.out.println("reach "+host+" in "+future.get()+" ns");
}

What do you think about that ?


Rémi

Related Topics >>