Home > Declaring, initializing and using variables. > Declaring, initializing and using variables in Java

Declaring, initializing and using variables in Java

 

Module 1: Declaring, initializing and using variables.

  

Objectives

  • Identify the uses for variables and define the syntax for variables.
  • 8 different types of java programming language primitive data types.
  • Declare, initialize, and use variables and constants according to java programming language guidelines and coding standards.
  • Modify variable values using operators.
  • Using promotion and type casting.

 

 

1. Identify the uses for variables and define the syntax for variables.

Variable can be declared in java in 2 different places:

  • In body of a method – in this case, the variable will be local to that method & exist only during the execution of that method.
  • Class definition – in this case, the variable will be declared outside of any method body and such variable are called instance / attribute variables.

 

1. attr var

 

In the above example, we hve 5 attribute / instance variables, since they are declared outside of any method body, but inside the class Shirt. These variables come into existence when the object of the class are created and each object of the class will have its own set of these variables. On the right side of the above figure, there are 3 shirt objects. Each shirt object has its own shirt ID, price, color, description, quantity in stock variables.

These variable declarations can exist anywhere within the class body as long as they are not in any method body. Typically they are put first in the class, before any method declaration. But they can actually come after method declaration, between method declaration or anywhere in class definition as long as they are not in a method body.

  

Variable declaration and intialization:

Attribute / instance variable syntax:

[modifiers] type identifier [=value];

  • [modifiers] -> optional – These are special Java keywords that modify the way the variable functions. ex: public, static etc.
  • type -> required – This specifies the type of information or data held by the variable. ex: int, float etc can be either primitive or can be object reference type.
  • identifier -> required – This is the name that you assign to the variable.
  • [=value] -> optional – This is an initial value that u may want to assign to the variable. It should match with the type of the data that we have specified.

The variable declaration / initialization should end with ‘;’ semi-colon.

  

Describing primitive data data types:

Java is an object-oriented language. Most of the times you will be interacting with objects / creating objects. But we do need some simple data types that act as building blocks for creating objects. In java we have 8 different primitive data types. All the other data types will be objects. Data types are basically representatives of what sort of data will be held in a given entity.

2. difft data types

  

The above table shows 8 different java types. The first 4 (byte, short, int, long) are integer data types. That means they hold whole numbers without any decimal place & they hold varying range of values and take up varying range of memory.

  • byte – it takes up 1 byte of memory or (8*1) bits, and it can hold values from -128 to 127 (2 pow -8 to 2 pow 8-1). This is the smallest.
  • short – it takes up 2 bytes of memory or (8*2) 16 bits, and it can hold values from -32768 to 32767 (2 pow -16 to 2 pow 16-1).
  • int – it takes up to 4 bytes of memory or (8*4) 32 bits, and it can hold values from (2 pow -32 to 2 pow 8-32) in billions. -2 to +2 billion.
  • long – it takes up to 8 bytes of memory or (8*8) 64 bits, and it can hold values from (2 pow -64 to 2 pow 8-64) – very large nos in quintillions. -9 to +9 quintillion.

These were the whole number data types, then we have the decimal point data types & thier value ranges are quite large.

  • float – it takes up 4 bytes of memory or (8*4) 32 bits.
  • double – it takes up 8 bytes of memory or (8*8) 64 bits.

Next data type is the boolean type, it can hold only 2 values,

  • boolean – either false or true.
  • char – Its a character. Its just one signle character. It can hold any of the unicode characters. Unicode is a character set that holds more characters than ASCII character set, which most of us are used to. It holds all the values tht ASCII holds such as letters, numbers, english language & many other internationional languages. It takes up 2 bytes of memory or (8*2) 16 bits.

 

In java, even the literal values in your code are assigned a data type. As you can see in the table, if in your code you have a literalal value 3, then it will be stored as integer type, 3L will be stored as a long type. 3.0f will be stored as a float variable. 3.08 without the f or 3.08D it will be stored as double.

