Chapter 4. Identifiers, Keywords, and Types

Identifiers, Keywords, and Types

The great majority of operating systems in use today employ the ASCII codeset to represent characters. ASCII, the American Standard Code for Information Interchange, started out as a 7-bit code that represented uppercase and lowercase letters, the digits 0–9, and a dozen or so control characters like NUL and EOT. As computing technology became pervasive in Western Europe, users demanded the ability to represent all characters in their national alphabets. ASCII was extended to 8 bits, with the additional 128 characters being used to represent various accented and diacritical characters not present in English. The extended 8-bit code is known as the ISO 8859-1 Latin-1 codeset. It is reproduced for reference as an appendix at the end of this book.

Java and Unicode

An even more general solution was needed for Java that included support for Asian languages with their many thousands of ideograms. The solution that was chosen is Unicode. It is an ISO [1] standard 16-bit character set supporting 65,536 different characters. About 21,000 of these are devoted to Han, the ideograms seen in Chinese, Japanese, and Korean. The ISO Latin-1 code set forms most of the first 256 values, effectively making ISO Latin-1 a subset of Unicode, just as ASCII is a subset of Latin-1.

Java takes 2 bytes to represent each character internally, and uses the Unicode encoding. If you’re only working with ASCII or Latin-1, then the encoding is the same, but you’re carrying an extra byte for each character.

On Unix, Windows, and Macintosh, the default character sets are all 8-bit based. When Java gets a character on these systems, the operating system gives it 8 bits, but Java squirrels it away in a 16-bit datatype and always processes it as 16 bits. This does away with some hideous multibyte char complications in C and the special wide versions of the string-handling routines.

JDK 1.4 introduces some new classes that manage the conversion from external character representation to internal, and back again. These are covered in the second of the two chapters on I/O, later in the book. The one-sentence summary is: “the right conversions happen by default when you read in or write out 16-bit Unicode characters into an ASCII world, and if you want something different, there’s a way to ask for it.” This chapter explains how chars and strings are processed once you have got them into your program.

You can read more about the Unicode standard at www.unicode.org. Be warned: For something that is conceptually so simple, the Unicode standard sets some kind of world record in obscurity and all-around lack of clarity. An example can be seen at www.unicode.org/unicode/standard/utf16.html, reproduced in the following box.

Another way of saying all that is, “Unicode characters are 16 bits, and UCS-4 characters are 32 bits. Right now, Unicode forms the least significant 16 bits of the 32-bit code, but that might get jumbled up in the future in a new coding system called UTF-16.” It’s ironic—some programmers would say “predictable”—that a standard whose purpose is to foster communication is so poorly written that it actually hinders the ready transmission of meaning.

Scanning

When a Java compiler reads in program source, the very first thing that it does, even before forming tokens out of the characters, is to look for any six-character sequences of the form uxxxx, where xxxx is exactly four hexadecimal digits, as in u3b9F. These six-character sequences are translated into the corresponding one Unicode character whose value is xxxx, which is pushed back into the input stream for rescanning.

Because this early scanning takes place before tokens are assembled, the six-character sequence uxxxx will be replaced even if it appears in a quoted string or character literal! It is done so that Java programs with arbitrary Unicode characters in them can be translated to and from ASCII and processed by ASCII tools with no loss of information. Relax, though: You never see this in practice.

Identifiers

Identifiers, which are names provided by the programmer, can be any length in Java. They must start with a letter, underscore, or dollar sign, and in subsequent positions can also contain digits.

A letter that can be used for a Java identifier doesn’t just mean uppercase and lowercase A–Z. It means any of the tens of thousands of Unicode letters from any of the major languages in the world including Bengali letters, Cyrillic letters, or Bopomofo symbols. Every Unicode character above hex 00C0 is legal in an identifier. Table 4-1 shows some example valid Java identifiers.

Table 4-1. Legal Java Identifiers

calories

Häagen_Dazs

déconnage

_99

Puñetas

fottío

i

$__

p

The more accented characters you use in your variable names, the harder it is for others to edit them and maintain the code. So you should try to stick to ASCII characters.

