Copyright (c) 2000 by Charlie Calvert
This chapter covers the basic facts about working with Java types. You will read about all eight simple types -- or primitive types, as they are sometimes called -- in the Java language. You will also find examples of how to work with each of these types.
When focusing on the JBuilder IDE, the chapter focuses on using the designers to work with the JMenu, JMenuBar and JMenuItem classes. The JComboBox class is also used in this chapter. The example program from this chapter will give you plenty of opportunity to set up event handlers that respond to the visual controls in your application. Finally, this chapter continues the discussion of classes and methods that was begun in the last chapter.
In general, the subject matter of this chapter covers not only types, but also many general programming issues. So, without further ado, let's begin our exploration of the basic Java types.
Java, being a well defined, strongly typed language, handles the whole subject of types with remarkable aplomb. There are only eight types, and each one is admirably simple in conception. Table 1 provides an overview of the types that will be discussed in this chapter.
| Type | Size | Range or Comment |
|---|---|---|
| boolean | NA Usually 32 | only false, true |
| byte | 8 bits | -127 to 127 |
| char | 16 bits | Any Unicode or standard character |
| short | 16 bits | -32,768 to 32,767 |
| int | 32 bits | -2,147,483,648 to 2,147,483,647 |
| long | 64 bits | -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 |
| float | 32 bits | -3.4E38 to 3.4E38 (6-7 significant digits) |
| double | 64 bits | -1.7E308 to 1.7E308 (15-16 significant digits) |
Table 1: The eight types, their sizes, and their ranges.
Each of these types is always set to a certain immutable number of bits. You have none of the monkey business that you get in C++ or Pascal, where an int (or Integer) is 16 bits in one set of circumstances and 32 bits in another. A Java int has 32 bits in all instances on all platforms. Neither do you have to worry about whether a particular value is signed or not. All types are signed, that is, they can be either negative or positive numbers. There is no such thing as an unsigned integer type in java. Oh frabjous day, collooh, collay! What an admirable design!
As you can see by looking at the table, there are simple types for 8, 16, 32 and 64 bit integers, or scalar numbers, as they sometimes called. The integer types (byte, short, int and long) hold whole numbers such as 1, 5, 25, -15 or 0. The types with the larger number of bits hold larger numbers.
The floating point types (float and double) differ from the integer types (byte, short, int and long) in that they can have decimal places. For instance, the number 3.2 is a floating point number, and the number 16 is an integer.
The char type is not 8, but 16 bits. This means that it is Unicode ready. Unicode characters are important because they capture foreign language sets such as kanji characters. In the old world of DOS programming, kanji characters were difficult to encode, because the char type had only 8 bits, and therefore could contain only 256 characters. There are thousands of Kanji characters, and to capture them all, a new standard needed to be developed. That standard is called Unicode, and Java fully supports it.
The boolean type only needs to capture one of two values: true or false. Nevertheless, the type usually takes up 32 bits, since that is the default size for a word on most modern computers. However, the subject of how much space a boolean takes up is purely academic, since it literally can contain only two values, and cannot be coerced into containing any other values. Later in the chapter I will take this subject up again, covering it in more depth and in plainer English.
Listing 1: The MyTypes class shows how to use all the basic Java types.
package foo;
public class MyTypes
{
// Boolean: This is a simple type, and can only be true or false. It can't
// be coerced into being an int or a char.
boolean myBool;
// Characters such as 'A' 'B' 'C'. For strings use the String class instead.
char myChar;
// Integers
byte myByte; // 8 bit
short myShort; // 16 bit
int myInt; // 32 bit
long myLong; // 64 bit, use L in assignments of literals: MyLong = 2L;
// Floating Point
float myFloat; // 32 bit, use F in assignments of literals: myFloat = 2.0F
double myDouble; // 64 bit
public MyTypes()
{
myBool = true;
myChar = 'A';
myByte = Byte.MAX_VALUE; // 127;
myShort = Short.MAX_VALUE; // 32767;
myInt = Integer.MAX_VALUE; // 2147483647;
myLong = 9223372036854775807L; // Add an l or L for literals
myFloat = 1.0f; // Add an f or F to declare literal
myDouble = Double.MAX_VALUE;
}
public byte getMyByte()
{
return myByte;
}
public String getMinByteAsString()
{
return Byte.toString(Byte.MIN_VALUE);
}
public int getMyInt()
{
return myInt;
}
public String getMinIntegerAsString()
{
return Integer.toString(Integer.MIN_VALUE);
}
public long getMyLong()
{
return myLong;
}
public String getMinLongAsString()
{
return Long.toString(Long.MIN_VALUE);
}
public short getMyShort()
{
return myShort;
}
public String getMinShortAsString()
{
return Integer.toString(Short.MIN_VALUE);
}
public float getMyFloat()
{
return myFloat;
}
public String getMinFloatAsString()
{
return Float.toString(Float.MIN_VALUE);
}
public double getMyDouble()
{
return myDouble;
}
public String getMinDoubleAsString()
{
return Double.toString(Double.MIN_VALUE);
}
}
The purpose of the class is to show how to use all the simple types in Java. The code also gives us practice working with the syntax of classes and methods. Let's take a look at this code and see if we can make some sense out of it.
The class begins by declaring a few variables:
// Boolean: This is a simple type, and can only be true or false. It can't // be coerced into being an int or a char. boolean myBool; // Characters such as 'A' 'B' 'C'. For strings use the String class instead. char myChar; // Integers byte myByte; // 8 bit short myShort; // 16 bit int myInt; // 32 bit long myLong; // 64 bit, use L in assignments of literals: MyLong = 2L; // Floating Point float myFloat; // 32 bit, use F in assignments of literals: myFloat = 2.0F double myDouble; // 64 bit
The first value is a boolean, the second a char, the third a byte, the fourth a short, the fifth an int, the sixth a long, the seventh a float, and the eighth a double. There they all are -- all the simple types available in Java.
Now that we've declared all the simple Java types, what do we do with them? The answer to that question is actually fairly complex, and takes up the majority of the rest of this chapter. I begin the examination in the next section, where you can take a look at the constructor for the MyTypes class.
The first significant code in this class initializes all the values in the class's constructor:
public MyTypes()
{
myBool = true;
myChar = 'A';
myByte = Byte.MAX_VALUE; // 127;
myShort = Short.MAX_VALUE; // 32767;
myInt = Integer.MAX_VALUE; // 2147483647;
myLong = 9223372036854775807L; // Add an l or L for literals
myFloat = 1.0f; // Add an f or F to declare literal
myDouble = Double.MAX_VALUE;
}
The variables myBool and myChar are assigned literal values. A literal is simply a raw declaration of some value such as a string, a character, or a number. You can't assign a value to a literal, they are not variables. myBool is a variable, the value true is a literal value. myChar is a variable, 'A' is a literal. myByte is a variable, the number 127 is a literal. String is a class type, while a string literal is written like this: "This is a string literal."
The code in the MyTypes class initializes the byte variable to the largest possible byte value, which is 127:
myByte = Byte.MAX_VALUE; // 127;
I could, of course, have written: myByte = 127. Assigning myBool to the literal value 127 would have had the exact same result as the code I wrote here. Instead, I used the MAX_VALUE field of the Byte class, which returns a constant equal to the maximum legal value for a Byte. Needless to say, the class can also return a MIN_VALUE. The only reason to use MAX_VALUE is that it will help you remember the maximum value for a byte. In C++ or Pascal you use similar functions in part because some types, such as integers, vary in size depending on the platform you are using. But here you don't have to worry about that, and you use the tool simply as a mnemonic.
You are allowed to write myByte = Byte.MAX_VALUE without using new to create an instance of the Byte class. This is legal because MAX_VALUE is declared to be static. In particular, here is the way the values are declared in the Java source code:
public final class Byte extends Number implements Comparable
{
/**
* The minimum value a Byte can have.
*/
public static final byte MIN_VALUE = -128;
/**
* The maximum value a Byte can have.
*/
public static final byte MAX_VALUE = 127;
Don't worry about the extends and implements business in the class header. I'll explain all that later in this text. I include that line simple so you can see that you are looking at the declaration for the Byte class.
As you can see, MIN_VALUE is declared to be a simple variable of type byte:
byte MIN_VALUE = -128;
That's as simple programming gets. But what about the "public static final" business? What's that all about?
You saw in the last chapter that the word public means that the variable can be accessed from outside of the package in which the class is declared. This is of course crucial in this case, since the Java source code is not declared in the same directory as your program.
The word static means that you can access this variable without creating an instance of the class. In other words, you don't have to write this:
Byte myByte = new Byte(); byte myVariable = myByte.MAX_VALUE;
Instead, you can write:
byte myVariable = Byte.MAX_VALUE;
Normally you can't access the fields or methods of a class without first creating an instance of the class. The only time, in fact, that you can do it, is when you are accessing a method or field that is declared static.
Note yet again the perhaps too subtle interplay between the type byte and the class Byte. Classes should always begin with a capital letter, and simple types begin with a small letter. It's madness, it's definitely part of the dark side of the Java language, but it is how the game is played. Whether a letter is capitalized or not can make a lot of difference in Java. Perhaps a bit too much difference for my tastes!
And what about final? What is that all about? The keyword final is used when you want to declare a value that will not and cannot change. Many other languages use the word const to designate the same thing. Java chose final for reasons that are often explained in various convoluted sentences that contain lots of words but little logic. When the dust settles, one comes back to the fact that the creators of Java wanted to use the word final rather than the word const. It was just a matter of taste.
NOTE: When launched on one of the verbal excesses posing as explanations of the const vs final issue, writers often mention the to me unrelated fact that you can use the word final when declaring an instance of a class:
final Byte myByte = new Byte();
This means that the variable myByte will never be assigned to anything else other than this particular instance of this class. The behavior of the class does not change because you do this, it is only that you are promising never to assign myByte to anything else other than this one instance of this class.
You can also use the word final when passing a parameter to a method. If you do that, then you are allowing the compiler to make some optimizations.
Don't worry if none of the things in this note make any sense to you. They are advanced programming issues, and are not relevant to most code written by new or intermediate level programmers. If you feel compelled to focus on one of these two issues, I would say that the latter one, involving passing parameters, strikes me as more important than the first. However, having absolutely no knowledge of this subject will not in any way impair your ability to write perfectly acceptable beginning or intermediate level Java code.
Intellectually curious readers may want to know exactly how I found the declaration for the Byte class. JBuilder makes this process easy. In the source code for your program, find the variable or type that you want to explore. For instance, find a place in your code that reads Byte.MAX_VALUE. Highlight the word Byte with the mouse, right click on it, and choose Browse Symbol from the pop up menu. The appropriate source file will be loaded automatically, and you will automatically be taken to the proper place in that source.
When you are browsing the source from the JDK, you will see a tab in the JBuilder IDE called Doc. (In Figure 1, the tab is hidden by the purple popup window.) If you click on the Doc tab you will see the docs for the class you are currently viewing . As a rule, there are doc files for all the classes in the JDK. However, the classes that you create will not have docs unless you explicitly create them. There is a technology called Java Doc for creating these documents.
The previous paragraphs highlight two important facts:
Besides MAX_VALUE and MIN_VALUE, the Byte class has other useful features such as the method toString, which converts a byte to String. For instance, it would convert the number 127 to the string "127". I will show exactly how to do this later in the chapter.
JBuilder provides a powerful tool called code insight that can help you explore the Byte class. In fact, it can help you explore any Java source code -- or any other source code, including your own. In particular, you can find all the methods of the Byte class by using code insight.
To use code insight, type in an instance of a class or the name of class followed by a period. For instance, write the letters Byte followed by a period in your source code. Now press Ctrl Alt H or Ctrl Space, depending on the type of key board emulation you are using. (To find out which strokes to use, select Tools | IDE Options from the menu, turn to the code insight page, and select the KeyStrokes button.) After pressing the right keys, a purple window will pop up showing all the methods of your class, as shown in Figure 1. This list is created dynamically, so it will be available for the SDK and for classes that you declare. It will always reflect the current state of the object.
Figure 1: The JBuilder IDE supports code insight. Here you can see the fields and methods of the Byte class in the purple popup window.
We've covered a lot of ground in this section of the chapter, but there is still a point I want to mention before moving on to the next subject. Consider these two lines from the MyTypes constructor:
myLong = 9223372036854775807L; // Add an l or L for literals myFloat = 1.0f; // Add an f or F to declare literal
Notice that I have appended an L on to the end of the number assigned to myLong. You must always do this when assigning a literal to a long. A similar rule is in effect for floats. When you assign a literal to a float, append an f to the number.
In the two lines under discussion I could have written code that paralleled the other examples in the constructor:
myLong = Long.MAX_VALUE; myFloat = Float.MAX_VALUE;
I didn't take this approach simply because I wanted to show you the fact that you needed to add l's and f's to literals that are assigned to these types.
We're through now with the subject of initializing types. In the next few sections I will say a few more words about the Java simple types, then move on to a discussion of a program that exercises the types.
I initialize the boolean type to true.
myBool = true
I could have set it to false. There are no other values to which you can set a boolean.
In C/C++ and Object Pascal, you can treat a boolean variable as a numeric value if you want. You can't do that in Java. The only thing you can do with a boolean is set it to true or false.
In Java you cannot type cast an integer value to treat it as a boolean. In Pascal or C++ you can draw parallels between the number zero and the value false, and any other scalar number and the value true. You can't do this in Java, unless you want to write code that looks like this:
void jMenuItem2_actionPerformed(ActionEvent e)
{
int Num = Integer.parseInt(jTextField1.getText());
boolean myBool = (Num == 0 ? false:true);
if (myBool == false)
jTextField1.setText("false");
else
jTextField1.setText("true");
}
This code checks to see whether a scalar number is zero. If it is zero, it sets myBool equal to false, if it is non-zero, it sets it equal to true. It's a long way around, but the end effect is the same as typecasting the number as a boolean. (If you are thrown by the syntax in this method, don't fear, as I will discuss this kind of thing in more depth later in the text.) In particular, this subject is known as branching, and when I write the text on branching in Java, I will discuss the kind of syntax you find here.
chars are character values, that is they are letters such as 'A', 'B', or 'C'. You can also set chars equal to basic syntactical elements of a string, such as a space, a tab character or an exclamation point. A char can also be set equal to a number, such as '1' or '2'. However, you have to realize that the character '1' is fundamentally different from the number 1. You always define characters by putting single quotes around them, while you define strings by putting double quotes around them. This is a char: 'a', and this is a string: "My String".
The char value I initialize to the letter A. In Java, you typically don't use chars as strings. Instead, you use the String class when you want to work with strings. In other words, there is no simple type for a string in Java. As I will show in a later chapter, you can create an array of char. But don't try to use an array of char as a string. Trying to treat an array of char as a string in Java is simply too complicated. The language isn't designed to support that kind of syntax.
You can perform basic arithmetic operations on chars. Consider the following code:
void AddCharMenu_actionPerformed(ActionEvent e)
{
char temp = 'A';
String S;
jTextField1.setText("");
for (int i = 0; i < 26; i++)
{
S = jTextField1.getText();
S = S + temp + ' ';
jTextField1.setText(S);
temp++;
}
}
As you can see, this method is an event handler. In particular, it will be called in response to a menu selection, but it could just as well occur in response to a button press. (Later in this chapter I will show how to set up menus, for now, just concentrate on the core code in the body of the method.)
I declare two variables, one of type char, and the other of type String. I initialize the char to the letter A, but do not initialize the String to anything. On the frame for this application, I have dropped down a JTextField. After declaring my variables, the first thing I do in the method is empty any text in the JTextField.
I then begin a for loop. Most readers will probably know what for loops are, but don't worry if they are unfamiliar to you. I will talk about them in more depth later in the text when I cover looping. For now, you need merely know that any code between the beginning of the for loop and the curly brace that closes the for loop will be repeated 26 times. In particular, the following code will be repeated 26 times:
S = jTextField1.getText();
S = S + temp + ' ';
jTextField1.setText(S);
temp++;
I begin by retrieving the string from the JTextField. The first time through the loop, the string will be empty. I then set it equal to itself, plus the current value of Temp, plus a space character. The first time through the loop, the end result is this:
A
I show the user the value of the string by calling the setText method of the JTextField object. (Remember that Java programmers write JTextField with a capital J when they are talking about the JTextField class, but they write jTextField1 with a small j when creating a default variable name to point at an instance of this object. You can, of course, give the variable any name you want, but jTextField1 is the default name assigned by the IDE to the first instance of this type of object that you drop on a form. The second instance gets the name jTextField2, etc.)
The last line of the code in the loop increments the value of temp by using the ++ operator. In other words, it adds 1 to the value of temp, which is 'A'. What is A plus 1, you might ask? The mathematicians in the crowd already have the answer, while readers with a background in the humanities are probably wondering what I could possibly be talking about. A is a letter, and what sense does it make to add a number to letter? Well, it happens that A + 1 equals, naturally enough, B!
How can this be? you ask. Good question. The thing to remember about computers is that numbers underlie everything you see on the screen. Internally, the letter A is represented by a number. The letter B is represented by the next number in that sequence, the letter C by the next letter, and so on. So if you add 1 to A, you get the next item in the sequence, which is B. You can usually count on computers being very logical. If the number 65 stands for A, then the number 66 will stand for B, 67 for C, and so on.
It happens that not only are computers logical, but in this particular case, so is your author. In particular, it happens that the letter A is in fact represented by the number 65, B by 66, C by 67, etc. As a result, the first two lines of our method could have read looked like this:
char Temp = 65;
String S;
When you are working with chars, there is no difference between writing char Temp = 'A'; and write char Temp = 65;. If all this sounds confusing, don't be disturbed. It's just an example of they way computers like to operate.
Consider the following two lines from Shakespeare's Sonnet 22:
My glass shall not persuade my I am old, So long as youth and thou are of one date;
People with a background in the humanities understand that Shakespeare is saying that he does not feel old so long as his love remains young. A necessary corollary of this idea explains a lot irrational behavior that men engage in while traversing their middle years. Shakespeare doesn't speak as plainly as he could because he wants to:
Artists have their reasons for doing things, and computer programmers have their own reasons for doing things. Each discipline has its own mysteries, its own charms, its own reasons for going about things in a particular way. chars in Java have a special relationship to numbers. It's the way of the world for programmers.
All of this makes possible an explanation of a fact I mentioned at the beginning of this section. I said that the character '1' is not the same thing as the number 1. The issue here is that the character '1' is almost always represented on computers by the number 49. I say almost always, because the value of a char depends a little on the character set you are using, I will take up this subject again at the end of this chapter.
It is now time to return now to the subject at hand, which was incrementing char values with the ++ operator. As you recall, the loop in our method is going to repeat 26 times. So now the code jumps back to the beginning of the loop and uses the getText method of JTextField to retrieve the current value of the string in the text field. It then appends the current value of temp plus one space to this string:
S = jTextField1.getText();
S = S + Temp + ' ';
When the string is first retrieved from the JTextField, it equals "A ". After executing the second line in the loop, it equals "A B ". The code then increments temp again by calling temp++. Now temp is equal to 67 or 'B'.
Needless to say, the loop continues on in this fashion, executing 26 times. By the time it is done, our little method has taught Java to say its ABCs, as shown in Figure 2.
Figure 2: Driven by the power of a loop and the relationship between chars and numbers, Java learns to say its ABCs.
I mentioned earlier that the character '1' is usually equal to 49. I say usually because the actual values printed by a particular font can vary. You know that some fonts are called Times Roman, others Courier, others Arial, while other fonts take on even more exotic characteristics such as gothic letters or characters that look like written script. All of these different font sets nearly always follow the standard that the 65th character in the set will be the letter 'A', and the 49 character in the set will be the number 1, etc. However, there is nothing that says that a particular character set cannot do something ever so logical such as setting the first character to the number 1, the second to 2, etc. In practice, this is not going to happen, as it would cause chaos in the computer world. The font would not work on any standard editor. But there is no theoretical reason why fonts of this type could not be made. For instance, someone undoubtedly created such a font as an Aprils fools joke. Furthermore, some character sets don't show numbers or letters at all. For instance, the wing dings character set, common on Windows installations, shows only a series of iconic pictures, and never shows any numbers or letters at all. Character sets of this latter type are fairly common, since they have an obvious contract with the user stating that they cannot be used to depict the letters alphabet, as shown in Figure 3.