true or false are java special keywords which will be a boolean type value. ‘3’ will be stored as character variable. Beside these literals we hve some special ones, such as if we put 0 infront of a literal, it will make the literal octal. if you put 0x infront of a literal, it will become hexadecimal.

Also in floating literals, we can also use exponential values such as 3.0E2F, this will be equivalent to 3*10 to power 2. Here all the literal values can either use lower or upper case l(L), f(F), d(D), e(E). Also note that there’s no literal value for a byte or short.

  

Naming a variable:

In the previous section, we saw various data types that we can assign to our variables such as byte, short, int & long. But besides assigning a data type to a variable, we must also assign a name to our variable, which will be the identifier for that variable. Here we have the rules and naming conventions for variables.

 

3. java reserved words

 

The rules bullets below must be followed, else the compiler will give you errors. The convention bullets are naming conventions that are most followed by Java programmers but they are not going to be enforced by the compiler i.e., the compiler will not issue error messages if these are not followed.

Rules:

  • Names must start with either upper case or lower case letter, an underscore, or a dollar sign. (ex: Aa_$) – These are the only initial characters that you can use for your variables.
  • After the initial character, you may also use numbers, in addition to the above mentioned characters.
  • No other types of characters are allowed anywhere in the variable name. (ex: ?,#,>, space etc) – The variable must all be one word, but valid seperators such as ‘_’ can be used as mentioned above.
  • Java technology reserved / keywords can not be used as variable names. – These variables are reserved by Java and you can not use them for your variable names.

Conventions:

  • Begin each name with lower case letters. (ex: name) – We might see some exception to these rules, for example while declaring constants.
  • Subsequent words within the name of the variable should be capitalized. (ex: firstName) – If you have multiple words, or want to use multiple words to define a variable meaningfully, this is the convention programmers follow.

  

Assigning a value to a variable:

  There are different ways to declare and assign a value to your variable. Let’s take a look at those ways.

1. Declaring and initializing a variable in one line:

 ex:
double price = 12.99;

Here we have declared a variable called price which is of type double and we have initialized it to 12.99, and all in one line of code.

2. Declaring and initializing several variables in one line:

ex:
double price = 12.99, wholesalePrice = 6.99;

Here you see, that we have our price variable from before and also have a wholsalePrice variable which is also of type double and its being initialized to the value 6.99. Notice the comma (,) that separates the two variables. You may declare and initialize as many variables in one line like this, but you have to ensure that all the variables are of the same data type and they are comma separated, else the compiler will issue an error.

3. Declaring and initializing a variable in different line:

ex:
double price;
price = 12.99;

Here we are declaring a price variable of type double in one line, then we are assigning a value of 12.99 in the next line to it.

4. Additional assignment examples:

ex:
price = 2 * 12.99; //assigning a formula to price variable
price = wholesalePrice; //assigning another variable to price variable
price = calculatePrice(); //assigning a method’s return value to price variable

In the first example, a formula has been assigned to price variable, wherein the formula will be evaluated and its value will be assigned to the price variable. In the second example, value of wholesalePrice variable is assigned to price variable. In the third example, a method’s return value is assigned to price variable. In all the cases, the value thats assigned to the price variable have to be of the same type as price variable, be it the formula or value of another variable or any method’s return value.

  

Constants:

ex:
final double SALEX_TAX = 6.25;

Sometimes we want to create a variable, initialize it, and make sure that the value we have assigned to the variable doesnt change. Such variables are called constants, because the value remains constant, from the time its intialized through the rest of the program. To create a variable that is constant in Java, we use the ‘final’ modifier. Once we have initialized the value of the variable, that value cannot be changed. If we try to change it anywhere in the code, we will get a compiler error.

And there are naming convention for variables used as constants, we put the name in all upper case letters and use underscore (_) to separate the words. This is to signify to other progrmmers that this variable is used as constants and its value cannot be changed.

Rules:

  • Use the final modifier to create a constant.
  • Constant values cannot be changed once initialized.
  • Constant names should all be in upper case letters with the (_) underscore used to separate words.

 

Storing primitives and constants in memory:

Its important to have a basic understanding of where in memory will your variables be allocated. There are 2 areas of memory:

  • Stack memory
  • Heap memory

4. Storing primitives and constants in memory

Stack memory is a short-term memory.  The variables declared inside a method called local variables are short-term variables, and they will be allocated in stack memory.

Heap memory is long-term memoty. The objects that you create in your program will be allocated in heap memory, along with the attribute variables that those objects contain.

 

Using arithmetic operators to modify value:

 Java has many operators. Here we will look at the arithmetic, increment / decrement operators. In subsequent modules we will look into some of the other operators that are available to us in Java.

 Arithmetic Operators:

  5. arithmetic

Java has the traditional arithmetic operators that  you would expect. We have the plus operator (+) which allows us to do addition. We have the minus operator (-) which allows us to do subtraction. We have the asterisk operator (*) which allows us to do multiplication. We have the slash operator (/) which allows us to do division. We have the percent operator (%) which allows us to do modulus operation.

The first four are fairly self-explanatory. But the modulus operator may be new to some. Lets take a look at an example.

ex:
10 % 6 = 4, 10 mod 6.

Here, we take 10 and divide it by 6. By doing so, we get a divisor of 1 and a remainder of 4. We keep the remainder of the division which is 4 and ignore the divisor. Hence the mod / modulo / modulus operator will always be the remainder of the numerals specified in the equation.

Increment / Decrement Operators:

 

6. incr - decr

 

The (++) operator is the increment operator and it adds 1 to the value of the variable.  The (–) operator is the decrement operator and it subtracts 1 from the value of the variable. These operators are shortcut operators. For instance, we use i = i + 1 to add 1 to the value of i, but the increment operator can be used as a shortcut operator to perform the same operation which is i++ instead.

There are 2 versions of each of these increment / decrement operators based on what side we use the (++) or the (–) operator. For instance, if we have ++i, that is the pre – increment version and if we have i++ then its the post – increment version. Same thing applies to the decrement operator. The result is based on which side we use the operators.

For increment operator, we have:

  • Pre – increment
  • Post – increment

For decrement operator, we have:

  • Pre – decrement
  • Post – decrement

Lets take a look at an example.

pre – increment -> it first increments and then does the assignment
ex:
int i = 6;
int j = ++i;
// i = i + 1 , j =  value of i assigned to j after i is incremented.
So, i = 7 and j = 7

post – increment -> works the opposite way,  it first assigns and then does the increment.
ex:
int i = 6;
int j = i++;
// i = i + 1 , j =  value of i assigned to j before i is incremented.
So, i = 7 and j = 6

The same thing happens with the pre – decrement and the post – decrement operators. So, you must be careful on which side you want to use these operators.

 

Operator Precedence:

We discussed about some of the operators available to us in Java. But what happens if we have more than one operator in a single line of Java code. For instance, what if we had 1 + 2 * 3 + 4. Should we go left to right and add 1 + 2 first? or should we go right to left and add 3 + 4 first? or is there some other order we should do?

 

7. operator precedance

 

For now, we are not going to cover all the operators in the above table, as we will cover them in subsequent modules. But this table shows us the precedence which the operators take over one another. For instance from this table we see that multiplication has a higher precedance than addition and subtraction. In our example, we will want to do the multiplication first, and then the addition and not go by left to right or right to left direction.

You are not expected to memorise this precedance, but this is just a reference in case you require it somewhere.

 

Example of need for rules of precedence:

To illustrate why its important to understand operator precedence and also how we can override operation precedence using paranthesis, let’s consider an example equation c = 25 – 5 * 4 / 2 – 10 + 4;  We shall first evaluate it from left to right over the operators, and then evaluate using rules of precedence, and then evaluate by overriding using paranthesis. Let’s first start with evaluating from left to right, which some think can be done so, but is incorrect.

Left to Right Evaluation of expressions:

 8. Example of need for rules of precedance

 

As seen above, by evaluating from left to right, one after the other operator, we end up with a value of 34 which is incorrect. Because this is not how Java evaluates an expression. Java will follow the order of operator precedence. Lets see the operator precedence way which is how Java does it.

Rules of Precedence:

8. a rules of precedence

 

Here you can see, that we have used paranthesis to highlight in the order the operator evaluation will occur. The first thing that will happen is multiplication as it has higher operator precedence than the subtraction or addition. But wait, we also have a division operator in the same line here as the multiplication, which is in the same precedence level. Okay, when you have 2 operators at the same level of operator precedence, then they go left to right. So we will first do the multiplication and then the division, because the multiplication appears to the left than the division in this equation. Now we have an equation narrowed to c = 25 – 10 – 10 + 4;  here again addition and subtraction appear in the same line which have same precedence levels so we will evaluate it from left to right. Finally we end with a result of 9 which is how Java does it.

But what if you dont want to follow this order of precedence? Then, you can override it using paranthesis. Lets see how it can be done.

Overriding using paranthesis:

override using paranthesis

 

In this case, what we would like to have happened is, to do the 25 – 5 first, and then multiply it by 4, then divide it by the result (2-10), and then finally add 4 to it. When you use paranthesis, things that you have inside the parathesis are evaluated first than any operator outside the paranthesis. In this case we have 25 – 5 to give us 20, then we multiply that by 4 to give us 80, then before we do the division, we evaluate 2-10 as it is inside the paranthesis which gives us -8, and then we divide 80/-8 because those are again in a set of paranthesis which gives us -10, and then we add 4 to it which gives us a result of -6.

Yu saw that we had 3 different answers depending on how we have done it. The left to right is completely wrong. The rules of precedence is the correct way of doing it and the way Java evaluates an expression. And then, if you wish you can override the operator precedence using the paranthesis.

 

Using promotion and type – casting:

Suppose we  have a value and variable of one type and we would like to copy that value into a variable of another type. Sometimes, this type of conversion can be done automatically for us and sometimes it cannot. Here we have an example where the conversion cannot be done automatically by the compiler so we get an error message when we compile this code.  

Using promotion and type - casting

 

In the above example, we have an integer type num1 with a value of 53, and another integer type  num2 with a value of 47, we want to add these integers and assign to a byte variable called num3 and expect a value of 100 to be stored in it. But no, this wont be the result but instead the compiler will cause an error in the line where we assign an integer value to a variable of type byte.

We have discussed this before in primitive datatype section, the byte variable can hold a value from -128 to +127. Here we are trying to store a value of 100 into a byte variable called num3. Its value is okay for the byte data type but yet there is a problem. At compile time all the compiler knows is that we are trying to assign an integer into a byte variable. Now, the integers have a value range of -2 billion to +2 billion approximately. 

At compile time, the compiler doesnt know what value will be calculated here. It just knows that here is a possibility where the value can be very small or very large, much smaller or much larger than what a byte datatype can hold. So the compiler is going to give us an error. Its going to give an error saying ‘possible loss of precision’ because it doesnt know whether this is going to result in an error or not at runtime. Its warning us. This is an instance where the compiler cannot do the conversion automatically for us and where we will have to do what is called as ‘casting’. If the compiler could do the conversion automatically, its called promotion.

 

Promotion:

Sometimes the compiler is able to do the conversion for us, from one datatype to another. This is called promotion. This happens when we are going from a type that has a smaller range of values to a type that has larger range of values.

 

promotion

 

Here in the above figure, we see that the automatic conversions that the compiler can do for us. For instance, a byte can be automatically converted to a short. A short can be automatically converted into an integer. A char can also be converted into int automatically. Int can be converted to long, long into float and float into double.

Its not just that a byte can be converted into short, or short to an int, but also byte can go into an int, a byte could also go into a long or double as long as you are moving from lower in the chart to one thats higher in the chart as indicated by the arrows. For all these, the conversion will be done automatically. We can see this in an example beside, we have an integer variable x with a value of 5 being assigned to a long variable y.

Now one conversion that can throw you to some debate is a char into an int. You can say, hey char is a character, and how can a character be converted into an integer? Well, internally characters are just numbers and those numbers have a look-up into a character table which says what character to print for that number. So thats how you can convert char into an int.

Now, also someone might say that character data type is 2 bytes and the short data type is 2 bytes, then why cant there be a conversion from char to short or from short to char since they are of the same size?  well, if you had thought so thats a good question. What you should note is that very first bit in byte, short, int, float, long and double is the sign bit. It indicates the + or – of the datatype. The char datatype doesnt have a sign bit. So its range of values is from 0 to approx 65,000 whereas the short datatype goes from -32,000 to +32,000. Thats why, even though they occupy same amount of memory, the range of values they hold differ, so conversion between each other cannot be done automatically.

 

Type Casting:

What do we do if we want to convert from a larger datatype to a smaller datatype? For instance from long down to an int. Well, we need to use casting. Lets consider the same example as before where we got a compiler error stating ‘possible loss of precision error’.

 

type casting 

Recollecting the example, we wanted to assign integer sum of num1 and num2 to a byte variable num3. We have already talked about why this is not possible automatically. Lets see how we can use casting to do it. With casting, we are basically going to override the compiler’s warning. We tell the compiler to go ahead and convert into a desired datatype and by doing so we accept that there might be possibility of an error or possible loss of precision. Thats why we have to do this carefully. Here in this example we know that the number is going to add upto 100 which is in an acceptable range for a byte, so we are going to go ahead and cast this integer into a byte.

The way you do it as you can see in the syntax is to use paranthesis. And inside the paranthesis, you put the datatype you want the value to be converted to, and you put it infront of the value evaluation expression. Here we have to make sure that we do the addition first thats num1 + num2, thats why those are in paranthesis. That gives an integer, and then we are going to cast that integer into a byte by using the cast. Now this will override the compiler’s warning to us and we must accept the consequence of our actions here.  If you are not ensuring the range of datatype before casting, then you will be getting weird results.

 

Type casting example:

Now lets take a look at another example of casting to see what can go wrong and why you have to make sure to be very careful when you cast from one datatype to another.  

 type casting example

 

Here in the example, we have a variable called myInt of type integer and another variable called myLong of type long. We are setting the value of the long variable to a value thats outside the range of the integers. And then as we see in line 3, we are casting the myLong variable to myInt variable using casting. So we are overriding the compiler’s protection and telling the compiler to do the conversion anyway. As you can see below when we cast the long value to the integer value, it gets garbled and becomes a negative number. What has happened is a part of long data gets tossed away during the conversion, and that causes the integer value to be all garbled. Thats why you have to be absolutely sure that when you make a cast from a larger datatype to a smaller datatype, the value you are casting from is appropriate to the variable you are casting into.

 

Compiler assumptions for integral and floating datatypes:

Lets take a look at other example where casting might be necessary in 2 different scenarios.  

  • Arithmetic -> While performing arithmetic operations.
  • Assignment -> While performing assignment operations.

Arithmetic:

 Compiler assumptions for integral and floating datatypes

 

In the top left window, we have 3 variables a, b, and c all of type short. We are setting a = 1 and b = 2 and then we are setting c = a + b. This will result in a compiler error of ‘possible loss of precision’. Now why is that? The reason is when Java does math, the lowest type of math that it can do is integer math. So even though it is adding 2 shorts together, it will convert them into integers, and then add them together to get an integer result. And as we know from before, that we cannot take an integer value and put it into a short variable unless you cast it. What you need to know is in Java while performing any of the arithmetic operation is that, whenever you are adding either byte with a byte or a byte with a short or a short with a short, you will get an integer result.

And yes, if you add integers you get integer result but if you add an integer and a long, you get long as a result. And if one of the operand in your expression is a float value, then you will get a float result.  And if one of the operand in your expression is a double value, then you will get a double result. So the smallest result you will get in addition is an integer but you may get a long, a float or a double depending on what is being added together. Thats why you have to be careful of what are the datatypes that you will be adding, what the result will be, and what is the datatype that this value is going to be stored into.

So what can we do in this scenario? Well, we have 2 options. One we can see in the top right window, here we declare the variable c of type integer. This will solve our problem as adding both the shorts will result in an integer and we have an integer to store that value into. This is perfectly fine. The other option is in the bottom of the screen, here we add a + b together, and we get an integer, and we cast the result to a short and store the casted short value into the c variable. Now you have to remember, that if you do this you have to make sure that the result of the a + b addition is in the valid range for shorts.

Assignment:

 compiler assumption

This is another area where we might run into trouble.  Here we are trying to store a value of 27.9 into a variable of type float called float1, but this is going to give us a compiler error as well. It will again be the ‘possible loss of precision error’. Why is that? Well, the 27.9 literal is interpreted by Java as being a double and a double cant be stored in a float unless you cast it. So you have 2 options, you either put an ‘F’ at the end of 27.9 to change the default literal double to literal float or you cast the double into a float. That is why we had a briefer in the primitive type section about what literal values will be interpreted as in Java.

But if that is the case, then why doesnt it apply to the previous example of shorts, isnt 1 and 2 an integer, and how did the compiler allow to assign it to a short then? Well, its a right question. Lets try to put some more clarity to the literal values here. When we discussed about the literal values in Java, we did encounter literal values for byte till double and from char to boolean. Certain literal values have an identifier of what datatype they belong to, such as a float with a ‘F’, long with a ‘L’, double with a ‘D’ and so on. But a byte or a short do not have any identifier as such. Yes 1 and 2 are integers, or any such whole number and the compiler automatically converts the integer to a byte or short based on the assignment as there is no specific identifier for a byte or a short. And again you have to make sure that the literal is in the valid range for the shorts or the bytes or you will get a compiler error.

 

Person Example:

In the previous example, we saw that during an addition operation the lowest result you could get is an integer result. And that if you had a long, float or a double as one of the operand you would get a long or a float or a double depending on what the highest operand was. That happens not only with addition but multiplication, subtraction and division and any of the mathematical operations. It isnt just enough that you are aware of the final results of your equation, you must also be aware of any intermediate results and the possible range of intermediate values as your result is being calculated. This can lead to some tricky problems. Here we are going to illustrate this in an example:

Example 1:

 

 a. person example

 

Here we have 2 calculations. One that calculates number of days old a person is, and the other one that calculates the number of seconds old a person is. The first one takes a person’s age in years and multiplies it by 365 and calculates an integer to get the number of days old a person is. The second one takes a person’s age in years, times 365, times 24 as a long value, times 60, times 60. Now here the 24 long value is important. By inserting this 24L in this equation instead of just 24, we are causing the intermediate result of this equation to be a long result.

If 24 didn’t have an L with it, then it would be an integer, and the intermediate result that would be calculated would be an integer. And its possible, that the number of seconds old a person is, depending on thier age could be greater than 2 billion which would put it outside the range of integers, and we would get a garbled answer. It isn’t just enoough that we are taking an integer value and assigning to a long value, you must also make sure that the intermediate calculation is also a long to make room to hold any intermediate values. With this example, you can see that a person is 11,680 days old and 1,00,91,52,000 seconds old.  To better understand about how the calculation is getting garbled we will take a look at other example. Lets take a look at example 2:

Example 2:

 

14. b. person example

person example

 

Now in this example, we have increased the person’s age to 70 years and taken off the L with the 24 thus causing the intermediate result to be integer result. And then, we are assigning this integer result to a long variable. But you should understand here that it doesnt matter that we are assigning an integer result to a long variable, as the damage has already been done before the assignment during the calculation. If you calculate the person’s age in seconds calculation, the number will result to > 2 billion. As implicitly the compiler treats all the whole numbers as integers, the value is large enough for the compiler to hold it in an integer intermediary result and hence we will end up with a garbled final answer.  As you can see in the output window, we get an output of – 2 billion which is obviously wrong. So, you always have to be careful not only about the final result for assignment but also about the intermediary result during the calculation.

 

 

Note:

 

Source: Sun Microsystems Educational Services Course – Beginning to Program with the Java Programming Language WJ-1102A.

 

 

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: