Variable Declaration -Part2
Variable Declaration
Declaring a variable with the final keyword makes it impossible to reinitialize that
variable once it has been initialized with an explicit value (notice we said explicit
rather than default). For primitives, this means that once the variable is assigned a
value, the value can't be changed. For example, if you assign 10 to the int variable
x, then x is going to stay 10, forever. So that's straightforward for primitives, but
what does it mean to have a final object reference variable? A reference variable
marked final can't ever be reassigned to refer to a different object. The data within
the object can be modified, but the reference variable cannot be changed. In other
words, a final reference still allows you to modify the state of the object it refers
to, but you can't modify the reference variable to make it refer to a different object.
Burn this in: there are no final objects, only final references.
We've now covered how the final modifier can be applied to classes, methods,
and variables.
Transient Variables
If you mark an instance variable as transient, you're telling the JVM to skip
(ignore) this variable when you attempt to serialize the object containing it.
Serialization is one of the coolest features of Java; it lets you save (sometimes called
"flatten") an object by writing its state (in other words, the value of its instance
variables) to a special type of I/O stream. With serialization you can save an object
to a file, or even ship it over a wire for reinflating (deserializing) at the other end, in
another JVM.
Volatile Variables
The volatile modifier tells the JVM that a thread accessing the variable must
always reconcile its own private copy of the variable with the master copy in
memory. Say what? Don't worry about it. For the exam, all you need to know about
volatile is that, as with transient, it can be applied only to instance variables.
Make no mistake, the idea of multiple threads accessing an instance variable is scary
stuff, and very important for any Java programmer to understand.
Static Variables and Methods
The static modifier is used to create variables and methods that will exist
independently of any instances created for the class. In other words, static
members exist before you ever make a new instance of a class, and there will be
only one copy of the static member regardless of the number of instances of that
class. In other words, all instances of a given class share the same value for any given
static variable. We'll cover static members in great detail in the next chapter.
Things you can mark as static:
1 Methods
2 Variables
3 A class nested within another class, but not within a method
4 Initialization blocks
Things you can't mark as static:
1 Constructors (makes no sense; a constructor is used only to create instances)
2 Classes (unless they are nested)
3 Interfaces
4 Method local inner classes (we'll explore this in Chapter 8)
5 Inner class methods and instance variables
6 Local variables
Declaring Enums
As of 5.0, Java lets you restrict a variable to having one of only a few pre-defined
values—in other words, one value from an enumerated list. (The items in the
enumerated list are called, surprisingly, enums.)
Using enums can help reduce the bugs in your code. For instance, in your coffee
shop application you might want to restrict your size selections to BIG, HUGE,
and OVERWHELMING. If you let an order for a LARGE or a GRANDE slip in, it
might cause an error. Enums to the rescue. With the following simple declaration,
you can guarantee that the compiler will stop you from assigning anything to a
CoffeeSize except BIG, HUGE, or OVERWHELMING:
enum CoffeeSize { BIG, HUGE, OVERWHELMING };
From then on, the only way to get a CoffeeSize will be with a statement something
like this:
CoffeeSize cs = CoffeeSize.BIG;
It's not required that enum constants be in all caps, but borrowing from the Sun
code convention that constants are named in caps, it's a good idea.
The basic components of an enum are its constants (i.e., BIG, HUGE, and
OVERWHELMING), although in a minute you'll see that there can be a lot more
to an enum. Enums can be declared as their own separate class, or as a class member,
however they must not be declared within a method!
Declaring an enum outside a class:
enum CoffeeSize { BIG, HUGE, OVERWHELMING } // this cannot be
// private or protected
class Coffee {
CoffeeSize size;
}
public class CoffeeTest1 {
public static void main(String[] args) {
Coffee drink = new Coffee();
drink.size = CoffeeSize.BIG; // enum outside class
}
}
The preceding code can be part of a single file. (Remember, the file must be named
CoffeeTest1.java because that's the name of the public class in the file.) The
key point to remember is that the enum can be declared with only the public or
default modifier, just like a non-inner class. Here's an example of declaring an enum
inside a class:
class Coffee2 {
enum CoffeeSize {BIG, HUGE, OVERWHELMING }
CoffeeSize size;
}
public class CoffeeTest2 {
public static void main(String[] args) {
Coffee2 drink = new Coffee2();
drink.size = Coffee2.CoffeeSize.BIG; // enclosing class
// name required
}
}
The key points to take away from these examples are that enums can be declared
as their own class, or enclosed in another class, and that the syntax for accessing
an enum's members depends on where the enum was declared.
The following is NOT legal:
public class CoffeeTest1 {
public static void main(String[] args) {
enum CoffeeSize { BIG, HUGE, OVERWHELMING } // WRONG! Cannot
// declare enums
// in methods
Coffee drink = new Coffee();
drink.size = CoffeeSize.BIG;
}
}
To make it more confusing for you, the Java language designers made it optional to
put a semicolon at the end of the enum declaration:
public class CoffeeTest1 {
enum CoffeeSize { BIG, HUGE, OVERWHELMING }; // <--semicolon
// is optional here
public static void main(String[] args) {
Coffee drink = new Coffee();
drink.size = CoffeeSize.BIG;
}
}
So what gets created when you make an enum? The most important thing to
remember is that enums are not Strings or ints! Each of the enumerated CoffeeSize
types are actually instances of CoffeeSize. In other words, BIG is of type CoffeeSize.
Think of an enum as a kind of class, that looks something (but not exactly) like this:
// conceptual example of how you can think
// about enums
class CoffeeSize {
public static final CoffeeSize BIG =
new CoffeeSize("BIG", 0);
public static final CoffeeSize HUGE =
new CoffeeSize("HUGE", 1);
public static final CoffeeSize OVERWHELMING =
new CoffeeSize("OVERWHELMING", 2);
public CoffeeSize(String enumName, int index) {
// stuff here
}
public static void main(String[] args) {
System.out.println(CoffeeSize.BIG);
}
}
Notice how each of the enumerated values, BIG, HUGE, and OVERWHELMING,
are instances of type CoffeeSize. They're represented as static and final, which in
the Java world, is thought of as a constant. Also notice that each enum value knows
its index or position…in other words, the order in which enum values are declared
matters. You can think of the CoffeeSize enums as existing in an array of type
CoffeeSize, and as you'll see in a later chapter, you can iterate through the values of
an enum by invoking the values() method on any enum type. (Don't worry about
that in this chapter.)
Declaring Constructors, Methods, and Variables in an enum
Because an enum really is a special kind of class, you can do more than just list the
enumerated constant values. You can add constructors, instance variables, methods,
and something really strange known as a constant specific class body. To understand
why you might need more in your enum, think about this scenario: imagine you
want to know the actual size, in ounces, that map to each of the three CoffeeSize
constants. For example, you want to know that BIG is 8 ounces, HUGE is 10
ounces, and OVERWHELMING is a whopping 16 ounces.
You could make some kind of a lookup table, using some other data structure,
but that would be a poor design and hard to maintain. The simplest way is to treat
your enum values (BIG, HUGE, and OVERWHELMING), as objects that can each
have their own instance variables. Then you can assign those values at the time the
enums are initialized, by passing a value to the enum constructor. This takes a little
explaining, but first look at the following code:
enum CoffeeSize {
BIG(8), HUGE(10), OVERWHELMING(16);
// the arguments after the enum value are "passed"
// as values to the constructor
CoffeeSize(int ounces) {
this.ounces = ounces; // assign the value to
// an instance variable
}
private int ounces; // an instance variable each enum
// value has
public int getOunces() {
return ounces;
}
}
class Coffee {
CoffeeSize size; // each instance of Coffee has-a
// CoffeeSize enum
public static void main(String[] args) {
Coffee drink1 = new Coffee();
drink1.size = CoffeeSize.BIG;
Coffee drink2 = new Coffee();
drink2.size = CoffeeSize.OVERWHELMING;
System.out.println(drink1.size.getOunces()); // prints 8
System.out.println(drink2.size.getOunces()); // prints 16
}
}
The key points to remember about enum constructors are
1 You can NEVER invoke an enum constructor directly. The enum constructor
is invoked automatically, with the arguments you define after the constant
value. For example, BIG(8) invokes the CoffeeSize constructor that takes
an int, passing the int literal 8 to the constructor.
2 You can define more than one argument to the constructor, and you can
overload the enum constructors, just as you can overload a normal class
constructor.
To initialize a CoffeeType with both the number of ounces and, say, a lid type,
you'd pass two arguments to the constructor as BIG(8, "A"), which means
you have a constructor in CoffeeSize that takes both an int and a String.
And finally, you can define something really strange in an enum that looks like an
anonymous inner class. It's known as a constant
specific class body, and you use it when you need a particular constant to override a
method defined in the enum.
Imagine this scenario: you want enums to have two methods—one for ounces
and one for lid code (a String). Now imagine that most coffee sizes use the same
lid code, "B", but the OVERWHELMING size uses type "A". You can define a
getLidCode() method in the CoffeeSize enum that returns "B", but then you need
a way to override it for OVERWHELMING. You don't want to do some hard-tomaintain
if/then code in the getLidCode() method, so the best approach might
be to somehow have the OVERWHELMING constant override the getLidCode()
method.
This looks strange, but you need to understand the basic declaration rules:
enum CoffeeSize {
BIG(8),
HUGE(10),
OVERWHELMING(16) { // start a code block that defines
// the "body" for this constant
public String getLidCode() { // override the method
// defined in CoffeeSize
return "A";
}
}; // <-- the semicolon is REQUIRED when you have a body
CoffeeSize(int ounces) {
this.ounces = ounces;
}
private int ounces;
public int getOunces() {
return ounces;
}
public String getLidCode() { // this method is overridden
// by the OVERWHELMING constant
return "B"; // the default value we want to return for
// CoffeeSize constants
}
}













JDBC probides a database programming API.Since ODBC API is written in C language and makes use of Clanguage constructs that Java does not support,a Java program cannot directly communicate with an ODBC driver.


















