Java Guide : Transient Variables
- Details
- Category: Programming Guides & Tutorials
- Published on Friday, 06 May 2011 11:17
- Written by Prabhu Selvakumar
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. you'll probably use synchronization, rather than the volatile modifier, to make your data thread-safe.
The volatile modifier may also be applied to project managers : )
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.
Things you can mark as static:
- Methods
- Variables
- A class nested within another class, but not within a method
- Initialization blocks
Things you can't mark as static:
Constructors (makes no sense; a constructor is used only to create instances)
- Classes (unless they are nested)
- Interfaces
- Method local inner classes (we'll explore this in Chapter 8)
- Inner class methods and instance variables
- Local variables
Declaring 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, you can iterate through the values of an enum by invoking the values() method on any enum type.
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
- 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. (Behind the scenes, of course, you can imagine that BIG is also passed to the constructor, but we don't have to know—or care—about the details.)
- 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.
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
}
}
Summary
After absorbing the material in this chapter, you should be familiar with some of the nuances of the Java language. You may also be experiencing confusion around why you ever wanted to take this exam in the first place. That's normal at this point. If you hear yourself saying, "What was I thinking?" just lie down until it passes. We would like to tell you that it gets easier…that this was the toughest chapter and it's all downhill from here…
Let's briefly review what you'll need to know for the exam.
There will be many questions dealing with keywords indirectly, so be sure you can identify which are keywords and which aren't. Although naming conventions like the use of camelCase won't be on the exam directly, you will need to understand the basics of JavaBeans naming, which uses camelCase.
You need to understand the rules associated with creating legal identifiers, and the rules associated with source code declarations, including the use of package and import statements.
You now have a good understanding of access control as it relates to classes, methods, and variables. You've looked at how access modifiers (public, protected, and private) define the access control of a class or member. You learned that abstract classes can contain both abstract and nonabstract methods, but that if even a single method is marked abstract, the class must be marked abstract. Don't forget that a concrete (nonabstract) subclass of an abstract class must provide implementations for all the abstract methods of the superclass, but that an abstract class does not have to implement the abstract methods from its superclass. An abstract subclass can "pass the buck" to the first concrete subclass.
We covered interface implementation. Remember that interfaces can extend another interface (even multiple interfaces), and that any class that implements an interface must implement all methods from all the interfaces in the inheritance tree of the interface the class is implementing.
You've also looked at the other modifiers including static, final, abstract, synchronized, and so on. You've learned how some modifiers can never be combined in a declaration, such as mixing abstract with either final or private. Keep in mind that there are no final objects in Java. A reference variable marked final can never be changed, but the object it refers to can be modified.
You've seen that final applied to methods means a subclass can't override them, and when applied to a class, the final class can't be subclassed. Remember that as of Java 5, methods can be declared with a var-arg parameter (which can take from zero to many arguments of the declared type), but that you can have only one var-arg per method, and it must be the method's last parameter. Make sure you're familiar with the relative sizes of the numeric primitives. Remember that while the values of non-final variables can change, a reference variable's type can never change.You also learned that arrays are objects that contain many variables of the same type. Arrays can also contain other arrays. Remember what you've learned about static variables and methods, especially that static members are per-class as opposed to per-instance. Don't forget that a static method can't directly access an instance variable from the class it's in, because it doesn't have an explicit reference to any particular instance of the class. Finally, we covered a feature new to Java 5, enums. An enum is a much safer and more flexible way to implement constants than was possible in earlier versions of Java. Because they are a special kind of class, enums can be declared very simply, or they can be quite complex—including such attributes as methods, variables, constructors, and a special type of inner class called a constant specific class body.
Before you hurl yourself at the practice test, spend some time with the following optimistically named "Two-Minute Drill." Come back to this particular drill often, as you work through this book and especially when you're doing that last-minute cramming. Because—and here's the advice you wished your mother had given you before you left for college—it's not what you know, it's when you know it.
Two-Minute Drill
Remember that in this chapter, when we talk about classes, we're referring to non-inner classes, or top-level classes.
Identifiers
- Identifiers can begin with a letter, an underscore, or a currency character.
- After the first character, identifiers can also include digits.
- Identifiers can be of any length.
- JavaBeans methods must be named using camelCase, and depending on the method's purpose, must start with set, get, is, add, or remove.
Declaration Rules
- A source code file can have only one public class.
- If the source file contains a public class, the filename must match the public class name.
- A file can have only one package statement, but multiple imports.
- The package statement (if any) must be the first (non-comment) line in a source file.
- The import statements (if any) must come after the package and before the class declaration.
- If there is no package statement, import statements must be the first (noncomment) statements in the source file.
- package and import statements apply to all classes in the file.
- A file can have more than one nonpublic class.
- Files with no public classes have no naming restrictions.
Class Access Modifiers
- There are three access modifiers: public, protected, and private.
- There are four access levels: public, protected, default, and private.
- Classes can have only public or default access.
- A class with default access can be seen only by classes within the same package.
- A class with public access can be seen by all classes from all packages.
- Class visibility revolves around whether code in one class can
- Create an instance of another class
- Extend (or subclass), another class
- Access methods and variables of another class
Class Modifiers (Nonaccess)
- Classes can also be modified with final, abstract, or strictfp.
- A class cannot be both final and abstract.
- A final class cannot be subclassed.
- An abstract class cannot be instantiated.
- A single abstract method in a class means the whole class must be abstract.
- An abstract class can have both abstract and nonabstract methods.
- The first concrete class to extend an abstract class must implement all of its abstract methods.
Interface Implementation
- Interfaces are contracts for what a class can do, but they say nothing about the way in which the class must do it.
- Interfaces can be implemented by any class, from any inheritance tree.
- An interface is like a 100-percent abstract class, and is implicitly abstract whether you type the abstract modifier in the declaration or not.
- An interface can have only abstract methods, no concrete methods allowed.
- Interface methods are by default public and abstract—explicit declaration of these modifiers is optional. Interfaces can have constants, which are always implicitly public, static, and final.
- Interface constant declarations of public, static, and final are optional in any combination.
- A legal nonabstract implementing class has the following properties:
- It provides concrete implementations for the interface's methods.
- It must follow all legal override rules for the methods it implements.
- It must not declare any new checked exceptions for an implementation method.
- It must not declare any checked exceptions that are broader than the exceptions declared in the interface method.
- It may declare runtime exceptions on any interface method implementation regardless of the interface declaration.
- It must maintain the exact signature (allowing for covariant returns) and return type of the methods it implements (but does not have to declare the exceptions of the interface).
- A class implementing an interface can itself be abstract.
- An abstract implementing class does not have to implement the interface methods (but the first concrete subclass must).
- A class can extend only one class (no multiple inheritance), but it can implement many interfaces.
- Interfaces can extend one or more other interfaces.
- Interfaces cannot extend a class, or implement a class or interface.
- When taking the exam, verify that interface and class declarations are legal before verifying other code logic.
Member Access Modifiers
- Methods and instance (nonlocal) variables are known as "membrs."
- Members can use all four access levels: public, protected, default, private.
- Member access comes in two forms:
- Code in one class can access a member of another class.
- A subclass can inherit a member of its superclass.
- If a class cannot be accessed, its members cannot be accessed.
- Determine class visibility before determining member visibility.
- public members can be accessed by all other classes, even in other packages.
- If a superclass member is public, the subclass inherits it—regardless of package.
- Members accessed without the dot operator (.) must belong to the same class.
- this. always refers to the currently executing object.
- this.aMethod() is the same as just invoking aMethod().
- private members can be accessed only by code in the same class.
- private members are not visible to subclasses, so private members cannot be inherited.
- Default and protected members differ only when subclasses are involved:
- Default members can be accessed only by classes in the same package.
- protected members can be accessed by other classes in the same package, plus subclasses regardless of package.
- protected = package plus kids (kids meaning subclasses).
- For subclasses outside the package, the protected member can be accessed only through inheritance; a subclass outside the package cannot access a protected member by using a reference to a superclass instance (in other words, inheritance is the only mechanism for a subclass outside the package to access a protected member of its superclass).
- A protected member inherited by a subclass from another package is not accessible to any other class in the subclass package, except for the subclass' own subclasses.
Local Variables
- Local (method, automatic, or stack) variable declarations cannot have access modifiers.
- final is the only modifier available to local variables.
- Local variables don't get default values, so they must be initialized before use.
Other Modifiers—Members
- final methods cannot be overridden in a subclass.
- abstract methods are declared, with a signature, a return type, and an optional throws clause, but are not implemented.
- abstract methods end in a semicolon—no curly braces.
- Three ways to spot a non-abstract method:
- The method is not marked abstract.
- The method has curly braces.
- The method has code between the curly braces.
- The first nonabstract (concrete) class to extend an abstract class must implement all of the abstract class' abstract methods.
- The synchronized modifier applies only to methods and code blocks.
- synchronized methods can have any access control and can also be marked final.
- abstract methods must be implemented by a subclass, so they must be inheritable. For that reason:
- abstract methods cannot be private.
- abstract methods cannot be final.
- The native modifier applies only to methods.
- The strictfp modifier applies only to classes and methods.
Methods with var-args
- As of Java 5, methods can declare a parameter that accepts from zero to many arguments, a so-called var-arg method.
- A var-arg parameter is declared with the syntax type... name; for instance: doStuff(int... x) { }
- A var-arg method can have only one var-arg parameter.
- In methods with normal parameters and a var-arg, the var-arg must come last.
Variable Declarations
- Instance variables can
- Have any access control
- Be marked final or transient
- Instance variables can't be abstract, synchronized, native, or strictfp.
- It is legal to declare a local variable with the same name as an instance variable; this is called "shadowing."
- final variables have the following properties:
- final variables cannot be reinitialized once assigned a value.
- final reference variables cannot refer to a different object once the object has been assigned to the final variable.
- final reference variables must be initialized before the constructor completes.
- There is no such thing as a final object. An object reference marked final does not mean the object itself is immutable.
- The transient modifier applies only to instance variables.
- The volatile modifier applies only to instance variables.
Array Declarations
- Arrays can hold primitives or objects, but the array itself is always an object.
- When you declare an array, the brackets can be to the left or right of the variable name.
- It is never legal to include the size of an array in the declaration.
- An array of objects can hold any object that passes the IS-A (or instanceof) test for the declared type of the array. For example, if Horse extends Animal, then a Horse object can go into an Animal array.
Static Variables and Methods
- They are not tied to any particular instance of a class.
- No classes instances are needed in order to use static members of the class.
- There is only one copy of a static variable / class and all instances share it.
- static methods do not have direct access to non-static members.
Enums
- An enum specifies a list of constant values that can be assigned to a particular type.
- An enum is NOT a String or an int; an enum constant's type is the enum type. For example, WINTER, SPRING, SUMMER, and FALL are of the enum type Season.
- An enum can be declared outside or inside a class, but NOT in a method.
- An enum declared outside a class must NOT be marked static, final, abstract, protected, or private.
- Enums can contain constructors, methods, variables, and constant class bodies.
- enum constants can send arguments to the enum constructor, using the syntax BIG(8), where the int literal 8 is passed to the enum constructor.
- enum constructors can have arguments, and can be overloaded.
- enum constructors can NEVER be invoked directly in code. They are always called automatically when an enum is initialized.
- The semicolon at the end of an enum declaration is optional. These are legal:
enum Foo { ONE, TWO, THREE}
enum Foo { ONE, TWO, THREE};
Transient Variables , Volatile Variables , Static Variables and Methods , Declaring Enums , Declaring Constructors , Methods , and Variables in an enum , Summary , Two-Minute Drill , Java Transient Variables , Java Volatile Variables , Java Static Variables and Methods , Java Declaring Enums , Declaring Constructors , Methods , and Variables in an enum , Java Summary , Java Two-Minute Drill ,blog comments powered by Disqus
More 
