If you add an Object to a String array, a compile time error is thrown. If no error was thrown you'd have ClassCastExceptions occurring all the time. The only other alternative is to create a 2-D array of Objects. Object is a super class of all classes in Java; it serves as a polymorphic handle for any instance of a Java class. For instance, you have:
Object[][] ar = new Object[2][2];
ar[0][0] = new String("A"); ar[0][1] = new Integer(1);
ar[1][0] = new Double(2); ar[1][1] = new Character('b');
Although, each element of this array contains an instance of a different class, we can guarantee that it is a subclass of Object. Therefore, we handle the object with a reference of type Object. This is polymorphism at work. Here's another example:
class Animal{}
class Dog{}
class Cat{}
Animal[] pound = new Animal[3];
pound[0] = new Animal();
pound[1] = new Dog();
pound[2] = new Cat();
When we access an element of the array, we must handle it with a reference to Animal. We can try downcasting it to a Dog or Cat, but if we're wrong, a ClassCastException will be thrown. It's the same with the first example. We handle all the elements with a reference to Object, then we try downcasting, but we must be right, or a ClassCastException is thrown.
Object obj = ar[0][0];
String s = (String)obj; //OK
Double d = (Double)obj; //ClassCastException will be thrown
So, here the first element, which is unknown at runtime, is a String. We only handle it as an Object, because we have to. We try downcasting to String, it works. Then, we try downcasting to a Double; but, it's a String, so no go.
I hope I explained this clearly. So, an Object array is the only solution, but you (the programmer) must know the object's type, and that's a pain.