Comments

Java has comment conventions that are similar to C++. Comments starting with “//” go to the end of the line, as follows:

i = 0;  // the "to end-of-line" comment 

Comments starting with “ /* ” end at the next “*/”, as follows:

/* the "regular multiline" comment 
*/ 

There’s a third variety of comment starting with “ /** ”. This indicates text that will be picked up by javadoc, an automatic documentation generator. This is the tool that generates the HTML files for the Java API, reviewed in the previous chapter. You can also use javadoc on your own code and generate some HTML documentation for it. Many professional packages, including LimeWire, are documented using javadoc.

Javadoc is an implementation of the literate programming system invented by Donald Knuth. The javadoc tool (part of the JDK) parses source code with these special comments and extracts them into a set of HTML pages describing the API.

/** the API comment for HTML documentation 
    @version 1.12 
    @author A.P.L. Byteswap 
    @see SomeOtherClassName 
    HTML tags can also be put in here. 
  */ 

The javadoc comments must be outside a method. Take a look at the source of the Java runtime library (distributed with the JDK) to see examples. There is a whole set of comments preceding each class, and each individual method in the class.

Try javadoc. You can easily annotate your own code with comments javadoc recognizes. Javadoc works on .java files, not .class files, because the .java files contain the comments. Add some of the javadoc tags to the myframe example and run javadoc like this:

javadoc myframe.java 

This will create several HTML files and a style sheet, listing their names as it generates them. A style sheet is an update to HTML that lets you customize the appearance of other tags. You can change colors, fonts, and sizes throughout a document by using a style sheet that overrides the default appearance.

The javadoc output can be viewed in your web browser. It shows the chain of class inheritance and all the public fields in the class, along with your comments.

Commenting Out Code

Whether or not you agree with the idea of using web pages to store program documentation, it offers some compelling advantages. Documentation automatically generated from the program source is much more likely to be available, accurate (what could be more accurate than the documentation and the source being two views of the same thing?), and complete (the documentation is written at the same time as the code and by the same person).

Keywords

Keywords are reserved words, and they cannot be used as identifiers. ANSI C has only 32 keywords. Java has almost 50 keywords, including some reserved for future use in case the language designers add to the language. The keywords can be divided into several categories as follows according to their main use:

Used for built-in types:

boolean 
char 
byte  short   int      long 
float double  strictfp 
void 

Used for objects:

new this super

Used in statements:

selection statements

if else

switch case break default

iteration statements

for continue

do while

transfer of control statements

return

throw

exception statements

try catch finally

assert

thread statements

synchronized

Used to modify declarations (visibility, sharing, etc.):

static 
abstract   final 
private    protected  public 

Used for other method or class-related purposes:

class       instanceof    throws   native 
transient   volatile 

Used for larger-than-a-single-class building blocks:

extends 
interface   implements 
package     import 

Reserved for possible future use:

const    goto 

The Primitive Types

Java has eight built-in, non-object types, also known as primitive types. They are:

  • boolean (for truth values)

  • int, long, byte, short (for arithmetic on integers)

  • double, float (for arithmetic on the real numbers)

  • char (for character data, ultimately to be input or printed)

All class types are ultimately represented in terms of primitive types. Primitive types are simpler than class types, and are directly supported in hardware on most computers. That is, most of the operations on primitive types are a single machine instruction, like ADD, whereas the operations on class types are specified as statements in a method.

Most high-level languages don’t specify the sizes of primitive data types. That allows compiler writers the freedom to select the best sizes on each architecture for performance. The freedom turns out to be a false economy, since it greatly impedes program portability, and programmer time is a lot more expensive than processor time.

Java does away with all the uncertainty by rigorously specifying the sizes of the primitive types and making clear that these sizes are identical on all platforms. Let us examine the properties of each of these in turn.

boolean

This is the data type used for true/false conditions. To optimize memory access time, more than one bit is used to store a boolean value. In the Sun JVM, all integer types smaller than 32 bits are promoted to 32 bits when pushed on the stack during execution. An array of booleans is treated as an array of bytes.

range of values: false, true

literals: A “literal” is a value provided at compile-time. Just write down the value that you mean, and that’s the literal. Literals have types just like variables have types. For boolean, the literals are false, true. In the code below, the assignment will always occur.

if (true) x = 33; 

You cannot cast (convert) a boolean value to any other type. However, you can always get the same effect by using an expression, for example,

if (bool) i=1; else i=0; // set int according to bool value. 
bool = (i==0? false:true); // set bool according to int value. 

In Java, the boolean type is not based on integers. In particular, the programmer cannot increment, decrement, or add boolean values. Inside a JVM, there are no instructions dedicated to booleans, and integer operations are used.

int

The type int is a 32-bit, signed, two’s-complement number, as used in virtually every modern cpu. It will be the type that you should choose by default whenever you are going to carry out integer arithmetic.

range of values: –2,147,483,648 to 2,147,483,647

literals: Int literals come in any of three varieties:

  • A decimal literal, e.g., 10 or –256

  • With a leading zero, meaning an octal literal, e.g., 077777

  • With a leading 0x, meaning a hexadecimal literal, e.g., 0xA5 or 0Xa5

Uppercase or lowercase has no significance with any of the letters that can appear in integer literals. If you use octal or hexadecimal, and you provide a literal that sets the leftmost bit in the receiving number, then it represents a negative number. (Brush up on two’s-complement format if you’re not sure why.)

A numeric literal is a 32-bit quantity, even if its value could fit into a smaller type. But provided its actual value is within range for a smaller type, an int literal can be assigned directly to something with fewer bits, such as byte, short, or char. If you try to assign an int literal that is too large into a smaller type, the compiler will insist that you write an explicit conversion, termed a “cast.”

Integer literals can be assigned to floating-point variables without casting. When you cast from a bigger type of integer to a smaller type, the high-order bits are just dropped.

long

The type long is a 64-bit, signed, two’s-complement quantity. It should be used when calculations on whole numbers may exceed the range of int. Using longs, the range of values is –263 to (263–1). Numbers up in this range will be increasingly prevalent in computing, and 264 in particular is a number that really needs a name of its own. In 1993, I coined the term “Bubbabyte” to describe 264 bytes. Just as 210 bytes is a Kilobyte, and 220 is a Megabyte, so 264 bytes is a Bubbabyte. Using a long, you can count up to half a Bubbabyte less one.

range of values: –9,223,372,036,854,775,808 to 9,223,372,036,854,775,807

literals: The general form of long literals is the same as int literals, but with an “L” or “l” on the end to indicate “long.” However, never use the lowercase letter “l” to indicate a “long” literal as it is too similar to the digit “1.” Always use the uppercase letter “L” instead. The three kinds of long literals are:

  • A decimal literal, e.g., 2047L or –10L

  • An octal literal, e.g., 0777777L

  • A hexadecimal literal, e.g., 0xA5L or OxABADCAFEDEADBE30L

All long literals are 64-bit quantities. A long literal must be cast to assign it to something with fewer bits, such as byte, short, int, or char.

byte

The byte type is an 8-bit, signed, two’s-complement quantity. The reasons for using byte are to hold a generic 8-bit value, to match a value in existing data files, or to economize on storage space where you have a large number of such values. Despite popular belief, there is no speed advantage to bytes, shorts, or chars—modern CPUs take the same amount of time to load or multiply 8 bits as they take for 32 bits.

range of values: –128 to 127

literals: There are no byte literals. You can use, without a cast, int literals provided their values fit in 8 bits. You can use char, long, and floating-point literals if you cast them.

You always have to cast a (non-literal) value of a larger type if you want to put it into a variable of a smaller type. Since arithmetic is always performed at least at 32-bit precision, this means that assignments to a byte variable must always be cast into the result if they involve any arithmetic, like this:

byte b1=1, b2=2; 
byte b3 = b2 + b1; // NO! NO! NO! compilation error 
byte b3 = (byte) (b2 + b1); // correct, uses a cast 

