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

6 183 0
HandBooks Professional Java-C-Scrip-SQL part 12 ppsx

Đang tải... (xem toàn văn)

Thông tin tài liệu

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); . 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. 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. Subramaniam lays out the problems in gory detail: [*] Venkat Subramaniam. Generics in Java, parts 1-3 (June 2005);

Ngày đăng: 06/07/2014, 03:20

Tài liệu cùng người dùng

  • Đang cập nhật ...

Tài liệu liên quan