Quantcast

P^i

Your Online Tech Magazine

Tue05212013

Last update04:23:48 AM

Back You are here: Home More Programming and Web Programming Java - Declaring Primitives And Primitive Ranges

Java - Declaring Primitives And Primitive Ranges



 

Declaring Primitives and Primitive Ranges

Java - Declaring Primitives And Primitive RangesPrimitive variables can be declared as class variables (statics), instance variables, method parameters, or local variables. You can declare one or more primitives, of the same primitive type, in a single line. we will discuss the various ways in which they can be initialized later, but for now we'll leave you with a few examples of primitive variable declarations:

byte b;

boolean myBooleanPrimitive;

int x, y, z; // declare three int primitives

On previous versions of the exam you needed to know how to calculate ranges for all the Java primitives. For the current exam, you can skip some of that detail, but it's still important to understand that for the integer types the sequence from small to big is byte, short, int, long, and that doubles are bigger than floats. You will also need to know that the number types (both integer and floatingpoint types) are all signed, and how that affects their ranges. First, let's review the concepts.

All six number types in Java are made up of a certain number of 8-bit bytes, and are signed, meaning they can be negative or positive. The leftmost bit (the most significant digit) is used to represent the sign, where a 1 means negative and 0 means positive, as shown in Figure 1-6. The rest of the bits represent the value, using two's complement notation.

The Sign bit for a byte

Table 1-3 shows the primitive types with their sizes and ranges. Figure 1-6 shows that with a byte, for example, there are 256 possible numbers (or 28). Half of these are negative, and half -1 are positive. The positive range is one less than the negative range because the number zero is stored as a positive binary number. We use the formula -2(bits-1) to calculate the negative range, and we use 2(bits-1)–1 for the positive range.

Ranges of Numeric Primitives

The range for floating-point numbers is complicated to determine, but luckily you don't need to know these for the exam (although you are expected to know that a double holds 64 bits and a float 32). For boolean types there is not a range; a boolean can be only true or false. If someone asks you for the bit depth of a boolean, look them straight in the eye and say, "That's virtual-machine dependent." They'll be impressed.

The char type (a character) contains a single, 16-bit Unicode character. Although the extended ASCII set known as ISO Latin-1 needs only 8 bits (256 different characters), a larger range is needed to represent characters found in languages other than English. Unicode characters are actually represented by unsigned 16-bit integers, which means 216 possible values, ranging from 0 to 65535 (216)-1. You'll learn in later chapter that because a char is really an integer type, it can be assigned to any number type large enough to hold 65535 (which means anything larger than a short. Although both chars and shorts are 16-bit types, remember that a short uses 1 bit to represent the sign, so fewer positive numbers are acceptable in a short).

 


 

Declaring Reference Variables

Reference variables can be declared as static variables, instance variables, method parameters, or local variables. You can declare one or more reference variables, of the same type, in a single line. we'll leave you with a few examples of reference variable declarations:

Object o;

Dog myNewDogReferenceVariable;

String s1, s2, s3; // declare three String vars.

Instance Variables

Instance variables are defined inside the class, but outside of any method, and are only initialized when the class is instantiated. Instance variables are the fields that belong to each unique object. For example, the following code defines fields (instance variables) for the name, title, and manager for employee objects:

class Employee {

// define fields (instance variables) for employee instances

private String name;

private String title,

private String manager;

// other code goes here including access methods for private

// fields

}

The preceding Employee class says that each employee instance will know its own name, title, and manager. In other words, each instance can have its own unique values for those three fields. If you see the term "field," "instance variable," "property," or "attribute," they mean virtually the same thing.

you need to know that instance variables

  • Can use any of the four access levels (which means they can be marked with any of the three access modifiers)
  • Can be marked final
  • Can be marked transient
  • Cannot be marked abstract
  • Cannot be marked synchronized
  • Cannot be marked strictfp
  • Cannot be marked native
  • Cannot be marked static, because then they'd become class variables.

We've already covered the effects of applying access control to instance variables (it works the same way as it does for member methods). A little later in this chapter we'll look at what it means to apply the final or transient modifier to an instance variable. First, though, we'll take a quick look at the difference between instance and local variables. Figure 1-7 compares the way in which modifiers can be applied to methods vs. variables.

Comparison of modifiers on variables vs. methods

Local (Automatic/Stack/Method) Variables

Local variables are variables declared within a method. That means the variable is not just initialized within the method, but also declared within the method. Just as the local variable starts its life inside the method, it's also destroyed when the method has completed. Local variables are always on the stack, not the heap. Although the value of the variable might be passed into, say, another method that then stores the value in an instance variable, the variable itself lives only within the scope of the method. Just don't forget that while the local variable is on the stack, if the variable is an object reference, the object itself will still be created on the heap. There is no such thing as a stack object, only a stack variable. You'll often hear programmers use the phrase, "local object," but what they really mean is, "locally declared reference variable." So if you hear a programmer use that expression, you'll know that he's just too lazy to phrase it in a technically precise way. You can tell him we said that— unless he knows where we live. Local variable declarations can't use most of the modifiers that can be applied to instance variables, such as public (or the other access modifiers), transient, volatile, abstract, or static, but as we saw earlier, local variables can be marked final. Before a local variable can be used, it must be initialized with a value. For instance:


