Working with Variables and Data Types

In this chapter, you find out the basics of working with variables in Java. Variables are the key to making Java programs general purpose. For example, the Hello, World! programs in the previous chapter are pretty specific: The only thing they say is, "Hello, World!" But with a variable, you can make this type of program more general. For example, you could vary the greeting, so that sometimes it would say "Hello, World!" and other times it would say "Greetings, Foolish Mortals." Or you could personalize the greeting, so that instead of saying "Hello, World!" it said "Hello, Bob!" or "Hello, Amanda!"

Variables are also the key to creating programs that can perform calculations. For example, suppose you want to create a program that calculates the area of a circle given the circle's radius. Such a program uses two variables: one to represent the radius of the circle, the other to represent the circle's area. The program asks the user to enter a value for the first variable. Then, it calculates the value of the second variable.

Declaring Variables

In Java, you must explicitly declare all variables before using them. This rule is in contrast to some languages-most notably Basic and Visual Basic, which let you use variables that haven't been automatically declared. Allowing you to use variables that you haven't explicitly declared might seem a pretty good idea at first glance-but it's a common source of bugs that result from misspelled variable names. Java requires that you explicitly declare variables so that if you misspell a variable name, the compiler can detect your mistake and display a compiler error.

The basic form of a variable declaration is this:

type name;

Here are some examples:

int x;
String lastName;
double radius;

In these examples, variables named x, lastName, and radius are declared. The x variable holds integer values, the lastName variable holds String values, and the radius variable holds double values. For more information about what these types mean, see the section "Working with Primitive Data Types" later in this chapter. Until then, just realize that int variables can hold whole numbers (such as 5, 1,340, or -34), double variables can hold numbers with fractional parts (such as 0.5, 99.97, or 3.1415), and String variables can hold text values (such as “Hello, World!” or “Jason P. Finch”).

  Tip 

Notice that variable declarations end with semicolons. That's because a variable declaration is itself a type of statement.

  REMEMBER 

Variable names follow the same rules as other Java identifiers, as I describe in Book II, Chapter 1. In short, a variable name can be any combination of letters and numerals, but must start with a letter. Most programmers prefer to start variable names with lowercase letters, and capitalize the first letter of individual words within the name. For example, firstName and salesTaxRate are typical variable names.

Declaring two or more variables in one statement

You can declare two or more variables of the same type in a single statement, by separating the variable names with commas. For example:

int x, y, z;

Here, three variables of type int are declared, using the names x, y, and z.

  Tip 

As a rule, I suggest you avoid declaring multiple variables in a single statement. Your code is easier to read and maintain if you give each variable a separate declaration.

Declaring class variables

A class variable is a variable that any method in a class can access, including static methods such as main. When declaring a class variable, you have two basic rules to follow:

  • You must place the declaration within the body of the class, but not within any of the class methods.
  • You must include the word static in the declaration. The word static comes before the variable type.

The following program shows the proper way to declare a class variable named helloMessage:

public class HelloApp
{
 static String helloMessage;

 public static void main(String[] args)
 {
 helloMessage = "Hello, World!";
 System.out.println(helloMessage);
 }
}

As you can see, the declaration includes the word static and is placed within the HelloApp class body, but not within the body of the main method.

  Tip 

You don't have to place class variable declarations at the beginning of a class. Some programmers prefer to place them at the end of the class, as in this example:

public class HelloApp
{
 public static void main(String[] args)
 {
 helloMessage = "Hello, World!";
 System.out.println(helloMessage);
 }

 static String helloMessage;
}

Here the helloMessage variable is declared after the main method.

I think classes are easier to read if the variables are declared first, so that's where you see them in this book.

Declaring instance variables

An instance variable is similar to a class variable, but doesn't specify the word static in its declaration. As its name suggests, instance variables are associated with instances of classes. As a result, you can only use them when you create an instance of a class. Because static methods aren't associated with an instance of the class, you can't use an instance variable in a static method-and that includes the main method.

For example, the following program won't compile:

public class HelloApp
{
 String helloMessage; // error -- should use static keyword

 public static void main(String[] args)
 {
 helloMessage = "Hello, World!";
 System.out.println(helloMessage); // will not compile
 }
}

If you attempt to compile this program, you get the following error messages:

C:JavaHelloApp.java:7: non-static variable helloMessage
 cannot be referenced from a static context
 helloMessage = "Hello, World!";
 ^
C:JavaHelloApp.java:8: non-static variable helloMessage
 cannot be referenced from a static context
 System.out.println(helloMessage);
 ^

Both of these errors occur because the main method is static, so it can't access instance variables.

Instance variables are useful whenever you create your own classes. But because I don't cover that until Book III, you won't see many examples of instance methods in the remainder of the chapters in Book II.

Declaring local variables

A local variable is a variable that's declared within the body of a method. Then, you can use the variable only within that method. Other methods in the class aren't even aware that the variable exists.

Here's a version of the HelloApp class in which the helloMessage variable is declared as a local variable:


public class HelloApp
{
 public static void main(String[] args)
 {
 String helloMessage;
 helloMessage = "Hello, World!";
 System.out.println(helloMessage);
 }
}

Note that you don't specify static on a declaration for a local variable. If you do, the compiler generates an error message and refuses to compile your program. Local variables always exist in the context of a method, and they exist only while that method is executing. As a result, whether or not an instance of the class has been created is irrelevant.

  Tip 

Unlike class and instance variables, a local variable is fussy about where you position the declaration for it. In particular, you must place the declaration prior to the first statement that actually uses the variable. Thus the following program won't compile:

