Some projects have to run on older JVMs. For example, some projects might not even be able to use assert
yet (introduced in Java 1.4), because they still need to work on Java 1.3 JVMs.
Another factor is simply inertia: If code was already written, and performs fine without adding the use of generics, there's little reason to take the risk in changing the code. But today, there are several automatic tools to help you migrate your Java code to use generics.
How many lines of code are in the following program?
#include <iostream>
int main()
{
std::cout << "Hello, world!\n";
return 0;
}
You probably answered 7 (or 6 if you didn't count the blank line, or 4 if you didn't count the braces).
Your compiler, however, sees something very different:
~$ cpp hello.cpp | wc
18736 40822 437015
Yes, that's 18.7 KLOC just for a "Hello, world!" program. The C++ compiler has to parse all that. This is a major reason why C++ compilation takes so long compared to other languages, and why modern languages eschew header files.
A better question would be
Why does C++ have header files?
C++ was designed to be a superset of C, so it had to keep header files for backwards compatibility.
OK, so why does C have header files?
Because of its primitive separate compilation model. The object files generated by C compilers don't include any type information, so in order to prevent type errors you need to include this information in your source code.
~$ cat sqrtdemo.c
int main(void)
{
/* implicit declaration int sqrt(int) */
double sqrt2 = sqrt(2);
printf("%f\n", sqrt2);
return 0;
}
~$ gcc -Wall -ansi -lm -Dsqrt= sqrtdemo.c
sqrtdemo.c: In function ‘main’:
sqrtdemo.c:5:5: warning: implicit declaration of function ‘printf’ [-Wimplicit-function-declaration]
sqrtdemo.c:5:5: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
~$ ./a.out
2.000000
Adding the proper type declarations fixes the bug:
~$ cat sqrtdemo.c
#undef printf
#undef sqrt
int printf(const char*, ...);
double sqrt(double);
int main(void)
{
double sqrt2 = sqrt(2);
printf("%f\n", sqrt2);
return 0;
}
~$ gcc -Wall -ansi -lm sqrtdemo.c
~$ ./a.out
1.414214
Notice that there are no #include
s. But when you use a large number of external functions (which most programs will), manually declaring them gets tedious and error-prone. It's much easier to use header files.
How are modern languages able to avoid header files?
By using a different object file format that includes type information. For example, the Java *.class file format includes "descriptors" that specify the types of fields and method parameters.
This was not a new invention. Earlier (1987), when Borland added separately-compiled "units" to Turbo Pascal 4.0, it chose to use a new *.TPU
format rather than Turbo C's *.OBJ
in order to remove the need for header files.
Best Answer
Well, a generic class is by definition not equal to a raw class. What you're trying there hides the issue of instantiation of ArrayLists (the actual lists, not their types).
will work and will allow any kind of element, objects, primitives, anything. On the other hand,
won't work since it's unclear, at compile time, what actual elements the list will hold. So, in order to make the list (almost) as broadly usable as the raw one, you could instantiate it like this:
(That will only hold actual objects, though, no primitives.)
generic
andraw
will never be equal type-wise and it won't make sense for them to be equal.What you can do with generic types instead of raw ones? Well, be safe at compile time. :) The other way around? Use primitives (generic types must inherit from
Object
which primitives do not).