class TestServer {

public void logIn() {

int count = 10;

}

}

Typically, you'll initialize a local variable in the same line in which you declare it, although you might still need to reinitialize it later in the method. The key is to remember that a local variable must be initialized before you try to use it. The compiler will reject any code that tries to use a local variable that hasn't been assigned a value, because—unlike instance variables—local variables don't get default values.

A local variable can't be referenced in any code outside the method in which it's declared. In the preceding code example, it would be impossible to refer to the variable count anywhere else in the class except within the scope of the method logIn(). Again, that's not to say that the value of count can't be passed out of the method to take on a new life. But the variable holding that value, count, can't be accessed once the method is complete, as the following illegal code demonstrates:

class TestServer {

public void logIn() {

int count = 10;

}

public void doSomething(int i) {

count = i; // Won't compile! Can't access count outside

// method login()

}

}

It is possible to declare a local variable with the same name as an instance variable. It's known as shadowing, as the following code demonstrates:

class TestServer {

int count = 9; // Declare an instance variable named count

public void logIn() {

int count = 10; // Declare a local variable named count

System.out.println("local variable count is " + count);

}

public void count() {

System.out.println("instance variable count is " + count);

}

public static void main(String[] args) {

new TestServer().logIn();

new TestServer().count();

}

}

The preceding code produces the following output:

local variable count is 10

instance variable count is 9

Why on earth (or the planet of your choice) would you want to do that? Normally, you won't. But one of the more common reasons is to name a parameter with the same name as the instance variable to which the parameter will be assigned.

The following (wrong) code is trying to set an instance variable's value using a parameter:

class Foo {

int size = 27;

public void setSize(int size) {

size = size; // ??? which size equals which size???

}

}

So you've decided that—for overall readability—you want to give the parameter the same name as the instance variable its value is destined for, but how do you resolve the naming collision? Use the keyword this. The keyword this always, always, always refers to the object currently running. The following code shows this in action:

class Foo {

int size = 27;

public void setSize(int size) {

this.size = size; // this.size means the current object's

// instance variable, size. The size

// on the right is the parameter

}

}

 


 

Array Declarations

In Java, arrays are objects that store multiple variables of the same type, or variables that are all subclasses of the same type. Arrays can hold either primitives or object references, but the array itself will always be an object on the heap, even if the array is declared to hold primitive elements. In other words, there is no such thing as a primitive array, but you can make an array of primitives.

You need to know three things:

  • How to make an array reference variable (declare)
  • How to make an array object (construct)
  • How to populate the array with elements (initialize)

Arrays are efficient, but many times you'll want to use one of the Collection types from java.util (including HashMap, ArrayList, and TreeSet). Collection classes offer more flexible ways to access an object (for insertion, deletion, reading, and so on) and unlike arrays, can expand or contract dynamically as you add or remove elements. There's a Collection type for a wide range of needs. Do you need a fast sort? A group of objects with no duplicates? A way to access a name-value pair? We will cover those details in later part.

Arrays are declared by stating the type of elements the array will hold (an object or a primitive), followed by square brackets to either side of the identifier. Declaring an Array of Primitives

int[] key; // Square brackets before name (recommended)

int key []; // Square brackets after name (legal but less

// readable)

Declaring an Array of Object References

Thread[] threads; // Recommended

Thread threads []; // Legal but less readable

When declaring an array reference, you should always put the array brackets immediately after the declared type, rather than after the identifier (variable name). That way, anyone reading the code can easily tell that, for example, key is a reference to an int array object, and not an int primitive.

We can also declare multidimensional arrays, which are in fact arrays of arrays.This can be done in the following manner:

String[][][] occupantName;

String[] ManagerName [];

The first example is a three-dimensional array (an array of arrays of arrays) and the second is a two-dimensional array. Notice in the second example we have one square bracket before the variable name and one after. This is perfectly legal to the compiler, proving once again that just because it's legal doesn't mean it's right.

It is never legal to include the size of the array in your declaration. Yes, we know you can do that in some other languages, which is why you might see a question or two that include code similar to the following:

int[5] scores;

The preceding code won’t compile. Remember, the JVM doesn’t allocate space until you actually instantiate the array object. That’s when size matters.

Final Variables

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 altered. 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. Figure 1-8 highlights the key points and differences of the various applications of final.

Effect of final on Variables, methods and classess








blog comments powered by Disqus