People often find this surprising. If I have an expression involving only bytes, why should I need to cast it into a byte result? The right way to think about it is that most modern computers do all integral arithmetic at 32-bit or 64-bit precision (there is no “8-bit add” on modern CPUs). Java follows this model of the underlying hardware. An arithmetic operation on two bytes potentially yields a bigger result than can be stored in one byte. The philosophy for numeric casts is that they are required whenever you assign from a more capacious type to a less capacious type.

short

This type is a 16-bit, signed, two’s-complement integer. The main reasons for using short are to match external values already present in a file or to economize on storage space where you have a large number of such values.

range of values: –32,768 to 32,767

literals: There are no short literals. You can use, without a cast, int literals provided their values will fit in 16 bits. You can use char, long, and floating-point literals if you cast them.

As with byte, assignments to short must always be cast into the result if the right-hand side of the assignment involves any arithmetic.

The next two types, double and float, are the floating-point arithmetic types.

double

The type double refers to floating-point numbers stored in 64 bits, as described in the IEEE [2] standard reference 754. The type double will be the default type you use when you want to do some calculations that might involve decimal places (i.e., not integral values).

range of values: These provide numbers that can range between about –1.7E308 to +1.7E308 with about 14 to 15 significant figures of accuracy. The exact accuracy depends on the number being represented. Double precision floating-point numbers have the range shown in Figure 4-1.

Type double should be used when calculations involve decimal places.

Figure 4-1. Type double should be used when calculations involve decimal places.

IEEE 754 arithmetic has come into virtually universal acceptance over the last decade, and it would certainly raise a few eyebrows if a computer manufacturer proposed an incompatible system of floating-point numbers now. IEEE 754 is the standard for floating-point arithmetic, but there are several places where chip designers can choose from different alternatives within the standard, such as rounding modes and extended precision. Java originally insisted on consistency on all hardware by specifying the alternatives that must be used. That is now being loosened somewhat.

IEEE 754 has an ingenious way of dealing with the problem of representing, on limited hardware, the unlimited amount of infinite precision real-world numbers. The problem is resolved by reserving a special value that says, “Help! I’ve fallen off the end of what’s representable and I can’t get up.” You’re probably familiar with infinity, but the “Not-a-Number” might be new if you haven’t done much numerical programming. Not-a-Number, or NaN, is a value that a floating point can take to indicate that the result of some operation is not mathematically well-defined, like dividing zero by zero.

If you get a NaN as an expression being evaluated, it will contaminate the whole expression, producing an overall result of NaN—which is exactly what you want! The worst way to handle a numeric error is to ignore it and pretend it didn’t happen.

You may never see a NaN if your algorithms are numerically stable, and you never push the limits of your datasets. Still, it’s nice to know that NaN is there, ready to tell you your results are garbage, if they head that way.

literals: It is easiest to show by example the valid formats for double literals:

1e1   2.   .3    3.14    6.02e+23d 

The format is very easy-going; just give the compiler a decimal point or an exponent, and it will recognize that a floating-point literal is intended. A suffix of “D”, “d”, or no suffix, means a double literal. In practice, most people omit the suffix.

It is also permissible to assign any of the integer literals or character literals to floats or doubles. The assignment doesn’t need a cast, as you are going from a less capacious type to a more capacious type. So a line like this, while perverse, is valid:

double cherry = '
'; 

It takes the integer value of the literal (0x0a in this case), floats it to get 10.0d, and assigns that to “cherry.” Don’t ever do this.

float

The type float refers to floating-point numbers stored in 32 bits, as described in the IEEE standard reference 754.

The justification for using single precision variables used to be that arithmetic operations were twice as fast as on double precision variables. With modern extensively pipelined processors and wide data buses between the cache and CPUs, the speed differences are inconsequential. The reasons for using floats are to minimize storage requirements when you have a very large quantity of them or to retain compatibility with external data files.

range of values: The type float provides numbers that can range between about –3.4E38 to 3.4E38 (i.e., 340,000,000,000,000,000,000,000,000,000,000,000,000) with about 6–7 significant figures of accuracy. The exact accuracy depends on the number being represented.