Figure 3: The same four characters shown in several different characters sets. Note the third character set does not show any letters at all.
The tenth character in most character sets is the line feed character, which can be written like this: '\n'. The following table shows how to work with some other characters of this type:
| Character | Number | Name |
|---|---|---|
| '\b' | 8 | backspace |
| '\t' | 9 | tab |
| '\n' | 10 | linefeed |
| '\f' | 12 | formfeed |
| '\r' | 13 | carriage return |
| '\"' | 34 | double quote |
| '\'' | 39 | single quote |
| '\\' | 92 | backslash |
That's all I want to say about characters. Later in the book we can chat some about character arrays, but that is really a different subject.
Bytes represent whole numbers between -128 and 127. They take up 8 bits.
Why is it that a byte ranges from -128 to 127? Why doesn't it range from some nice round number like -250 to 250. Or why must it have a range at all?
The issue here is that you can only hold a number of a certain size in 8 bits. A bit is a binary number that can hold either 0 or 1. A one bit number can therefore hold only the values 0 and 1. A two bit number allows you to count up to 3.
| Binary | Base Ten |
|---|---|
| 00 | 0 |
| 01 | 1 |
| 10 | 2 |
| 11 | 3 |
With 3 bits you can count up to 7.
| Binary | Base Ten |
|---|---|
| 000 | 0 |
| 001 | 1 |
| 010 | 2 |
| 011 | 3 |
| 100 | 4 |
| 101 | 5 |
| 110 | 6 |
| 111 | 7 |
With 4 bits you can get to 15, with 5 bits you can get to 31, 6 bits gets you 63, 7 bits to 127, and 8 bits to 256.
All that is simple enough. The question then becomes, if 8 bits allows you to count up to 256, why does the 8 bit byte type go only up to 127? The reason is that the eighth bit, the highest bit, is considered the sign of the number. If the eighth bit is a 1, then the number is negative, if it is 0 then the number is positive. This means that the eighth bit is already spoken for, meaning that you only have 7 bits to work with, and the highest number you can depict with 7 bits is 127.
The previous section ended with a discussion of bits. One of the interesting corollaries of all you read about bits is that it is not legal to write the following code:
byte a = 1, b = 2, c; c = a + b;
Instead, you must write:
byte a = 1, b = 2, c; c = (byte)(a + b);
What you are doing in the second case is typecasting the value (a + b) to a byte. You must perform this typecast because the value a + b could be larger than 127. As a result, the compiler assumes that the result of the addition will be larger than a byte. It is expecting a type larger than a byte. In particular, according to the type promotion rules of Java, the compiler will convert the result to an int. The only way to keep it from doing this is to explicitly use a typecast.
In the previous example, if a were equal to 100 and b were equal to 100 then a + b would equal 200, which cannot be captured in 7 bits. As a result, the result of the addition would not be 200 but -56. There are reasons why the number -56 emerges here, and many of you can probably figure them out, but for our purposes it's simplest to say that the result of such an addition would be undefined.
The governing rule in this case is that whenever you want to assign a smaller type to a larger type, you have to use a typecast. A typecast coerces the compiler into doing something it would normally consider illogical. You are saying, in effect: "Hey, I know that adding two bytes together can be problematic, but in this case I promise you that it will work out." Note that you must perform the typecast even if you explicitly set the values a and b to values that will not exceed 127. The computer is too busy with other matters to bother checking whether the addition will proceed safely. Instead, it insists that you take responsibility for the code.
Here is another way of stating the same thing. You can assign smaller numerical values to large numerical values. For instance, you can assign a byte to a short:
byte MyByte = 3; short MyShort; MyShort = MyByte;
To go the opposite way, you must use an explicit cast:
byte MyByte = 3; short MyShort; MyByte = (byte)MyShort;
The following code is legal:
byte a = 100, b = 100; int c; c = a + b;
Even if a were set to Byte.MAX_VALUE and b to Byte.MAX_VALUE, the value of the two numbers added together would not exceed Integer.MAX_VALUE. As a result, you do not need to perform a typecast. In other words, you are trying to assign from a larger type to a smaller type, so you can proceed with normal code.
It is legal to assign a char to a short, int or long so long as you use a typecast:
short x; char y = 'A'; x = (short)(y);
In this case, x would, of course, be set equal to 65.
By now you have probably heard more than you wanted to hear about bytes, ints, shorts and longs. The only topic I haven't addressed is probably the one uppermost in your mind, namely: "What type should I use by default in my code?" Fortunately, the answer to this question is very simple: use the int type!
Most computers these days use 32 bit operating systems and 32 bit chips. For instance the Intel Pentium chips are all 32 bit chips. Windows 2000 and Windows 98 are both 32 bit operating systems. This means that they work most readily with 32 bit values. As a result, it usually takes a computer longer to work with a byte than it does to work with an int. We might find numbers in the range -128 to 127 easier to work with than numbers in the range -2,147,483,648 to 2,147,483,647. Computers, however, don't think that way. They don't find it any easier to work with the number 1 than the number 2,147,483,647. It's all the same to them, they are both numbers that fit neatly into 32 bits.
Furthermore, a computer has to go out of its way to work with a value that is explicitly cast to be less than 32 bits. Its harder for a 32 bit Intel chip to work with a byte than to work with an int! Not necessarily a lot harder, and sometimes it all amounts to the same thing, but it certainly is never, or at least very rarely, easier or faster for the chip to work with 8 bit values rather than 32 bit values.
Given these facts, then why shoud we even both with bytes and shorts? It happens that there are some occasions when they are useful. Sometimes when you are performing bit manipulations, then it really matters how many bits there are in a particular value. Or if you want to declare an array of 10,000 numbers, then an array of 10,000 bytes will take up ten thousands bytes of memory, while an array of 10,000 ints will take up 40,000 bytes of memory. Most of the time, however, these kinds of issues are not worth your consideration, and you should just use ints.
The sad fact of the matter is that most beginning and intermediate level programmers never really get anywhere when they try to optimize their code. Attempts to use bytes instead of ints in order to save space or speed up your code will backfire as often as not for any but the most expert programmer. Furthermore, expert programmers wrote the compilers and SDKs that you use. As a result, they often automatically put in optimizations that speed up your code. In other words, they often see when it is useful to automatically convert an int to a byte, or vice versa, and they perform the chore for automatically in the background in a totally save and highly efficient manner.
All of which is not to say that really good programmers can't optimize their code effectively. They can. But optimizing code is a lot more complicated than most programmers think. As a result, smart programmers who haven't achieved expert status and who aren't unusually gifted often don't waste a lot of time trying to optimize their code.
Just as bytes, shorts, ints and longs are all consider integer types, so are floats and doubles both considered to be floating point types. The words "floating point" are just a generic way of referring to any number that contains a decimal point.
A floating point literal is assumed to be a value of type double. In other words, if you write 5.5 or 0.2, then the compiler automatically converts that number to a double. Therefore it is illegal to write the following
float a = 5.6;
This code assigns a float to a double, which is illegal, since you can't assign a smaller type to a larger type. As a result, you must write:
float a = (float)(5.6)
or
float a = 5.6f
of
float a = 5.6F
All of these statements are different ways of saying the same thing. In other words, appending an f or an F to a floating point number is the same thing as typecasting it to a float.
Here is how to assign a float to an int:
float a = (float)(1.2);
int b;
b = (int)(a);
The typecast is all you need.
If you multiple an int times a double, the rules of Java say that the result will be a double unless you explicitly typecast it to be some other type. As mentioned earlier, this is known as type promotion. If you add or multiply two bytes or shorts together, the result is automatically promoted to an int. If you add or multiple an integer type with a floating point type the result will always be a double, unless you use typecast it to coerce the compiler into treating it as some other type.
It is at last time to start using the simple, or primitive, types in a Java program. The first program is not very practical, but hopefully you will find it helps you understand what the simple types are about, and what kinds of operations you usually perform with them.
The code shown in Listing 2 demonstrates how to use the MyTypes class. As in the previous chapter, I assume that you have created a directory called foo beneath your project and dropped the MyTypes class into that directory. You must also add a statement to import the package foo into your current project. (If you wanted, you could put MyTypes.java into the same directory as your Frame1.java and then change the package name to correspond to the package where your project is listed.
You can download a copy of this project in zip format here. The main form for the project is shown in Figure 1.
Listing 2: The source to the Frame1.java file from the CallMyTypes project.
package callmytypes;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import foo.*;
public class Frame1 extends JFrame
{
JPanel contentPane;
JMenuBar jMenuBar1 = new JMenuBar();
JMenu jMenu1 = new JMenu();
JMenuItem jMenuItem1 = new JMenuItem();
JMenu jMenu2 = new JMenu();
JMenu jMenu3 = new JMenu();
JMenuItem rawMyIntegerMenu = new JMenuItem();
JMenuItem rawMyByteMenu = new JMenuItem();
JMenuItem rawMyLongMenu = new JMenuItem();
JMenuItem rawMyFloatMenu = new JMenuItem();
JMenuItem rawMyDoubleMenu = new JMenuItem();
JMenu jMenu4 = new JMenu();
JMenuItem stringMyByteMenu = new JMenuItem();
JMenuItem stringMyShortMenu = new JMenuItem();
JMenuItem stringMyIntegerMenu = new JMenuItem();
JMenuItem stringMyLongMenu = new JMenuItem();
JMenuItem stringMyFloatMenu = new JMenuItem();
JMenuItem stringMyDoubleMenu = new JMenuItem();
MyTypes myTypes = new MyTypes();
JComboBox jComboBox1 = new JComboBox();
JComboBox jComboBox2 = new JComboBox();
JLabel jLabel1 = new JLabel();
JLabel jLabel2 = new JLabel();
JMenuItem AllRawMenu = new JMenuItem();
JMenuItem AllStringMenu = new JMenuItem();
JMenuItem rawMyShortMenu = new JMenuItem();
JTextField jTextField1 = new JTextField();
JMenu jMenu5 = new JMenu();
JMenuItem AddCharMenu = new JMenuItem();
JMenuItem jMenuItem2 = new JMenuItem();
//Construct the frame
public Frame1()
{
enableEvents(AWTEvent.WINDOW_EVENT_MASK);
try
{
jbInit();
}
catch(Exception e)
{
e.printStackTrace();
}
}
//Component initialization
private void jbInit() throws Exception
{
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(null);
this.setSize(new Dimension(400, 300));
this.setTitle("Frame Title");
jMenu1.setText("File");
jMenuItem1.setText("Exit");
jMenu2.setText("Options");
jMenu3.setText("Raw");
rawMyIntegerMenu.setText("myInteger");
rawMyIntegerMenu.addActionListener(new Frame1_rawMyIntegerMenu_actionAdapter(this));
rawMyByteMenu.setText("myByte");
rawMyByteMenu.addActionListener(new Frame1_rawMyByteMenu_actionAdapter(this));
rawMyLongMenu.setText("myLong");
rawMyLongMenu.addActionListener(new Frame1_rawMyLongMenu_actionAdapter(this));
rawMyFloatMenu.setText("myFloat");
rawMyFloatMenu.addActionListener(new Frame1_rawMyFloatMenu_actionAdapter(this));
rawMyDoubleMenu.setText("myDouble");
rawMyDoubleMenu.addActionListener(new Frame1_rawMyDoubleMenu_actionAdapter(this));
jMenu4.setText("AsString");
stringMyByteMenu.setText("myByte");
stringMyByteMenu.addActionListener(new Frame1_stringMyByteMenu_actionAdapter(this));
stringMyShortMenu.setText("myShort");
stringMyShortMenu.addActionListener(new Frame1_stringMyShortMenu_actionAdapter(this));
stringMyIntegerMenu.setText("myInteger");
stringMyIntegerMenu.addActionListener(new Frame1_stringMyIntegerMenu_actionAdapter(this));
stringMyLongMenu.setText("myLong");
stringMyLongMenu.addActionListener(new Frame1_stringMyLongMenu_actionAdapter(this));
stringMyFloatMenu.setText("myFloat");
stringMyFloatMenu.addActionListener(new Frame1_stringMyFloatMenu_actionAdapter(this));
stringMyDoubleMenu.setText("myDouble");
stringMyDoubleMenu.addActionListener(new Frame1_stringMyDoubleMenu_actionAdapter(this));
jComboBox1.setBounds(new Rectangle(33, 50, 331, 27));
jComboBox2.setBounds(new Rectangle(33, 114, 330, 27));
jLabel1.setText("Raw Max Values");
jLabel1.setBounds(new Rectangle(34, 27, 188, 18));
jLabel2.setText("String Min Values");
jLabel2.setBounds(new Rectangle(35, 91, 178, 18));
AllRawMenu.setText("All Raw");
AllRawMenu.addActionListener(new Frame1_AllRawMenu_actionAdapter(this));
AllStringMenu.setText("All AsString");
AllStringMenu.addActionListener(new Frame1_AllStringMenu_actionAdapter(this));
rawMyShortMenu.setText("myShort");
rawMyShortMenu.addActionListener(new Frame1_rawMyShortMenu_actionAdapter(this));
jTextField1.setText("jTextField1");
jTextField1.setBounds(new Rectangle(33, 174, 329, 22));
jMenu5.setText("Play");
AddCharMenu.setText("Add Char");
AddCharMenu.addActionListener(new Frame1_AddCharMenu_actionAdapter(this));
jMenuItem2.setText("Bool Test");
jMenuItem2.addActionListener(new Frame1_jMenuItem2_actionAdapter(this));
jMenuBar1.add(jMenu1);
jMenuBar1.add(jMenu2);
jMenuBar1.add(jMenu5);
jMenu1.add(jMenuItem1);
jMenu2.add(jMenu3);
jMenu2.add(jMenu4);
jMenu3.add(rawMyByteMenu);
jMenu3.add(rawMyShortMenu);
jMenu3.add(rawMyIntegerMenu);
jMenu3.add(rawMyLongMenu);
jMenu3.add(rawMyFloatMenu);
jMenu3.add(rawMyDoubleMenu);
jMenu3.add(AllRawMenu);
jMenu4.add(stringMyByteMenu);
jMenu4.add(stringMyShortMenu);
jMenu4.add(stringMyIntegerMenu);
jMenu4.add(stringMyLongMenu);
jMenu4.add(stringMyFloatMenu);
jMenu4.add(stringMyDoubleMenu);
jMenu4.add(AllStringMenu);
contentPane.add(jLabel1, null);
contentPane.add(jComboBox1, null);
contentPane.add(jLabel2, null);
contentPane.add(jComboBox2, null);
contentPane.add(jTextField1, null);
jMenu5.add(AddCharMenu);
jMenu5.add(jMenuItem2);
this.setJMenuBar(jMenuBar1);
}
//Overridden so we can exit when window is closed
protected void processWindowEvent(WindowEvent e)
{
super.processWindowEvent(e);
if (e.getID() == WindowEvent.WINDOW_CLOSING)
{
System.exit(0);
}
}
void rawMyIntegerMenu_actionPerformed(ActionEvent e)
{
jComboBox1.addItem("Integer: " + Integer.toString(myTypes.getMyInt()));
}
void rawMyLongMenu_actionPerformed(ActionEvent e)
{
jComboBox1.addItem("Long : " + Long.toString(myTypes.getMyLong()));
}
void rawMyFloatMenu_actionPerformed(ActionEvent e)
{
jComboBox1.addItem("Float: " + Float.toString(myTypes.getMyFloat()));
}
void rawMyByteMenu_actionPerformed(ActionEvent e)
{
jComboBox1.addItem("Byte: " + Byte.toString(myTypes.getMyByte()));
}
void rawMyShortMenu_actionPerformed(ActionEvent e)
{
jComboBox1.addItem("Short: " + Short.toString(myTypes.getMyShort()));
}
void rawMyDoubleMenu_actionPerformed(ActionEvent e)
{
jComboBox1.addItem("Double: " + Double.toString(myTypes.getMyDouble()));
}
void stringMyByteMenu_actionPerformed(ActionEvent e)
{
jComboBox2.addItem("Byte: " + myTypes.getMinByteAsString());
}
void stringMyShortMenu_actionPerformed(ActionEvent e)
{
jComboBox2.addItem("Short: " + myTypes.getMinShortAsString());
}
void stringMyIntegerMenu_actionPerformed(ActionEvent e)
{
jComboBox2.addItem("Integer: " + myTypes.getMinIntegerAsString());
}
void stringMyLongMenu_actionPerformed(ActionEvent e)
{
jComboBox2.addItem("Long: " + myTypes.getMinLongAsString());
}
void stringMyFloatMenu_actionPerformed(ActionEvent e)
{
jComboBox2.addItem("Float: " + myTypes.getMinFloatAsString());
}
void stringMyDoubleMenu_actionPerformed(ActionEvent e)
{
jComboBox2.addItem("Double: " + myTypes.getMinDoubleAsString());
}
void AllStringMenu_actionPerformed(ActionEvent e)
{
this.stringMyByteMenu_actionPerformed(null);
stringMyShortMenu_actionPerformed(null);
stringMyIntegerMenu_actionPerformed(null);
stringMyLongMenu_actionPerformed(null);
stringMyFloatMenu_actionPerformed(null);
stringMyDoubleMenu_actionPerformed(null);
}
void AllRawMenu_actionPerformed(ActionEvent e)
{
rawMyByteMenu_actionPerformed(null);
rawMyShortMenu_actionPerformed(null);
rawMyIntegerMenu_actionPerformed(null);
rawMyLongMenu_actionPerformed(null);
rawMyDoubleMenu_actionPerformed(null);
rawMyFloatMenu_actionPerformed(null);
}
void AddCharMenu_actionPerformed(ActionEvent e)
{
char temp = 65;
String S;
jTextField1.setText("");
for (int i = 0; i < 26; i++)
{
S = jTextField1.getText();
S = S + temp + ' ';
jTextField1.setText(S);
temp++;
}
}
void jMenuItem2_actionPerformed(ActionEvent e)
{
int Num = Integer.parseInt(jTextField1.getText());
boolean myBool = (Num == 25 ? true:false);
if (myBool == false)
jTextField1.setText("false");
else
jTextField1.setText("true");
}
}
class Frame1_rawMyIntegerMenu_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_rawMyIntegerMenu_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.rawMyIntegerMenu_actionPerformed(e);
}
}
class Frame1_rawMyLongMenu_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_rawMyLongMenu_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.rawMyLongMenu_actionPerformed(e);
}
}
class Frame1_rawMyFloatMenu_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_rawMyFloatMenu_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.rawMyFloatMenu_actionPerformed(e);
}
}
class Frame1_rawMyByteMenu_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_rawMyByteMenu_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.rawMyByteMenu_actionPerformed(e);
}
}
class Frame1_rawMyDoubleMenu_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_rawMyDoubleMenu_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.rawMyDoubleMenu_actionPerformed(e);
}
}
class Frame1_stringMyByteMenu_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_stringMyByteMenu_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.stringMyByteMenu_actionPerformed(e);
}
}
class Frame1_stringMyShortMenu_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_stringMyShortMenu_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.stringMyShortMenu_actionPerformed(e);
}
}
class Frame1_stringMyIntegerMenu_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_stringMyIntegerMenu_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.stringMyIntegerMenu_actionPerformed(e);
}
}
class Frame1_stringMyLongMenu_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_stringMyLongMenu_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.stringMyLongMenu_actionPerformed(e);
}
}
class Frame1_stringMyFloatMenu_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_stringMyFloatMenu_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.stringMyFloatMenu_actionPerformed(e);
}
}
class Frame1_stringMyDoubleMenu_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_stringMyDoubleMenu_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.stringMyDoubleMenu_actionPerformed(e);
}
}
class Frame1_AllStringMenu_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_AllStringMenu_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.AllStringMenu_actionPerformed(e);
}
}
class Frame1_AllRawMenu_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_AllRawMenu_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.AllRawMenu_actionPerformed(e);
}
}
class Frame1_rawMyShortMenu_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_rawMyShortMenu_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.rawMyShortMenu_actionPerformed(e);
}
}
class Frame1_AddCharMenu_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_AddCharMenu_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.AddCharMenu_actionPerformed(e);
}
}
class Frame1_jMenuItem2_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_jMenuItem2_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.jMenuItem2_actionPerformed(e);
}
}
There is a long of code in this program, but most of it is very simple. If you had to write all those code yourself, you would soon become exhausted. By JBuilder Foundation makes the process of creating a program of this type very simple. 98 percent of the code you see here was generated automatically by the IDE. All you had to do was type in the body of a few methods.
Before I can describe the code, however, I need to spend a few moments talking about menus. I do this in the next section.
The simplest way to add menus to your program is to include them from the very beginning by requesting them from the application wizard. When you choose File | New | Application, the wizard will ask you if you want to add menus to your main form. If you answer yes to this question, then your program will automatically contain a few basic menu items that you can edit to suit your purposes. However, we don't always remember or think to do add menus when creating a project.
If you want to add menus to an existing form that does not have menus, turn to the Swing Containers page of the component palette and drop down a jMenuBar. Then add the following line of code to the end of your jbInit method:
this.setJMenuBar(menuBar);
If you want to add menus to an existing form in an entirely manual fashion, you can do so by adding a few simple lines of code to your program. Start by adding this code at the top of your declaration for Frame1:
public class Frame1 extends JFrame
{
JPanel contentPane;
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu();
... // Code ommitted here
I've included the declaration for Frame1 and the contentPane just to give you enough code to get oriented.
Now add the following code to your JBInit method:
menuBar.add(menu); this.setJMenuBar(menuBar);
Once you have included this code, you can switch over to the designers, and begin creating the rest of the menu, and modifying the code you inserted manually. The fact that you can create visual items either in code or by using the visual tools is a technology that Borland calls two way tools. Two way tools are glorious, because they insure that you are not working with any black boxes. You can use either the source code or the visual tools to create you program, its up to you. In practice, most people use a combination of the two approaches. The key point, however, is that JBuilder is not locking you into some visual tool which creates code you can't understand. Instead, JBuilder just uses standard Java code. The trick is simply that it gives you visual ways to manipulate that standard code. Once again, the code is totally standard. Its exactly the same code you would write if you weren't using visual tools.
In the structure pane for Frame 1, you can find a place to edit menus, as shown in Figure 4. To get a view like the one in Figure 4, right click on the word Menu in the structure pane, and chose Activiate Designer from the menu.

Figure 4: Working with menus in the menu designer. At top left, the navigator pane. Beneath it is the structure pane. To the right is the menu designer. On the far right is the inspector.
To edit any of the items, you can use either the designer itself, or the inspector, which is shown to the right of the designer. In Figure 4, if you look to the right of the word Play, you can see a little area with a dotted outline. If you double clicked on this area, it would turn into an edit control. There you could type in the caption for a new JMenu. Adding this caption will automatically create the menu itself. You can use the same process to add a JMenuItem to the bottom of an existing drop down menu. For instance, if you double clicked on the area beneath the words AsString or the words All Raw, then you would get a chance to type in the caption for your menu, and the JMenuItem itself would be appended to the menu.
To further edit the menus, you can work in the Inspector. The key fields you need to use for now are the text property on the Properties page, and the action performed event on the Events page. You can flip back and forth between the Properties page and the Events page by clicking on the tabs at the bottom of the Inspector, as shown in Figure 5 and Figure 6.
Figure 5: The Properties page of the Inspector. Use the tabs at the bottom of the inspector to choose this page.
Figure 6: The Events page of the Inspector. Use the tabs at the bottom of the inspector to choose this page.
If you look at the Figure 5, you can see that I have changed the default name of this JMenuItem from jMenuItemX to AllRawMenu. I have made this change because the name AllRawMenu tells me something about what the menu item does, while jMenuItemX does not tell me anything about what the menu item does.
On the Events page, shown in Figure 6, you can see that I have associated an event with this menu item. To do this, I simply turned to the Events page, highlighted the actionPerformed event, and the pressed the Enter key. The words allRawMenu_actionPerformed were typed in for me automatically by the IDE, and the following code was added to my program:
// Code omitted here
void allRawMenu_actionPerformed(ActionEvent e)
{
}
}
class Frame1_allRawMenu_actionAdapter implements java.awt.event.ActionListener
{
Frame1 adaptee;
Frame1_allRawMenu_actionAdapter(Frame1 adaptee)
{
this.adaptee = adaptee;
}
public void actionPerformed(ActionEvent e)
{
adaptee.allRawMenu_actionPerformed(e);
}
}
You've seen code like this before. The class at the bottom of the code fragment is the adapter which will automatically handle events for me. In particular, whenever the AllRawMenu is selected by the user, the Frame1_AllRawMenu_actionAdapter class will automatically call the allRawMenu_actionPerformed method.
This program uses some nested menus, as shown in Figure 4. The nomenclature for menus runs as follows. The bar along the top of the program that contains the menus is called a JMenuBar. The individual words which appear on the JMenuBar each are held by an instance of the Java JMenu class. When you drop down a JMenu, you get a list of words such as Raw and AsString. Each of these are JMenuItems.
If you drill down one layer further, so that the Raw JMenuItem has a another menu in it, then you call that a nested menu. The JMenuItems with captions that read myByte, myInt, etc, are all part of a nested menu. I created this nested menu by right clicking on the word Raw and selecting Insert Nested Menu from the JBuilder popup menu.
Most of the methods that handling clicks on the menu items in the CallMyTypes program are very simple. All they do is call methods in the MyTypes class and then display the results of the call to the user.
The calls in the program demonstrate how to use each of the numeric types. (The program also shows how to use booleans and chars, but I showed you the code for those methods earlier in this chapter in the Thinking about chars and Working with booleans sections.)
Here is the code for working with the int type:
void rawMyIntegerMenu_actionPerformed(ActionEvent e)
{
jComboBox1.addItem("Integer: " + Integer.toString(myTypes.getMyInt()));
}
As shown in Figure 2, the main form for this program contains two JComboBoxes. You can find the JComboBoxes on the swing page of the component palette. The code in this method places some text in the first of these combo boxes. It does this by calling the addItem method of the JComboBox class.
The MyTypes class has a method called getMyInt, which returns the value to which we initialized the variable myInt in the MyTypes constructor:
myInt = Integer.MAX_VALUE; // 2147483647;
// Code omitted here
public int getMyInt()
{
return myInt;
}
It should be clear to you that getMyInt will return the value 2147483647. I use the toString method of the Integer class to convert this number into a String. After doing this, the program is holding the string value "2147483647" in memory. I then use the + operator to concatenate the string "Integer: " to the string "2147483647". The end result is "Integer: 2147483647". (I will talk more about operators in Chapter Eight.) This is the value that is placed in the JComboBox.
Another JMenuItem actionPerformed response method looks like this:
void stringMyIntegerMenu_actionPerformed(ActionEvent e)
{
jComboBox2.addItem("Integer: " + myTypes.getMinIntegerAsString());
}
The code shown here calls the getMinIntegerAsString method of the MyTypes class. Here is what that method looks like:
public String getMinIntegerAsString()
{
return Integer.toString(Integer.MIN_VALUE);
}
By now you should be starting to understand the rhythm of this program. It consists of a series of menu items, each of which calls a method from the MyTypes class. Once I have called all the methods in the class, then the program is done.
I'm not going to step through each of those methods, since the process is repetitive and relatively simple to understand. Instead, I suggest that you spend time examining Listing 2, going over it until it all makes sense to you. Furthermore, you should spend time running the program in the JBuilder IDE, experimenting with it as you see fit. The best possible course of action would be to create the program yourself in the IDE, rather than just running my copy of it.
When you are working with the program, please note that I show you standard Java class types used to wrap each of the simple types.
| Simple Type | Class Type |
|---|---|
| byte | Byte |
| short | Short |
| int | Integer |
| long | Long |
| float | Float |
| double | Double |
I use each of the class types at least once in the program. Usually I just call the toString method of the class, or use the MAX_VALUE or MIN_VALUE fields of the class. In fact, there isn't a whole lot more to the classes than just these few features, but you can use the online help or browse the source to find out more if you wish.
There are two methods in the CallMyTypes application that deserve perhaps a moments comment. If you are working your way through the nested menus in this program, it can take quite awhile to fill in the JComboBoxes with the results from all the methods in the MyTypes class. For instance, you have to individually click on the myByte, myShort, myInt, etc JMenuItems. While not a daunting task, this process still gets a bit trying at times. As a result I created a menu item with the label "All Raw" which will call all the nested JMenuItems at once. Here is the method which is called in response to a click on the "All Raw" JMenuItem:
void allRawMenu_actionPerformed(ActionEvent e)
{
rawMyByteMenu_actionPerformed(null);
rawMyShortMenu_actionPerformed(null);
rawMyIntegerMenu_actionPerformed(null);
rawMyLongMenu_actionPerformed(null);
rawMyDoubleMenu_actionPerformed(null);
rawMyFloatMenu_actionPerformed(null);
}
This code calls each of the response method for the other nested JMenuItems in this group. As result, a single click on this the All Raw menu item has the effect of calling all the other methods in that group of menu items.
Each of the response methods called in this event takes a parameter of type ActionEvent:
void stringMyIntegerMenu_actionPerformed(ActionEvent e)
It is not yet time for us to begin discussing ActionEvents. That subject belongs in a later chapter of this text. Fortunately, in this case we can ignore the parameter altogether, and pass in null in its place.
You can think of the value null as pointing to a class that has not been initialized. Normally we reference the address of a class by writing the name of a variable that points to it:
MyTypes myTypes = new TMyTypes()
In this code, myTypes references an actual instance of a class of type MyTypes. It is, for all intents and purposes, a pointer to the place in memory where an initialized instance of the class MyTypes resides. If we set myTypes equal to null, then we are saying that this variable does not point to an initialized instance of the MyTypes class. It points at nothing, it references nothing. It is just a variable, and you can't do much with it other than say its name. Its value is nil, nothing, null!
A class that doesn't point at anything isn't much good to you most of the time. But in this one case, there is some value in it. In particular, it allows you to call your method handlers without having to come up with an initialized variable of type ActionEvent. Since you are not going to use the ActionEvent object, there is no harm in omitting it in this case.
That is all I'm going to say about the Java simple, or primitive, types. Hopefully this chapter has given you a sense of what they are all about.
Here is a list of all eight of the simple types:
This chapter also gave you a look at an example application called CallMyTypes. The program has shown you how to use the simple types. Perhaps of equal importance, is the fact that the application makes heavy use of menus and events. Creating menus and events in Java is normally a time consuming process that involves a lot of typing. JBuilder eliminates the need for you to doing any typing of all that repetitive menu and event handler code. It literally saves you hours, if not days, of time.
Creating a program like CallMyTypes would be a major undertaking without the help of visual tools like those found in JBuilder. That's a pity, because the program is conceptually very simple. The code in the program isn't difficult, it's just long and repetitive. JBuilder eliminates all that typing and all that repetition. Its one of the great advantages of using this tool!