Page 5




Literal Constants

In JAVA, we can assign to data explicitly expressed values. These values are called literal constants. Literal constants can be used for assignment statements, comparisons, and calculations. But literal constants have types just as our own data does, and we must be mindful of this fact.
The numerical data types have, as literal constants, either the integers or the reals. Any literal constant in which you include a decimal point is automatically a decimal type (either floating point or double precision floating point). When you do not include a decimal point, it will be some integer type. For example, the literal constant 18 would be the integer eighteen, whereas the literal constant 18.0 would be the decimal eighteen.
JAVA also allows a form of scientific notation, but only for decimal values. To express a decimal in scientific notaiton, you can write in any value, followed by either a capital or lowercase 'e', followed by an integer number. This result is the first number multiplied the second number's power of ten. For example, 500 = 5 * 100 = 5 * 10^2 so you would write 5e2. Note that ^, the carrot character, does not represent exponentiation in JAVA. Note also that writing 5e2 does not stand for 25, the second power of 5.
The boolean type also has literal constants available to it. Since there are only two values, JAVA made each of these values a JAVA keyword. They are true and false.
The char type has, as its literal constants, any single character (or no character at all) in single quotes. For example, 'a', 'b', and 'c'. Note that when we write out 1, this is an integer literal constant whereas '1' is a character literal constant. The char value of '' is the default value for chars.
Classes, in general, only have one literal constant value for their object references. This is the JAVA keyword null. This keyword is often very useful for comparisons between object references since they are, after all, only references. A comparison between any object reference and the JAVA keyword null will tell you immediately whether or not the reference is actually referring to an actual object or not.
Two very specific Classes, the String class and the [] (array) class, have their own unique literal constants. However, the array literal constants may be only used for initialization. They may not be used for reassignment, comparisons, or calculations. String literal constants are simliar to char literal constants. They are formed somply by placing the desired value in double quotes. For example, "Hello, World!" is a String literal constant. Although String literal constants may be used for comparison with the double equals comparison operator, since Strings are objects we will always use the equals() method to for comparisons. We will never ever ever use the dobule equals comparison operator to compare String objects.
The array initialization lists are ordered lists, sourounded by curly braces ( { and } ), and with a comma-separated list of the successive values. For example, an int[] initialization list might look like {1,2,3,4,5}, a char[] initialization list would look like {'1','2','3','4','5'}, and a String[][] initialization list would look like { {"hello","world"} , {"nice","to","see","you"} , {"again"} }. Note that the array of arrays has as its initialization list an initialization list of initialization lists, thus following the pattern.



Type Conversions

The studious, pragmatic, axiomatic mathematician will most likely want to keep separate the differing numeric types as we so far have. He will realize that the definitions for the different types are, in most set-theory classes, unreconcilable. At most he would be willing to say that there is a subset of real numbers that is isomorphic to the integers, or something really complicated like that.
Fortunately, we are not so pragmatic! We wish to say at least that an integer value may be assigned to a decimal value. But of course, we get stuck going in the other direction. While we could repsent the integer 5 as the decimal 5.0, we could not ever hope to represent the decimal 5.4 as any integer. (The aforementioned pragmatic mathmetician will start ranting and raving something utterly incoherent about "different sizes of infinity" or some and other foolish notions). But ultimately, this means that we will need to take all pairs of every single JAVA data type, and see if we can devise a way to safely go from one to the other.
When looking at all the JAVA numeric primitives, we can see from the range of the values that a well-ordering can be obtained from the smallest to the largest. That is, a short can always step in and represent a byte, since the range of a short covers at least the range of a byte. (Some may want to say that one is a proper subset of another). Continuing in this fashion, we arrive at the following ordering: byte --> short --> int --> long --> float --> double . Whenever we take of advantage of this ordering in comparison, assignment, or computation, we will call this numeric promotion. For example, a double may be safely assigned the value of an int, due to numeric promotion. In fact, the statement 'double x = 3;' actually uses numeric promotion.
To go in the reverse order of numeric promotion runs the risk of losing information. But we will allow ourselves to do this anyways through a process called explicit casting. To explicitly cast ont type to another, simply place the desired type in parentheses immediately in front of the data. For example, if we had declared a double x and assigned it to 7.5, we could cast it to an int, and then assign that value to an int y by saying: int y = (int)x.
This ability to explicitly cast goes beyond numeric types, however. Remember from inheritance that a subclass, by definition, is an instance of the superclass. Therefore, we can impose at least a hierarchical ordering on classes, and apply a kind of promotion when necessary. Say we have two classes, Rectangle and Square. We can say the following without any syntax errors: Rectangle a; Square b; a = b; (of course, not on the same line!). A kind of promotion will occur during the last assignment statement since a Square is a Rectangle. However, we could not hope to perform the reverse assignment without casting, since we are not garunateed that all Rectangles are Squares. For this assignment we would write the following: Rectanlge a; Square b; b = (Square)a; We must first cast the rectangle to a square, before assignment can occur. Note that while this may not cause a syntax error, it would probably cause a runtime error if a does not actually refer to a Square object.
The char type presents various possibilities. To account for integers, the ASCII table was invented. ASCII stands for Ameircan Standard Code for Information something or other, and it simply maps the type byte to char (and vice vera). Take a look at the ASCII table to see that the character 'a' maps to the integer 97 and the character '1' maps to the number 49. Assignment from any numeric type to a char requires an explicit cast, and assignment from a char to either a byte or a short requires an explicit cast.
In general, object references of one class cannot be assigned to object references of any other, without incurring either a compilation error or a runtime error. The exception to this is, of course, inheritance. In that case, promotion can occur upwards through the hierarchy tree, and explicit casting may be possible downwards, but only if you really do have the type required. Otherwise, Strings cannot be reconciled with arrays, or with MainWindows, or Donuts, or anything of that sort.
Moreover, you cannot cast between object references and primitives. This may seem strange in at least one case. We should think that we can at least treat characters as Strings, but we can't. The best we can do is wait until we learn about the String concatenation operator.