literals: The simplest way to understand what is allowed is to look at examples of valid float literals, as follows:

1e1f  2.f  .3f  3.14f  6.02e+23f 

A suffix of “F” or “f” is always required on a float literal. A common mistake is to leave the suffix off the float literal, as follows:

float cabbage = 6.5; 
 Error: explicit cast needed to convert double to float. 

The code must be changed to the following:

float cabbage = 6.5f; 

Also, a double literal cannot be assigned to a float variable without a cast, even if it is within the range of the float type. This is because some precision in decimal places may potentially be lost. The next section explains more about this interesting, and sometimes subtle, topic.

char

This type is a 16-bit unsigned quantity that is used to represent printable characters. Since it is an integer-based type, all the arithmetic operators are available on it. Unlike all the other arithmetic types, char is unsigned—it never takes a negative value. You should only use char to hold character data or bit values. If you want a 16-bit quantity for general calculations, don’t use char, use short. This will avoid the possible surprise of converting between signed and unsigned types. Otherwise, a cast of a negative value into char will magically become positive without the bits changing.

Java provides the framework that is capable of handling characters from just about any locale in the world. The cost is that we store and move 16 bits for each character instead of just 8 bits.

range of values:a value in the Unicode code set 0 to 65,535

You have to cast a 32- or 64-bit result if you want to put it into a smaller result. This means that assignments to char must always be cast into the result if they involve any arithmetic. An example would be:

char c = (char) (i + 42); // cast 

literals: Character literals appear between single quotes or in Strings. They can be expressed in four ways, and can be used for all of the types: char, byte, short, int, and long.

  • A single character, ‘A’

  • A character escape sequence. The allowable values are:

    ‘
    ’  (linefeed)             ‘
    ’  (carriage return)      ‘f’ formfeed 
    ‘’  (backspace)         ‘	’  (tab)                           ‘\’ (backslash) 
    ‘”’ (double quote)   ‘’’ (single quote) 
  • An octal escape sequence. This has the form ‘ nn’ where nnn is one-to-three octal digits in the range 0 to 377. Note the odd fact that you can only set the least significant 8 bits of a 16-bit char when using an octal escape sequence. Some examples are ‘’ or ‘12’ or ‘277’ or ‘377’.

  • A Unicode escape sequence. This has the form ‘uxxxx’ where xxxx is exactly four hexadecimal digits. An example is:

‘u0041’ is the character A 

Choosing Unicode for the char type was a bold and forward-looking design choice. Although a few people complained about the cost and waste of using 16 bits per character, these are the same pikers who a few years ago didn’t want to shift from two-digit years to four-digit years, and who still hold onto their abacuses while they evaluate the “cutting edge” slide rules.

Designers of forward-looking systems like Java have a responsibility to include proper support for more than just Western alphabets. Apart from anything else, customers are more likely to buy your software if it supports their native language. Until all systems have adopted Unicode, however, handling it on an ASCII system is clumsy, so avoid sprinkling Unicode literals through your code.

String

To round out this chapter, here is the standard Java class String. As a class type, it contrasts with the primitive types described up to this point in the chapter.

As the name suggests, String objects hold a series of adjacent characters like an array. It takes a method call, however (not an array reference), to pull an individual character out. You will use String instances a lot—whenever you want to store zero or more characters in a sequence or do character I/O. Arrays of char do some of these things, too, but String is a lot more convenient for comparing several characters and using literal values.

literals: A string literal is zero or more characters enclosed in double quotes, like this:

"" // empty string 
"That’ll cost you two-fifty 
" 

Because Strings are used so frequently, Java has some special built-in support. Everywhere else in Java, you use a constructor to create an object of a class, such as:

String filmStar = new String( "Arnold Alois Schwarzenegger" ); 

String literals count as a shortcut for the constructor. So this is equivalent:

String filmStar = "Arnold Alois Schwarzenegger"; 

Each string literal behaves as if it is a reference to an instance of class String, meaning that you can invoke methods on it, copy a reference to it, and so on. For the sake of performance, the compiler can implement it another way, but it must be indistinguishable to the programmer.

