Since I haven’t posted anything this week, I figured I’d share something annoying I discovered in Java: you can’t assume that you can put an object of type T into a T array (unless you happen to know that T is declared as a final class).
Take for example this code, which tries to put an Integer (which is an Object) into an array of Objects:
1 2 3 4 5 6
public static void main(String[] args)
{
Object[] objects = new String[2];
objects[0] = "ABC";
objects[1] = new Integer(5);
}
This code compiles with no problem but when run it gives a runtime error on the objects[1]= line. But if the array were declared as new Object[2]; it would run with no complaints.
The problem is that you’re allowed to cast an array of type T to an array of a super-type of T, but you don’t really have an array of the super-type. I imagine they decided to allow this because of the usefulness of casting arrays to super-types for reading the data. But it opens up a whole new set of bugs that most of the time you wouldn’t even think to check for (especially if the array is declared in someone else’s code).
Apparently C# has controversially included the same feature.
October 20, 10:37 am
I don’t understand why you would initialize your array as a collection of Strings (first line in the method). Just because you declare it as an array of Objects doesn’t mean it will always be an array of Objects. You must also initialize that array as a collection of Objects if that’s what you wanted. It seems to me that this is a bug in the code you’ve written. I see very few cases where I’d want to declare an array of a super-type, only to initialize it to a sub-type. This is one reason why strong type-casting sucks.
Neither Perl nor Python have this problem, one more reason why they are (and always will be) superior. :-)
October 20, 2:14 pm
Well the example is intentionally oversimplified, you probably wouldn’t write something like that. But it would be perfectly legal to say “Object o = new Integer(5);” and then later say “o = new Double(5.0);” without any compiler or runtime error, because o is never allowed to be initialized to something that is not an Object.
Say I’m writing a function that takes an array of JComponents, and for whatever reason if there is a null item in the array I want to make it a default JButton. I might assume that a JButton can always go into an array of JComponents, but the fact is that the caller could just as easily pass in an array of JTextBoxes. That example isn’t very good either, but if you tried hard enough you could maybe come up with some realistic scenario where this could be a problem.
That being said, I can’t remember ever encountering this in the past seven years (counting college) of writing Java code. Probably because if you ever need to modify a list of objects, it is to add or remove elements, so you would use a Vector or ArrayList rather than an array. And usually when an array is taken as a parameter to a function, you don’t modify any of the elements.
With Google, I managed to find some examples of this happening in the real world.
October 20, 4:12 pm
Jonah: I see very few cases where I’d want to declare an array of a super-type, only to initialize it to a sub-type.
I agree with Jonah until...
Jonah: Neither Perl nor Python have this problem, one more reason why they are (and always will be) superior. :-)
That’s like saying tennis shoes are better than work boots. Sometimes you need to protect your feet!
Kip: “Say I’m writing a function that takes an array of JComponents, and for whatever reason if there is a null item in the array I want to make it a default JButton.”
Bad assumptions lead to bad coding.
October 20, 11:59 pm
Yes, the example is contrived and frankly lousy. I was just surprised to learn that you can’t always put an Object into an array of Objects. And I thought I’d share that to keep something new on the blog.
And correct me if I’m wrong, but does Perl have any way to guarantee that a variable/array/parameter is of a specific type? This problem is a hole in an otherwise strongly-typed language, so you wouldn’t expect the problem in a weakly-typed language.
Also, it occurred to me later that you couldn’t have, for example, the function Array.sort(Object[] a) without this behavior. (Well you could but you’d never be able to pass in an array of Strings.)
October 21, 3:30 pm
This really isn’t a problem in Perl, since there are only three data types: scalars, arrays of scalars, and hashes of scalars. You can force scalar context with the scalar keyword (this is useful to get the size of an array, for example), but for the most part, Perl just does the right thing. There are some pragmas and modules that will ensure that you get Integral results (for stuff like integer division), but I’ve never had a need to use those.
I am of the opinion that as programmers, we spend far too much time and effort on deciding the particulars: how big stuff should be, what data type stuff should be, etc. Shouldn’t the computer do all that work for me (ala Perl or Python)? I know there are cases where you want that level of control (as in testing hardware, which I do at work), but in the majority of cases, I shouldn’t have to think about that stuff. I can write more in a shorter amount of time, and spend my effort on thinking about solving the actual problems being faced.
It would be great to see strongly typed languages go the way of the dinosaur. If for no other reason, it would save us from a lot of typing.
October 21, 10:47 pm
Wow I didn’t really expect this post to spin off a conversation like this. I wouldn’t want to see strongly-typed languages go away. Both have their strengths and weaknesses. Sometimes you need more than three data types, and you’d like some assurance that the idiot calling your function isn’t passing in negative four and “Hi mom!” to AcmeSprocket.CalculateDistanceBetweenSprockets(), because that function only makes sense for two AcmeSprockets.
But other times you just want to convert $var to a string and append a br/ tag to the end of it.
October 22, 9:32 am
Jonah:It would be great to see strongly typed languages go the way of the dinosaur
)-: so above when you so nicely append Python to your Perl arguments, did you only mean Perl? Python is strongly typed...and unless you mean the really cool large teeth way of the dinosaurs, then I don’t want Python going that way...
October 22, 9:51 am
I used the wrong term in my previous statement.
I’d like to see statically typed languages go away. Dynamic typing is clearly beneficial (Perl, Python, PHP, etc), and the performance difference between static and dynamic typed languages is becoming less and less significant.
Pardon my error.