Tải bản đầy đủ (.pdf) (6 trang)

HandBooks Professional Java-C-Scrip-SQL part 12 ppsx

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (22.44 KB, 6 trang )


The type is bound to the object. Therefore, the type of containers can change. An
imperfect rule of thumb is that static languages force you to declare variables, but
dynamic languages don't.
Ironically, most dynamic languages also tend to be strongly typed. Most weakly
typed languages tend to be static. Said another way, strong typing can be dynamic
or weak, but weak typing is usually also static. You don't find many weakly and
dynamically typed languages, beyond Assembly language. Figure 4-1 places
programming languages on two axes. Java has strong, static typing. You know this,
because you get type mismatch errors when you make certain kinds of mistakes.
Compiling this:
class TypeTest {
public static void main(String args[ ]) {
i = 4; // Nope!!! Static typing
int j;
j = 4.2; // Nyet!!! Strong typing
}
}
gives you this result:
TypeTest.java:3: cannot resolve symbol
symbol : variable i
location: class TypeTest
i = 4;
TypeTest.java:5: possible loss of precision
found : double
required: int
j = 4.2;
Figure 4-1. Java is a strongly and statically typed language

Sometimes, that's good. After all, a bug that gets caught at compile time takes
much less time than a bug that gets solved much later. In general, though, the


dynamic programmers that I interviewed said static typing simply mauls
productivity.
4.3.3. Syntax
Initially, you immediately can see that Java's syntax forces you to do more work.
You have to declare and type all of your variables and parameters. You also need
to cast objects that are compatible but different, and convert objects that aren't. The
extra syntax provides valuethe compiler has more information to catch bugs
earlier. There's a cost, too. Static typing makes you work harder to enter equivalent
code to dynamically typed languages, but you also have more lines of code to
understand, maintain, or enhance. It's very difficult to prove or disprove the notion
that static typing makes you more or less productive in terms of hours at the
keyboard, but you can show that static typing leads to more characters, and more
code to read and maintain.
Raw code count is not definitive; if it were, Perl, with all of the two- or three-
character shortcuts, would be the most productive language of all time. Still, it's
suggestive. Java's syntax wouldn't be such a problem if you could limit the extra
code to a few lines of code at the top or bottom of a program, but you can't. You
need to declare types for parameters. You need a cast every time you take
something out of a collection. This syntax only gets more invasive with generics.
4.3.4. Thought Process
Some of the costs related to typing are hidden costs . I believe that one such cost is
related to high-level, conceptual work versus finishing work. It's usually preferable
to do conceptual work first and finishing work later, because much of your code
will be thrown away, especially at early stages. As your program takes shape, you
can do more and more detailed work. You make the expected case work, and then
you work through noncritical path issues.
Java forces you to work the opposite way: to make things compile, you must deal
comprehensively with typing, which involves dominantly finishing issues. Also,
many of the compiler errors in Java might not even be problems at all in a
dynamically typed language.

4.3.5. Code/Compile Cycle
Dynamic typing comes into play especially when you need to experiment.
Remember, you must declare variables in statically typed languages. In Java, that
means you need to start each application with a class definition, and it snowballs.
You can't just jump in and evaluate a single line of codethe compiler just doesn't
have enough information. Instead of just simply evaluating statements, you need to
blow out a class, type everything, compile, and execute. In Smalltalk, Lisp, Basic,
and Ruby, you can just start typing. For simple experimentation on an initial cut at
a Fibonacci sequence, here's the Java version:
class Fib {
public static void main (String args[ ]) {
int x1 = 0;
int x2 = 1;
int total = 1;
for (int i=0; i<10; i++) {
System.out.println(total);
total = x1+x2;
x1 = x2;
x2 = total;
}
}
}
It's 13 lines; 41 words; 226 characters. Keep in mind that Java forces you to
declare the class to explore, and that's what we're measuring here. On the
command line, you need to save, compile, and run. The Ruby counterpart looks
like this:
x1 = 0
x2 = 1
100.times do
puts x2

x1, x2 = x2, x1+x2
end
It's 6 lines; 16 words; 57 characters. Notice how the code just flows better. Read it
in English. But the biggest impact is on experimentation. You just type and go.
You can cut and paste right on the console screen. You'll use command retrieval to
repeat the lines that you need. And these advantages come into play in IDEs as
well. Further, if you need 100 iterations, the Java version breaks because an int is
not big enough. Ruby still works fine.
This is a trivial example, and probably not completely fair. After all, the Java
version packages up a full class and the Ruby version doesn't need to. But you'll
find that as we go on, the examples get more and more compelling, especially for
the dynamic, reflective style of programming that leading Java developers seek
today.
As you add the Web and other deployment steps, the case for dynamic languages
gets more compelling, because you can make changes and immediately see the
results, instead of having to compile and deploy, and maybe even bounce your
servlet engine. Web-based programming gets very easy. Just make a change, and
hit Reload.
From my small forays into Basic (where I made my spending money in high
school by writing games) and Smalltalk (where I did marketing demos), I miss the
rapid feedback cycle afforded by dynamic typing and an interpreter the most.
4.3.6. Adaptability
If you've been coding in Java for most of your career, you probably don't know that
you have to jump through so many hoops just to support static typing, but you do.
One of the greatest typing costs comes into play when you refactor. Think of the
impact of a simple type change for a member variable. You've got to change the
property, the getters and setters, every type cast, and every parameter usage.
Dynamically typed languages delay the binding of a type to a variable or a
parameter, so you often don't need to make any change at all to support a simple
type change. For Smalltalk, for example, you can change a type easily. If the new

type supports all of the messages of the old type, you will likely limit the changes
to one place in your code.
4.3.7. Generics
The Java architects have traditionally gone to great lengths to ensure type safety,
but there's been one particular case that's troubled them. When you take an object
from a collection, you need to cast the object:
ArrayList animals = new ArrayList( );
animals.add("elephant");
String cat = (String)animals.get(0);
The compiler has just lost the ability to provide compile-time type safety. You
could call the array element anything you want. To fix this, Java introduces an ugly
implementation of a feature called generics . Here's what the usage looks like:
ArrayList<String> animals = new ArrayList<String>( );
animals.add("elephant");
String elephant=animals.get(0);
Comparing the preceding code with its nongeneric equivalent, you may think that
you avoided casting, but you really did not. Java introduced an ugly
implementation of generics, called type erasure. Under the hood, in the modified
version, the ArrayList still maintains a collection of Objects and not a
collection of Strings. Of course, any library that you need to strongly type with
user-defined types must enable the code for generics. Enabling generics gets a little
ugly. Here's the List declaration from within the Java collections package:
public interface List<E> { void add(E x);
Iterator<E> iterator( );
}public interface Iterator<E> {
E next( );
boolean hasNext( );
}
If you're not a fan of statically typed languages, you don't like the extra type checks
that place yet an additional burden on you. Even if you like the idea of generics,

you probably don't like the implementation. Generics offer only syntactic sugar
and not real runtime protection, because the JVM has no concept of generics. In an
article series on agiledeveloper.com,
[*]
Venkat Subramaniam lays out the problems
in gory detail:
[*]
Venkat Subramaniam. Generics in Java, parts 1-3 (June 2005);

×