Like all literals, string literals cannot be modified after they have been created. Variables of class String have the same quality—once you have created a String, you cannot change a character in the middle to something else. Some people refer to this by saying, “Strings are immutable.” You can always discard any String and make the same reference variable refer to a different one in its place. You can even construct a new String out of pieces from another, so being unable to change a given String after it has been created isn’t a handicap in practice.

String Concatenation

The other String feature with special built-in support is concatenation. Whenever a String is one operand of the “+” operator, the system does not do addition. Instead, the other operand (whatever it is, object or primitive thing) will be converted to a String by calling its toString() method, and the result is the two Strings joined together. You will use this feature in many places. Here are a few examples:

  • To print out a variable and some text saying what it is:

    System.out.println( "x has value " + x 
                             + " and y has value " + y ); 
  • to break a long String literal down into smaller strings and continue it across several lines:

     "Thomas the Tank Engine and the naughty " 
    + "Engine-driver who tied down Thomas’s Boiler Safety Valve" 
    + "and How They Found Pieces of Thomas in Three Counties." 
  • To convert the value to a String (concatenating an empty String with a value of a primitive type is a Java idiom):

    int i = 256; 
         ... 
    ... "" + i // yields a String containing the value of i. 

That’s much shorter than the alternative of using the conversion method of the String class String.valueOf( i ).

String Comparison and intern()

String Comparison and intern()

Just a reminder about String comparisons. Compare two Strings like this:

if ( s1.equals(s2)) .... 

not this:

if (s1 == s2) .... 

The first compares string contents, the second, string addresses. Failing to use “equals()” to compare two strings is probably the most common single mistake made by Java novices.

There is one exception to this string comparison rule. The exception has been put in place as a performance optimization. String has a method called intern(). You can call intern on one of your strings, and it will go into a private program-wide pool that the string class maintains. It gives you back a pointer to that string in the pool. Each string is only in that pool once. If you later call intern on a string that is already in the pool, you get the shared version back to use. This works because string contents never change after creation.

All string literals and String-valued constant expressions are interned for you automatically. That ensures that you don’t have two copies of a string literal with the same contents. You can call intern() on your own strings in addition, if you wish. There is some cost to interning a string, so only do it when the number of string comparisons in your program is a lot more than the number of string creations.

The key reason to use intern() is that all strings returned from intern() can be compared for equality by using s == t instead of s.equals(t)! (Exercise: why?) The reference comparison is obviously quicker than invoking the equals method. A second benefit is that since all references to Strings of the same value use only a single object, you may save memory.

String uses another built-in class called StringBuffer to help it operate. StringBuffer differs from String in that you can change characters in the middle of a StringBuffer after it has been instantiated. StringBuffer doesn’t have any support for searching for individual characters or substrings though. StringBuffer is widely used by the compiler to implement support for concatenating two Strings into a longer String. You’ll use the class String a lot more than StringBuffer.

The following code shows the important methods of the String class. You can look at the entire source in file $JAVAHOME/java/src/lang/String.java. Also look at the HTML API, by choosing package java.lang.