public class HelloApp
{
 public static void main(String[] args)
 {
 helloMessage = "Hello, World!"; // error -- helloMessage
 System.out.println(helloMessage); // is not yet declared
 String helloMessage;
 }
}

When it gets to the first line of the main method, the compiler generates an error message complaining that it can't find the symbol “helloMessage”. That's because it hasn't yet been declared.

Although most local variables are declared near the beginning of a method's body, you can also declare local variables within smaller blocks of code marked by braces. This will make more sense to you when you read about statements that use blocks, such as if and for statements. But here's an example:

if (taxRate > 0)
{
 double taxAmount;
 taxAmount = subTotal * taxRate;
 total = subTotal + total;
}

Here the variable taxAmount exists only within the set of braces that belongs to the if statement.


Initializing Variables

In Java, local variables are not given initial default values. The compiler checks to make sure that you have assigned a value before you use a local variable. For example, the following program won't compile:

public class testApp
{
 public static void main(String[] args)
 {
 int i;
 System.out.println("The value of i is " + i);
 }
}

If you try to compile this program, you get the following error message:

C:Java	estApp.java:6: variable i might not have been
 initialized
 System.out.println("The value of i is " + i);
 ^

To avoid this error message, you must initialize local variables before you can use them. You can do that by using an assignment statement or an initializer, as I describe in the following sections.

  Tip 

Unlike local variables, class variables and instance variables are given default values. Numeric types are automatically initialized to zero, and String variables are initialized to empty strings. As a result, you don't have to initialize a class variable or an instance variable, although you can if you want them to have an initial value other than the default.

Initializing variables with assignment statements

One way to initialize a variable is to code an assignment statement following the variable declaration. Assignment statements have this general form:

variable = expression;

Here the expression can be any Java expression that yields a value of the same type as the variable. For example, here's a version of the main method from the previous example that correctly initializes the i variable before using it:

 public static void main(String[] args)
 {
 int i;

 i = 0;
 System.out.println("i is " + i);
 }

In this example, the variable is initialized to a value of zero before the println method is called to print the variable's value.

You find out a lot more about expressions in Book II, Chapter 3. For now, you can just use simple literal values, such as 0 in this example.

Initializing variables with initializers

Java also allows you to initialize a variable on the same statement that declares the variable. To do that, you use an initializer, which has the following general form:

type name = expression;

In effect, the initializer lets you combine a declaration and an assignment statement into one concise statement. Here are some examples:

int x = 0;
String lastName = "Lowe";
double radius = 15.4;

In each case, the variable is both declared and initialized in a single statement.

When you declare more than one variable in a single statement, each can have its own initializer. For example, the following code declares variables named x and y, and initializes x to 5 and y to 10:

int x = 5, y = 10;
  Warning 

When you declare two class or instance variables in a single statement but use only one initializer, you can mistakenly think the initializer applies to both variables. For example, consider this statement:

static int x, y = 5;

Here, you might think that both x and y would initialize to 5. But the initializer only applies to y, so x is initialized to its default value, 0. (If you make this mistake with a local variable, the compiler displays an error message for the first statement that uses the x variable because it isn't properly initialized.)


Using Final Variables (Constants)

A final variable, also called a constant, is a variable whose value you can't change once it's been initialized. To declare a final variable, you add the final keyword to the variable declaration, like this:

final int WEEKDAYS = 5;

Although you can create final local variables, most final variables are class or instance variables. To create a final class variable (sometimes called a class constant), add static final (not final static) to the declaration:

static final WEEKDAYS = 5;
  Tip 

Although it isn't required, using all capital letters for final variable names is common. You can easily spot the use of final variables in your programs.

Constants are useful for values that are used in several places throughout a program and that don't change during the course of the program. For example, suppose you're writing a game that features bouncing balls and you want the balls to always have a radius of 6 pixels. This program probably needs to use the ball diameter in several different places-for example, to draw the ball on-screen, to determine whether the ball has hit a wall, to determine whether the ball has hit another ball, and so on. Rather than just specify 6 whenever you need the ball's radius, you can set up a class constant named BALL_RADIUS, like this:

static final BALL_RADIUS = 6;

Using a class constant has two advantages:

  • If you later decide that the radius of the balls should be 7, you make the change in just one place-the initializer for the BALL_RADIUS constant.
  • The constant helps document the inner workings of your program. For example, the operation of a complicated calculation that uses the ball's radius is easier to understand if it specifies BALL_RADIUS rather than 6.


Working with Primitive Data Types

The term data type refers to the type of data that can be stored in a variable. Java is sometimes called a strongly typed language because when you declare a variable, you must specify the variable's type. Then the compiler ensures that you don't try to assign data of the wrong type to the variable. For example, the following code generates a compiler error:


int x;
x = 3.1415;

Because x is declared as a variable of type int (which holds whole numbers), you can't assign the value 3.1415 to it.

Java has an important distinction between primitive types and reference types. Primitive types are the data types defined by the language itself. In contrast, reference types are types defined by classes in the Java API rather than by the language itself.

A key difference between a primitive type and a reference type is that the memory location associated with a primitive type variable contains the actual value of the variable. As a result, primitive types are sometimes called value types. In contrast, the memory location associated with a reference type variable contains an address (called a pointer) that indicates the memory location of the actual object. I explain reference types more fully in the section "Using Reference Types" later in this chapter, so don't worry if this explanation doesn't make sense just yet.

  TECHNICAL STAUFF 

It isn't quite true that reference types are defined by the Java API and not by the Java language specification. A few reference types, such as Object and String, are defined by classes in the API, but those classes are specified in the Java Language API. And a special type of variable called an array, which can hold multiple occurrences of primitive or reference type variables, is considered to be a reference type.

Java defines a total of eight primitive types. Table 2-1 lists them. Of the eight primitive types, six are for numbers, one is for characters, and one is for true/false values. Of the six number types, four are types of integers and two are types of floating-point numbers. I describe each of the primitive types in the following sections.

Table 2-1: Java's Primitive Types
Open table as spreadsheet

Type

Explanation

int

A 32-bit (4-byte) integer value

short

A 16-bit (2-byte) integer value

long

A 64-bit (8-byte) integer value

byte

An 8-bit (1-byte) integer value

float

A 32-bit (4-byte) floating-point value

double

A 64-bit (8-byte) floating-point value

char

A 16-bit character using the Unicode encoding scheme

boolean

A true or false value

Integer types

An integer is a whole number-that is, a number with no fractional or decimal portion. Java has four different integer types, which you can use to store numbers of varying sizes. The most commonly used integer type is int. This type uses four bytes to store an integer value that can range from about negative two billion to positive two billion.

If you're writing the application that counts how many hamburgers McDonald's has sold, an int variable might not be big enough. In that case, you can use a long integer instead. long is a 64-bit integer that can hold numbers ranging from about negative 9,000 trillion to positive 9,000 trillion. (That's a big number, even by federal-deficit standards.)

In some cases, you may not need integers as large as the standard int type provides. For those cases, Java provides two smaller integer types. The short type represents a two-digit integer, which can hold numbers from −32,768 to +32,767. And the byte type defines an 8-bit integer that can range from −128 to +127.

Although the short and byte types require less memory than the int and long types, there's usually little reason to use them. A few bytes here or there won't make any difference in the performance of most programs-so you should stick to int and long most of the time. And use long only when you know that you're dealing with numbers too large for int.

  TECHNICAL STAUFF 

In Java, the size of integer data types is specified by the language and is the same regardless of what computer a program runs on. This is a huge improvement over the C and C++ languages, which let compilers for different platforms determine the optimum size for integer data types. As a result, a C or C++ program written and tested on one type of computer might not execute identically on another computer.

  Tip 

Java allows you to promote an integer type to a larger integer type. For example, Java allows the following:

int xInt;
long yLong;
xInt = 32;
yLong = xInt;

Here, you can assign the value of the xInt variable to the yLong variable because yLong is a larger size than xInt. However, Java does not allow the converse:

int xInt;
long yLong;
yLong = 32;
xInt = yLong;

The value of the yLong variable cannot be assigned to the xInt because xInt is smaller than yLong. Because this assignment might result in a loss of data, Java doesn't allow it.

(If you need to assign a long to an int variable, you must use explicit casting as described in the "Type casting" section later in this chapter.)

Floating point types

Floating-point numbers are numbers that have fractional parts (usually expressed by using a decimal point). You should use a floating-point type whenever you need a number with a decimal, such as 19.95 or 3.1415.

Java has two primitive types for floating-point numbers: float, which uses four bytes, and double, which uses eight bytes. In almost all cases, you should use the double type whenever you need numbers with fractional values.

The precision of a floating-point value indicates how many significant digits the value can have following its decimal point. The precision of a float type is only about 6 or 7 decimal digits, which isn't sufficient for most types of calculations. For example, if you use Java to write a payroll system, you might get away with using float variables to store salaries for employees such as teachers or firefighters, but not for professional baseball players or corporate executives.

In contrast, double variables have a precision of about 15 digits, which is enough for most purposes.

  TECHNICAL STAUFF 

Floating-point numbers actually use exponential notation (also called scientific notation) to store their values. That means that a floating-point number actually records two numbers: a base value (also called the mantissa) and an exponent. The actual value of the floating-point number is calculated by multiplying the mantissa by two raised to the power indicated by the exponent. For float types, the exponent can be from −127 to +128. For double types, the exponent can be from −1,023 to +1,024. Thus, both float and double variables are capable of representing very large and very small numbers.

You can find more information about some of the nuances of working with floating-point values in Book II, Chapter 3.

When you use a floating-point literal, you should always include a decimal point, like this:

double period = 99.0;

Getting scientific with floats and doubles

If you have a scientific mind, you may want to use scientific notation when you write floating-point literals. For example

 double e = 5.10e+6;

This equation is equivalent to

 double e = 5100000D;

The sign is optional if the exponent is positive, so you can also write

 double e = 5.10e6;

Note that the exponent can be negative to indicate values smaller than 1. For example

 double impulse = 23e-7;

This equation is equivalent to

 double impulse = 0.0000023;

If you omit the decimal point, the Java compiler treats the literal as an integer. Then, when it sees that you're trying to assign the integer literal to a double variable, the compiler converts the integer into a double value. This avoidable conversion step uses some precious processing time.

To save that time, you can add an F or D suffix to a floating-point literal to indicate whether the literal itself is of type float or double. For example:

float value1 = 199.33F;
double value2 = 200495.995D;

If you omit the suffix, D is assumed. As a result, you can usually omit the D suffix for double literals.

  TECHNICAL STAUFF 

Interestingly, floating-point numbers have two distinct zero values: a negative zero and a positive zero. You don't have to worry about these much, because Java treats them as equal. Still, it would make for a good question on Jeopardy! ("I'll take weird numbers for $200, Alex.")

The char type

The char type represents a single character from the Unicode character set. It's important to keep in mind that a character is not the same as a string; you find out about strings later in this chapter, in the section "Working with Strings." For now, just realize that a char variable can store just one character, not a sequence of characters as a string can.

To assign a value to a char variable, you use a character literal, which is always enclosed in apostrophes rather than quotes. Here's an example:

char code =

Here the character X is assigned to the variable named code.

The following statement won't compile:

char code = "X"; // error -- should use apostrophes, not quotes

That's because quotation marks are used to mark strings, not character constants.

Unicode is a two-byte character code that can represent the characters used in most languages throughout the world. Currently, about 35,000 codes in the Unicode character set are defined. That leaves another 29,000 codes unused. The first 256 characters in the Unicode character set are the same as the characters of the ASCII character set, which is the most commonly used character set for computers with Western languages.

  Tip 

For more information about the Unicode character set, see the official Unicode Web site at http://www.unicode.org.

Character literals can also use special escape sequences to represent special characters. Table 2-2 lists the allowable escape sequences. These escape sequences let you create literals for characters that can't otherwise be typed within a character constant.

Table 2-2: Escape Sequences for Character Constants
Open table as spreadsheet

Escape Sequence

Explanation



Backspace

Horizontal tab

Linefeed

f

Form feed

Carriage return

Double quote

'

Single quote

\

Backslash

The boolean type

A boolean type can have one of two values: true or false. Booleans are used to perform logical operations, most commonly to determine whether some condition is true. For example:

boolean enrolled = true;
boolean credited = false;

Here a variable named enrolled of type boolean is declared and initialized to a value of true, and another boolean named credited is declared and initialized to false.

  Warning 

In some languages, such as C or C++, integer values can be treated as booleans, with 0 equal to false and any other value equal to true. Not so in Java. In Java, you can't convert between an integer type and a boolean type.

Wrapper classes

Every primitive type has a corresponding class defined in the Java API class library. This class is sometimes called a wrapper class, because it wraps a primitive value with the object-oriented equivalent of pretty wrapping paper and a bow to make the primitive type look and behave like an object. Table 2-3 lists the wrapper classes for each of the eight primitive types.

Table 2-3: Wrapper Classes for the Primitive Types
Open table as spreadsheet

Primitive Type

Wrapper Class

int

Integer

short

Short

long

Long

byte

Byte

float

Float

double

Double

char

Character

boolean

Boolean

As you find out later in this chapter, you can use these wrapper classes to convert primitive values to strings and vice versa.


Using Reference Types

In Book III, Chapter 1, you're introduced to some of the basic concepts of object-oriented programming. In particular, you see how all Java programs are made up of one or more classes, and how to use classes to create objects. In this section, I show how you can create variables that work with objects created from classes.

To start, a reference type is a type that's based on a class rather than on one of the primitive types that are built in to the Java language. The class can either be a class that's provided as part of the Java API class library or a class that you write yourself. Either way, when you create an object from a class, Java allocates however much memory the object requires to store the object. Then, if you assign the object to a variable, the variable is actually assigned a reference to the object, not the object itself. This reference is the address of the memory location where the object is stored.

For example, suppose you're writing a game program that involves balls, and you create a class named Ball that defines the behavior of a ball. To declare a variable that can refer to a Ball object, you use a statement like this:

Ball b;

Here, the variable b is a variable of type Ball.

To create a new instance of an object from a class, you use the new keyword along with the class name. This second reference to the class name is actually a call to a special routine of the class called a constructor. The constructor is responsible for initializing the new object. For example, here's a statement that declares a variable of type Ball, calls the Ball class constructor to create a new Ball object, and assigns a reference to the Ball object to the variable:

Ball b = new Ball();
  Warning 

One of the key concepts for working with reference types is to remember that a variable of a particular type doesn't actually contain an object of that type. Instead, it contains a reference to an object of the correct type. An important side effect is that two variables can refer to the same object. For example, consider these statements:

Ball b1 = new Ball();
Ball b2 = b1;

Here I've declared two Ball variables, named b1 and b2. But I've only created one Ball object. In the first statement, the Ball object is created, and b1 is assigned a reference to it. Then, in the second statement, the variable b2 is assigned a reference to the same object that's referenced by b1. As a result, both b1 and b2 refer to the same Ball object.

If you use one of these variables to change some aspect of the ball, the change is visible to the ball no matter which variable you use. For example, suppose the Ball class has a method called setSpeed that lets you set the speed of the ball to any int value, and a getSpeed method that returns an integer value that reflects the ball's current speed. Now consider these statements:

b1.setSpeed(50);
b2.setSpeed(100);
int speed = b1.getSpeed();

When these statements complete, is the value of the speed variable 50 or 100? The correct answer is 100. Because both b1 and b2 refer to the same Ball object, changing the speed using b2 affects b1 as well.

This is one of the most confusing aspects of programming with an object-oriented language such as Java, so don't feel bad if you get tripped up from time to time.


Working with Strings

A string is a sequence of text characters, such as the message “Hello, World!” displayed by the HelloApp program illustrated in this chapter and the previous chapter. In Java, strings are an interesting breed. Java doesn't define strings as a primitive type. Instead, strings are a reference type defined by the Java API String class. The Java language does have some built-in features for working with strings. In some cases, these features make strings appear to be primitive types rather than reference types.

Java's string-handling features are advanced enough to merit an entire chapter to explain them. So, for the full scoop on strings, I refer you to Book IV, Chapter 1. The following sections present just the bare essentials of working with strings so you can incorporate simple strings in your programs.

Declaring and initializing strings

Strings are declared and initialized much like primitive types. In fact, the only difference you may notice at first is that the word String is capitalized, unlike the keywords for the primitive types such as int and double. That's because String isn't a keyword. Instead, it's the name of the Java API class that provides for string objects.

The following statements define and initialize a string variable:

String s;
s = "Hello, World!";

Here, a variable named s of type String is declared and initialized with the string literal “Hello, World!” Notice that string literals are enclosed in quotation marks, not apostrophes. Apostrophes are used for character literals, which are different than string literals.

Like any variable declaration, a string declaration can include an initializer. Thus you can declare and initialize a string variable in one statement, like this:

String s = "Hello, World!";
  Tip 

Class variables and instance variables are automatically initialized to empty strings, but local variables aren't. To initialize a local string variable to an empty string, use a statement like this:

String s = "";

Combining strings

Combine two strings by using the plus sign (+) as a concatenation operator. (In Java-speak, combining strings is called concatenation.) For example, the following statement combines the value of two string variables to create a third string:

String hello = "Hello, ";
String world = "World!";
String greeting = hello + world;

The final value of the greeting variable is “Hello, World!”

  Tip 

When Java concatenates strings, it doesn't insert any blank spaces between the strings. Thus, if you want to combine two strings and have a space appear between them, make sure the first string ends with a space or the second string begins with a space. (In the previous example, the first string ends with a space.)

Alternatively, you can concatenate a string literal along with the string variables. For example:

String hello = "Hello";
String world = "World!";
String greeting = hello + ", " + world;

Here the comma and the space that appear between the words Hello and World are inserted as a string literal.

Concatenation is one of the most commonly used string-handling techniques, so you see plenty of examples in this book. In fact, I've already used concatenation once in this chapter; earlier, I showed you a program that included the following line:

System.out.println("The value of i is " + i);

Here the println method of the System.out object prints the string that's created when the literal “The value of i is “ is concatenated with the value of the i variable.

Converting primitives to strings

Because string concatenation lets you combine two or more string values, and primitive types such as int and double are not string types, you might be wondering how the last example in the previous section can work. In other words, how can Java concatenate the string literal “The value of i is “ with the integer value of i in this statement:

System.out.println("The value of i is " + i);

The answer is that Java automatically converts primitive values to string values whenever you use a primitive value in a concatenation.

  Tip 

You can explicitly convert a primitive value to a string by using the toString method of the primitive type's wrapper class. For example, to convert the int variable x to a string, you use this statement:

String s = Integer.toString(x);

In the next chapter, you discover how to use a special class called the NumberFormat class to convert primitive types to strings while applying various types of formatting to the value, such as adding commas, dollar signs, or percentage marks.

Converting strings to primitives

Converting a primitive value to a string value is pretty easy. Going the other way-converting a string value to a primitive-is a little more complex, because it doesn't always work. For example, if a string contains the value 10, you can easily convert it to an integer. But if the string contains thirty-two, you can't.

To convert a string to a primitive type, you use a parse method of the appropriate wrapper class, as listed in Table 2-4. For example, to convert a string value to an integer, you use statements like this:

String s = "10";
int x = Integer.parseInt(s);
Table 2-4: Methods that Convert Strings to Numeric Primitive Types
Open table as spreadsheet

Wrapper

Parse Method

Example Class

Integer

parseInt(String)

int x = Integer. parseInt(“100”);

Short

parseShort(String)

short x = Short. parseShort(“100”);

Long

parseLong(String)

long x = Long. parseLong(“100”);

Byte

parseByte(String)

byte x = Byte. parseByte(“100”);

Float

parseByte(String)

float x = Float. parseFloat(“19.95”);

Double

parseByte(String)

double x = Double. parseDouble(“19.95”);

Character

(none)

 

Boolean

parseBoolean

boolean x = Boolean. parseBoolean

(String)

(“true”);

 

Of course, you have no real reason to do this. However, as you see later in this chapter, you can use the parse methods to convert string values entered by the user to primitive types. That way you can write programs that let the user enter numeric data via the console window.

Note that you don't need a parse method to convert a String to a Character. If you need to do that, you can find out how in Book IV, Chapter 1.


Converting and Casting Numeric Data

From time to time, you need to convert numeric data of one type to another. For example, you might need to convert a double value to an integer, or vice versa. Some conversions can be done automatically. Others are done using a technique called casting. I describe automatic type conversions and casting in the following sections.

Automatic conversions

Java can automatically convert some primitive types to others and do so whenever necessary. Figure 2-1 shows which conversions Java allows. Note that the conversions shown with dotted arrows in the figure may cause some of the value's precision to be lost. For example, an int can be converted to a float, but large int values won't be converted exactly because int values can have more digits than can be represented by the float type.

image from book
Figure 2-1: Numeric type conversions that are done automatically.

Whenever you perform a mathematical operation on two values that aren't of the same type, Java automatically converts one of them to the type of the other. Here are the rules Java follows when doing this conversion:

  • If one of the values is a double, the other value is converted to a double.
  • If neither is a double but one is a float, the other is converted to a float.
  • If neither is a double nor a float but one is a long, the other is converted to a long.
  • If all else fails, both values are converted to int.

Type casting

Casting is similar to conversion, but isn't done automatically. You use casting to perform a conversion that is not shown in Figure 2-1. For example, if you want to convert a double to an int, you must use casting.

  Warning 

When you use casting, you run the risk of losing information. For example, a double can hold larger numbers than an int. In addition, an int can't hold the fractional part of a double. As a result, if you cast a double to an int, you run the risk of losing data or accuracy. For example, 3.1415 becomes 3.

To cast a primitive value from one type to another, you use a cast operator, which is simply the name of a primitive type in parentheses placed before the value you want to cast. For example:

double pi = 3.1314;
int iPi;
iPi = (int) pi;

Note that the fractional part of a double is simply discarded when cast to an integer; it isn't rounded. For example:

double price = 9.99;
int iPrice = (int) price;

Here iPrice is assigned the value 9. If you want to round the double value when you convert it, use the Round method of the Math class as I show you in the next chapter.


Thinking Inside the Box

Beginning with version 1.5, the Java language supports boxing and unboxing. Boxing occurs when Java converts a primitive value to its corresponding wrapped object. And unboxing occurs when Java goes the other way (converts from a wrapped object to the corresponding primitive value). Here's an example:

Integer wrap = 10;
System.out.println(wrap);

int prim = wrap;
System.out.println(prim);

The output of this code is 10 followed by another 10. In the first line, you assign a primitive value 10 to the wrapper object named wrap. Believe it or not, Java does a lot of work to put the little number 10 into a handsome Integer wrapper. In the third line of code, Java turns the big wrapped wrap object back into a primitive 10 (because the variable prim is of type int). Again, Java does some work behind the scenes.

Think of boxing and unboxing as nicknames for "wrapping" and "unwrapping." The bottom line is, Java can wrap and unwrap values automatically. That's very handy.


Understanding Scope

The scope of a variable refers to which parts of a class the variable exists in. In the simplest terms, every variable exists only within the block in which the variable is declared as well as any blocks that are contained within that block. That's why class and instance variables, which are declared in the class body, can be accessed by any methods defined by the class, but local variables defined within a method can be accessed only by the method in which they are defined.

  REMEMBER 

In Java, a block is marked by a matching pair of braces. Java has many different kinds of blocks: class bodies, method bodies, and block statements that belong to statements such as if or for statements. But in each case, a block marks the scope boundaries for the variables declared within it.

The program in Listing 2-1 can help clarify the scope of class and local variables.

Listing 2-1: A Program that Demonstrates Scope for Class and Local Variables

public class ScopeApp
{ → 2
 static int x;

 public static void main(String[] args)
 {
 x = 5;
 System.out.println("main: x = " + x);
 myMethod();
 }

 public static void myMethod()
 {
 int y;
 y = 10; → 16
 if (y == x + 5) → 17
 {
 int z;
 z = 15; → 20
 System.out.println("myMethod: z = " + z);
 } → 22
 System.out.println("myMethod: x = " + x);
 System.out.println("myMethod: y = " + y);
 } → 25
} → 27

The following paragraphs explain the scope of each of the variables used in this class:

2

The variable x is a class variable. Its scope begins in line 2 and ends in line 27. As a result, both the main method and the myMethod method can access it.

16

The variable y is a local variable that's initialized in line 16. As a result, its scope begins in line 16 and ends in line 25, which marks the end of the body of the myMethod method.

17

The variable z is a local variable that's declared and initialized in the statement block that belongs to the if statement in line 17.

22

The scope of variable z begins when the variable is initialized in line 20 and ends when the statement block ends in line 22.

Open table as spreadsheet

  TECHNICAL STAUFF 

Strictly speaking, the scope of a local variable begins when the variable is initialized and ends when the block that contains the variable's declaration ends. In contrast, the scope for a class or instance variable is the entire class in which the variable is declared. That means that you can use a class or instance variable in a method that physically appears before the variable is declared. But you can't use a local variable before it's declared.


Shadowing Variables

A shadowed variable is a variable that would otherwise be accessible, but is temporarily made unavailable because a variable with the same name has been declared in a more immediate scope. That's a mouthful, but the example in Listing 2-2 makes the concept clear. Here a class variable named x is declared. Then, in the main method, a local variable with the same name is declared.

Listing 2-2: A Class that Demonstrates Shadowing

public class ShadowApp
{ → 2
 static int x; → 4
 public static void main(String[] args)
 {
 x = 5; → 8
 System.out.println("x = " + x); → 9
 int x; → 10
 x = 10; → 11
 System.out.println("x = " + x); → 12
 System.out.println("ShadowApp.x = " +
 ShadowApp.x); → 14
 } → 15
} → 17

The following paragraphs explain the scoping issues in this program:

2–4

The class variable x is declared in line 4. Its scope is the entire class body, from line 2 to line 17.

8–9

The class variable x is assigned a value of 5 in line 8. Then this value is printed to the console in line 9.

10

In line 10, a local variable named x is declared. The local variable shadows the class variable x, so any reference to x through the end of this method in line 15 refers to the local variable rather than the class variable.

11

The local variable x is initialized in line 11. At that point, the local variable x comes into scope and remains in scope until the end of the method in line 15.

12

The System.out.println statement in line 12 prints the value of the local variable x. Note that this statement is identical to the statement in line 9, which printed the class variable x because the class variable had not yet been shadowed.

14

While a class variable is shadowed, you can access it by specifying the class name as shown in line 14. Here ShadowApp.x refers to the class variable.

15

When the main method ends in line 15, the class variable x is no longer shadowed.

Open table as spreadsheet

  TECHNICAL STAUFF 

The scope of a local variable that shadows a class variable doesn't necessarily begin at the same point that the local variable's scope begins. The shadowing begins when the local variable is declared, but the local variable's scope doesn't begin until the variable is initialized. If you attempt to access the variable between the declaration and the initialization, the Java compiler displays an error message.

  Warning 

Because shadowing is a common source of errors, I suggest you avoid it as much as possible.


Printing Data with System out

You've already seen several programs that use System.out.println to display output on the console. In the following sections, I officially show you how this method works, along with a related method called just print.

Standard input and output streams

Java applications are designed to work in a terminal I/O environment. Every Java application has at its disposal three I/O streams that are designed for terminal-based input and output, which simply sends or receives data one character at a time. The three streams are

  • Standard input: A stream designed to receive input data. This stream is usually connected to the keyboard at the computer where the program is run. That way, the user can type characters directly into the standard input stream. In the section "Getting Input with the Scanner Class" that appears later in this chapter, you connect this input stream to a class called Scanner, which makes it easy to read primitive data types from the standard input stream.
  • Standard output: A stream designed to display text output on-screen. When you run a Java program under Windows, a special console window is opened, and the standard output stream is connected to it. Then any text you send to standard output is displayed in that window.
  • Standard error: Another stream designed for output. This stream is also connected to the console window. As a result, text written to the standard output stream is often intermixed with text written to the error stream.
  Tip 

Windows and other operating systems allow you to redirect standard output to some other destination-typically a file. When you do that, only the standard output data is redirected. Text written to standard error is still displayed in the console window.

To redirect standard output, you use a greater-than sign on the command that runs the Java class, followed by the name of the file you want to save the standard output text to. Here's an example:

C:Java>java TestApp >output.txt

Here, the standard output created by the class TestApp is saved in a file named output.txt. However, any text sent to the standard error stream still appears in the console window. As a result, the standard error stream is useful for programs that use output redirection to display status messages, error messages, or other information.

All three standard streams are available to every Java program via the fields of the System class, as described in Table 2-5.

Table 2-5: Static Fields of the System Object
Open table as spreadsheet

Field

Description

System.in

Standard input

System.out

Standard output

System.err

Standard error

Using System out and System err

Both System.out and System.err represent instances of a class called PrintWriter, which defines the print and println methods used to write data to the console. You can use both methods with either a String argument or an argument of any primitive data type.

The only difference between the print and the println methods is that the println method adds a line-feed character to the end of the output, so the output from the next call to print or println begins on a new line.

Because it doesn't start a new line, the print method is useful when you want to print two or more items on the same line. Here's an example:

int i = 64;
int j = 23;
System.out.print(i);
System.out.print(" and ");
System.out.println(j);

The console output produced by these lines is

64 and 23

Note that you could do the same thing with a single call to println by using string concatenation, like this:

int i = 64;
int j = 23;
System.out.println(i + " and " + j);


Getting Input with the Scanner Class

Until Java 1.5, getting text input from the user in a console-based Java program wasn't easy. But with Java 1.5, a new class-called Scanner-was introduced to simplify the task of getting input from the user. In the following sections, you use the Scanner class to get simple input values from the user. The techniques that I present here are used in many of the programs shown in the rest of this book.

If you're using an older version of Java, you should still read this section, because many of the programs in this book use the Scanner class. However, you should also read the next section, "Getting Input with the JOptionPane Class," because that section describes a way of getting user input that works with earlier versions of Java.

Throughout the following sections, I refer to the program shown in Listing 2-3. This simple program uses the Scanner class to read an integer value from the user, and then displays the value back to the console to verify that the program received the value entered by the user. Here's a sample of the console window for this program:

Enter an integer: 5
You entered 5.

The program begins by displaying the message Enter an integer: on the first line. Then, it waits for you to enter a number. When you press the Enter key, it displays the confirmation message (You entered 5.) on the second line.

Listing 2-3: A Program that Uses the Scanner Class

import java.util.Scanner; → 1
public class ScannerApp
{

 static Scanner sc = new Scanner(System.in); → 6
 public static void main(String[] args)
 {
 System.out.print("Enter an integer: "); → 10
 int x = sc.nextInt(); → 11
 System.out.println("You entered " + x + "."); → 12
 }

}

Importing the Scanner class

Before you can use the Scanner class in a program, you must import it. To do that, you code an import statement at the beginning of the program, before the class declaration as shown in line 1 of Listing 2-3:

import java.util.Scanner;

Note that java and util are not capitalized, but Scanner is.

  Tip 

If you're using other classes in the java.util package, you can import the entire package by coding the import statement like this:

import java.util.*;

Declaring and creating a Scanner object

Before you can use the Scanner class to read input from the console, you must declare a Scanner variable and create an instance of the Scanner class. I recommend you create the Scanner variable as a class variable, and create the Scanner object in the class variable initializer, as shown in line 6 of Listing 2-3:

static Scanner sc = new Scanner(System.in);

That way, you can use the sc variable in any method in the class.

To create a Scanner object, you use the new keyword followed by a call to the Scanner class constructor. Note that the Scanner class requires a parameter that indicates the input stream that the input comes from. You can use System.in here to specify standard keyboard console input.

Getting input

To read an input value from the user, you can use one of the methods of the Scanner class that are listed in Table 2-6. As you can see, the primitive data type has a separate method.

Table 2-6: Scanner Class Methods that Get Input Values
Open table as spreadsheet

Method

Explanation

boolean nextBoolean()

Reads a boolean value from the user.

byte nextByte()

Reads a byte value from the user.

double nextDouble()

Reads a double value from the user.

float nextFloat()

Reads a float value from the user.

int nextInt()

Reads an int value from the user.

String nextLine()

Reads a String value from the user.

long nextLong()

Reads a long value from the user.

short nextShort()

Reads a short value from the user.

Notice in the first column of the table that each method listing begins with the type of the value that's returned by the method. For example, the nextInt method returns an int value. Also, notice that each of the methods ends with an empty set of parentheses. That means that none of these methods require parameters. If a method requires parameters, the parameters are listed within these parentheses.

Because these methods read a value from the user and return the value, you most often use them in statements that assign the value to a variable. For example, line 11 in Listing 2-3 reads an int and assigns it to a variable named x.

When the nextInt method is executed, the program waits for the user to enter a value in the console window. To let the user know what kind of input the program expects, you should usually call the System.out.print method before you call a Scanner method to get input. For example, line 10 in Listing 2-3 calls System.out.print to display the message Enter an integer: on the console. That way the user knows that the program is waiting for input.

  TECHNICAL STAUFF 

If the user enters a value that can't be converted to the correct type, the program crashes, which means that it abruptly terminates. As the program crashes, it displays a cryptic error message that indicates what caused the failure. For example, if you enter three instead of an actual number, the console window looks something like this:

Enter an integer: three
 Exception in thread "main" java.util.InputMismatchException
 at java.util.Scanner.throwFor(Scanner.java:819)
 at java.util.Scanner.next(Scanner.java:1431)
 at java.util.Scanner.nextInt(Scanner.java:2040)
 at java.util.Scanner.nextInt(Scanner.java:2000)
 at ScannerApp.main(ScannerApp.java:11)

This message indicates that an exception called InputMismatchException has occurred, which means that the program was expecting to see an integer, but got something else instead. In Book II, Chapter 8, you find out how to provide for exceptions like these so that the program can display a friendlier message and give the user another shot at entering a correct value. Until then, you have to put up with the fact that if the user enters incorrect data, your program crashes ungracefully.

  Tip 

You can prevent the nextInt and similar methods from crashing with incorrect input data by using one of the methods listed in Table 2-7 to first test the next input to make sure it's valid. I haven't covered the Java statements you need to perform this test yet. Don't worry; in Book II, Chapter 8, I show you the solution.

Table 2-7: Scanner Class Methods that Check for Valid Input Values
Open table as spreadsheet

Method

Explanation

boolean hasNextBoolean()

Returns true if the next value entered by the user is a valid boolean value.

boolean hasNextByte()

Returns true if the next value entered by the user is a valid byte value.

boolean hasNextDouble()

Returns true if the next value entered by the user is a valid double value.

boolean hasNextFloat()

Returns true if the next value entered by the user is a valid float value.

boolean hasNextInt()

Returns true if the next value entered by the user is a valid int value.

boolean hasNextLong()

Returns true if the next value entered by the user is a valid long value.

boolean hasNextShort()

Returns true if the next value entered by the user is a valid short value.


Getting Input with the JOptionPane Class

If you're using a version of Java prior to Java 1.5, you don't have the luxury of using the Scanner class to read input directly from the user via a console window. However, you can use the JOptionPane class to display simple dialog boxes such as the one shown in Figure 2-2 to get text input from the user. Then you can use the parse methods of the primitive type wrapper classes to convert the text entered by the user to the appropriate primitive type.

image from book
Figure 2-2: A dialog box displayed by the JOptionPane class.

Although the JOptionPane class has many methods, the only one you need to get simple text input is the showInputDialog method. This method uses a single parameter that specifies the prompting message that's displayed in the dialog box. It returns a string value that you can then parse to the proper type.

The JOptionPane class is a part of the javax.swing package, so you need to add an import javax.swing.JOptionPane statement to the beginning of any program that uses this class.

Listing 2-4 shows a simple program that uses the JOPtionPane class to get an integer value and display it on the console.

Listing 2-4: A Program that Uses the JOptionPane Class to Get User Input

import javax.swing.JOptionPane; → 1
public class DialogApp
{
 public static void main(String[] args)
 {
 String s;
 s = JOptionPane.showInputDialog → 7
 ("Enter an integer:"); → 8
 int x = Integer.parseInt(s); → 9
 System.out.println("You entered " + x + "."); → 10
 }
}

The following paragraphs describe the important lines in this program:

1

This line imports the JOptionPane class.

7–8

This statement displays an input dialog box with the prompt Enter an integer: and assigns the string entered by the user to the variable named s.

9

This statement uses the parseInt method of the Integer class to convert the string entered by the user to an integer.

10

This statement displays the integer value to confirm that the data entered by the user was converted properly to an integer.

Open table as spreadsheet

  TECHNICAL STAUFF 

This program terminates abruptly if the user enters anything other than an integer in the input dialog box. For example, if the user enters ten, the program terminates, and a cryptic message indicating that a NumberFormat Exception has occurred is displayed. You can provide for this situation in Book II, Chapter 8. Until then, just be careful to enter correct numbers when you use the JOptionPane class.


Book I - Java Basics

Book II - Programming Basics

Book III - Object-Oriented Programming

Book IV - Strings, Arrays, and Collections

Book V - Programming Techniques

Book VI - Swing

Book VII - Web Programming

Book VIII - Files and Databases

Book IX - Fun and Games



Java All-In-One Desk Reference For Dummies
Java All-In-One Desk Reference For Dummies
ISBN: 0470124512
EAN: 2147483647
Year: 2004
Pages: 332

Flylib.com © 2008-2020.
If you may any questions please contact us: flylib@qtcs.net