public final class String implements CharSequence, Comparable, Serializable {
           // constructors with various arguments 
      public String(); 
      public String(java.lang.String); 
      public String(java.lang.StringBuffer); 
      public String(byte[]); 
      public String(byte[],int); 
      public String(byte[],int,int); 
      public String(byte[],int,int,int); 
      public String(byte[],int,int,java.lang.String) 
                                        throws UnsupportedEncodingException; 
      public String(byte[],java.lang.String) throws UnsupportedEncodingException; 
      public String(char[]); 
      public String(char[],int,int); 
            // comparisons 
      public char charAt(int); 
      public int compareTo(java.lang.Object); 
      public int compareTo(java.lang.String); 
      public int compareToIgnoreCase(java.lang.String); 
      public boolean endsWith(java.lang.String); 
      public boolean equals(java.lang.Object); 
      public boolean equalsIgnoreCase(java.lang.String); 
      public boolean regionMatches(int, java.lang.String, int, int); 
      public boolean regionMatches(boolean, int, java.lang.String, int, int); 
      public boolean startsWith(java.lang.String); 
      public boolean startsWith(java.lang.String, int); 
            // search, extract and other routines 
      public String concat(java.lang.String); 
      public static String copyValueOf(char[]); 
      public static String copyValueOf(char[], int, int); 
      public byte [] getBytes(); 
      public void getBytes(int, int, byte[], int); 
      public byte [] getBytes(java.lang.String)throws UnsupportedEncodingException; 
      public void getChars(int, int, char[], int); 
      public int hashCode(); 
      public int indexOf(int); 
      public int indexOf(int, int); 
      public int indexOf(java.lang.String); 
      public int indexOf(java.lang.String, int); 
      public native java.lang.String intern(); 
      public int lastIndexOf(int); 
      public int lastIndexOf(int, int); 
      public int lastIndexOf(java.lang.String); 
      public int lastIndexOf(java.lang.String, int); 
      public int length(); // gets the length of the string 
      public String replace(char, char); 
      //new in JDK 1.4, splits the string according to the pattern 
      public String[] split (String pattern); 
      public String[] split (String pattern, int limit); 

      public String substring(int); 
      public String substring(int, int); 
      public char toCharArray()[]; public java.lang.String toLowerCase(); 
      public String toLowerCase(java.util.Locale); 
      public String toString(); 
      public String toUpperCase(); 
      public String toUpperCase(java.util.Locale); 
      public String trim(); // chops off leading & trailing spaces 
            // conversion to String 
      public static String valueOf(char); 
      public static String valueOf(double); 
      public static String valueOf(float); 
      public static String valueOf(int); 
      public static String valueOf(long); 
      public static String valueOf(java.lang.Object); 
      public static String valueOf(boolean); 
      public static String valueOf(char[]); 
      public static String valueOf(char[], int, int); 
} 

Some Light Relief—Hatless Atlas

Here’s a cheery song that was written by top programmer David H. Zobel and circulated on the Internet for more than a while. It’s sung to the tune of Twinkle, Twinkle, Little Star, but to sing it you have to know how some programmers pronounce the shifted and control characters on a keyboard. The “^” character above the “6” is often pronounced “hat” because it looks like a little hat. Some people give the name “huh” to “?”, and “wow” to “!”. Both of those are a lot shorter than more conventional names.

The song is called Hatless Atlas and it goes like this:

^ < @ < . @ *

Hat less at less point at star,

} " _ # |

backbrace double base pound space bar.

- @ $ & / _ %

Dash at cash and slash base rate,

!( @ | = >

wow open tab at bar is great.

; ' + $ ? ^?

Semi backquote plus cash huh DEL,

, # " ∼ | ) ^G

comma pound double tilde bar close BEL.

This song can be enjoyed on more than one level. While the theme is not totally transparent, key elements are revealed. The bare-headed strong man relishes nature (“point at star”), and then enjoys the full hospitality of a tavern (“Wow, open tab at bar is great”). Soon he finds that the question of payment does arise, after all; hence, the veiled reference to Alan Greenspan (“slash base rate”) and the finality overshadowing that closing lament “bar close BEL”!

I like to think that in the years to come wherever programmers gather in the evening, after the pizza is all eaten and a sufficient quantity of beer has been drunk, a piano may start to play softly in the corner. Quietly, one member of the group will sing, and then more and more of the programming staff will join in. Any systems analysts who haven’t yet quaffed themselves unconscious might sway unsteadily with the beat. Soon several choruses of Hatless Atlas will roll lustily around the corners of the room. Old-timers will talk of the great bugs they have overcome and the days of punching clocks, cards, and DOS.

Or maybe we’ll all stay home and watch reruns of Star Trek: Kirk Violates the Prime Directive with Xena, Warrior Princess instead, who knows?



[1] ISO is the International Organization for Standardization, a federation of national standards bodies.

[2] IEEE is the Institute of Electrical and Electronic Engineers, a U.S. professional body.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.222.21.30