Chapter:Variables and types

From Juneday education
Jump to: navigation, search

Meta information about this chapter

Expand using link to the right to see the full content.

Introduction

Variables is a basic building block when developing software in programming languages such as Java and C. In these languages it is important to have a good understanding of what a variable is and how it relates to memory - both as a way to understand how a computer program works and when learning about pointer or references later on.

We need to give the computer a bit of help on how to interpret the variable. We do this by using the type concept, which tells how big the variable is (how much space in memory is used) and how to use the memory for a variable.

It is not enough having variables and types. We, of course, need use them to store values and later on retrieve values. In this lecture we go through how to initialize and assign variables values.

Being able to manage conversion between type, automatic and explicit, are important for a developer. This lecture gives an overview and introduction to type cast.

We've been introduced to types. These have been general so in this chapter we will focus on Java and the primitive types found in Java.

This chapter will be using Java as a basis for the syntax. Students learning C will have to adapt to this naming convention during this chapter since we (the authors) can reuse the material between courses.

Purpose

To give the student a basic understanding of variables, types and type cast. This understanding will be used as a basis for future learning.

Types are used in many languages, to different degrees. Being familiar with the type concept is important regardless of language and this presentation gives the student a foundation for future studies.

Declaring variables is done all over the source code of imperative programs (since the only way to create a variable is to declare it).

Without assignment there would not be much a program written in languages such as C, C++ and Java could do. The concept is relatively easy to understand and use but important enough for a separate lecture.

Primitive types are useful in Java and a good start in understanding types, variables and expressions.

Goal

The goal of this presentation is to motivate and make the student familiar with the variable concept as well as discuss the way we humans use variables in everyday life.

The student shall be able:

  • motivate why variables are needed
  • use variables
  • use and reflect over the type concept
  • convert/cast between different types
  • understand the meaning of an assignment
  • know that the = sign does NOT refer to mathematical equality
  • understand how to use assignments with typed variables
  • use assignment when writing programs
  • be familiar with the type cast concept
  • know the implications of switching between types
  • be able to convert between types
  • know that you can represent whole numbers in Java
  • know that you can represent real numbers in Java
  • be familiar with boolean, int and double and know that there exist other types

Instructions to the teacher

Common problems

Variables are very important to understand. Without this understanding we have found it hard for the students to:

  • to understand functions and their parameter/argument list
  • pointers and reference variables

It's well worth the effort to stress that Java has basically two sorts of types: Primitive types and Reference types. While it is natural to start off with the simpler (to understand and use) primitive types, it should be mentioned already that there are also reference types. One way of understanding the difference at this point could be to think of reference types as indirect types, where the value is always an address or referral to some place in the memory where actual values etc are stored. Primitive types could be said to allow values to be stored more directly "in the variable" and that this is possible because the possible values are so primitive that no special care needs to be taken to prepare the variable's memory space. Stuff that is much more complex than primitive values, need to be stored in a special place, in a special way, and the values etc stored needs to be accessed more indirectly. Therefor reference variables is a way to have variables referring to some address where more complex structures may be found.

In the chapters about objects and classes this fundamental difference, between primitive types and reference types, should be re-iterated.

Chapter videos

All English videos in this chapter

All Swedish videos in this chapter

See below for individual links to the videos.

Variables

Description

A memory (storage location) with a name. If we want to store the current temperature in a program, we can store the value in a place in memory and name (using a programming language) that piece of memory for instance currentTemperature. Having descriptive names of memory locations greatly helps when writing programs. When we want to use the value of the current temperature again in our program, it is easy to remember and understand what currentTemperature stands for.

Note: If you're programming in C you would name the variable current_temperature.

Presentation

Presentation: Variable (pdf)

Videos

Variable (eng) (swe)

Links

Types

Description

A type is a classification to identify different types of data, e.g. integers. Variables in the Java programming language have types, which means that we restrict what values are legal to store in variables of certain types. If we want to store and use integer values in our program, we can use a variable of type int (which stands for integer values) for instance. We will then only be able to store integer values in that variable, which helps us avoid storing something else in the variable by mistake. It can be argued that types help us making fewer mistakes. This is sometimes called type safety.

Presentation

Presentation: Type (pdf)

Videos

Types (eng) (swe)

Links

  • No external links for Types

Declaration

Description

Creating a variable in programming languages is done using a declaration. The declaration specifies a name and, in Java and many other programming languages, also a type. An example can be int currentTemperature; which declares a variable with the name currentTemperature and of the type int. In Java, int is the name of the type for storing integer values in a certain range.

Presentation

Presentation: Declaration (pdf)

Videos

Declaration (eng) (swe)

Links

Wikipedia links for the keen student:

Assignment

Description

With assignments we can set or modify the value of a variable. An example is currentTemperature = 12; which assigns the value 12 to the variable currentTemperature. The assignment is done using the = sign. On the right side of the assignment we can find a literal (e g 12), an expression such as 12*3; or as we will see later on in the course a function/method. When we talk about the = sign, we call it "assignment operator" because its use and meaning is very different from the same character when used in mathematics, for instance.

Note: a literal is a simple form of expression

Presentation

Presentation: Assignment (pdf)

Videos

Assignment (eng) (swe)

Links

Wikipedia links for the keen student:

Type cast

Description

Some types can store similar values but in different ranges. For integer values, there are more than one type, but the valid values for the different types in the integer family (byte (or char in C), short, int, long) vary. A type for storing only a small set of the integers is byte. It can only store integer values between -128 and +127. In return, such variables occupy less space of the memory compared to, for instance, int.

If we want to change the type of a variable (or expression) we can do this explicitly in code by using type cast (or typecast). If we want to assign a byte (char in C) variable, lastTemperature, with the value of a variable of int type currentTemperature and the change the type we can write: lastTemperature = (byte) currentTemperature; When using explicit casts like this, we must be sure that the value will fit inside the target type, or there will be unwanted results. It is always possible to cast from a "smaller type" like byte to a "larger type" like int, because the valid values of a smaller interval always fit in the valid range of the larger type.

There are also rules for casting between more complex types than integers etc, but that's for a later chapter!

Presentation

Presentation: Type-cast (pdf)

Videos

Typecast (eng) (swe)

Variables and types in Java

Description

Primitive types for integer values (whole numbers)

Primitive datatypes are a basic datatype which form a building block in Java. They serve one purpose - store a simple value. They come with a set of predefined operations which you can not extend or change. For instance, the primitive types for integer values are:

  • byte
  • short
  • int
  • long

Operations on expressions with integer types

The operations you can perform on expressions of an integer type are:

  • addition and subtraction (using the operators + and -
    • changing the sign using - - e.g. if you have a variable balance of type int, -balance changes the sign of the value of the expression - see example below.
  • multiplication and division (using the operatos * and /
    • you can get the "remainder" of an integer division using the operator % too, e.g. 4 % 3 is 1, the remainder after dividing the integer 4 with the integer 3 is one.
Example of changing the sign of an integer expression

Here's an example of how to change the sign of a value (of an expression):

    int balance = 10;
    System.out.println(-balance); // will print -10

Primitive types for floating-point values

The Java primitive types for floating-point expressions are:

  • float
  • double

The operations on floating-point expressions are pretty much the same as for integer types. But the result of division where at least one of the operands are of a floating point type, is also of a floating-point type. The division between two integer type operands, is of the type of the largest integer type operand.

  • 1.0 / 4.0 is 0.25 (which is of floating-point type, in this case double)
  • 1 / 4 is 0 (which is of integer type, in this case int)

Primitive type for logical values

The Java primitive type for "Boolean expressions" (expressions with a truth value) is:

  • boolean (note that boolean, like all primitive types, is spelled with a lower case initial letter)

Primitive type for character values

The Java primitive type for a "character" is:

  • char

The type char is special, since it is used to represent characters from the unicode character set, which is very large. It is sometimes required to use two char expressions to represent one single character, but for now, you can think of it as a type for characters. The Western characters like 'a', 'b', 'c' etc, can be represented as one single char value in the Java primitive type char.

Literals - values typed in by hand

It's important to know that a literal integer such as 25 in Java has the type int. If you need a literal value of type long, you must append "L" or "l" (a lower case L) to the literal value, e.g. 55L. For floating point literals, the default type is double. If you need a literal floating point value of type float, you must append F or f to the value, e.g. 3.14F.

To express a literal character, you use single quotes:

    char firstLetter = 'A';

Note that strings of text are not of a primitive type. The type String is a reference type, of which we will talk more later. Literal strings are put inside double quotes:

    String teacherName = "Henrik"; // teacherName is a variable of reference type

The reason we distinguish between primitive types and reference types, is that it helps us think about values in our programs. The primitive types are for storing primitive values of a predetermined range (we know beforehand what the valid values for each type is).

We know what integer values are valid for storing inside a byte variable for instance. That is decided by the size of the type byte. With size, we mean what the smallest and largest valid value for the type is. For the Java type byte, those values are from -128 through 127. For the primitive type boolean, ther are only two valid values; true or false. The size of a boolean expression is thus very small (only two possible values).

The notion of primitive types exists because we can think of e.g. a variable of a primitive type as simply a placeholder for a value in the valid range for the type.

But an expression of type String (a string of characters) doesn't have a set for valid values - it can be empty or a string of a few or insanely many characters (perhaps the characters of a full boring Java text book). So we don't have the notion of the predictable size for a String. It is dynamic and depends. Contrast this with the primitive type boolean which always is simply one of two predefined values (true/false). Also, the operations on the primitive types are predefined and limited. But operations we can perform on a String object are much more complex and sophisticated.

Later in the course, we will see that we can write our own types and supply as many operations on those types as we want.

One last thing, primitive types are also keywords in the Java language. They have a special meaning and can only be used as signifying e.g. the type of a variable, the type of a type conversions or the type of an operation we are writing. They are always printed in only lower case letters.

Primitive types (except for arrays) are always (by convention, not by rule) spelled with an initial capital letter, like String.

What are primitive used for

You will as the course material progresses, learn that Java programming is almost exclusively about using reference types that describe objecs. The reference types are expressed in Java as class declarations, typically describing objects of the class type. Such objects may, but don't have to, have parts and operations (behaviors) of a primitive type.

It is not often we have to deal with primitive type expressions our selves, (except early on in Java courses), since the objects will hide such details from us. We've already mentioned String as a reference type. String is a class describing objects of the reference type String. When they (Sun Microsystems and later on Oracle) wrote the String class, they used the primitive type char to represent the "value" or "content" of a String object. A String can thus be thought of as a descriptions for objects that have as their value a list of char values. But the operations on a String object often result in new Strings (like taking a substring of a String) or of some other type (like asking a string how long it is and getting an int value back).

Types that are not primitive

All types that are not one of the eight primitive types are called reference types. We'll talk more about references and reference types in chapters ahead.

References are for more complex objects than just values.

Videos

  1. Variables and types in Java (eng) (swe) Java types (pdf)

Note: the presentation is unclear on when so called default values are used. Local variables never get default values.


Questions and Answers

We really encourage you to read the questions and answers below.

Q: “OK, so we use variables so that we can use a name instead of some technical hardware address. Are there any rules or recommendations for what kind of names we should use?”
A: We are glad that you asked! In Java, there are some rules and some recommendations. Let’s start at what names are legal to use (the compiler will tell you when you try to violate these rules, but it is good to know the rules anyway). The name you choose for a variable must start with a letter (underscore and $ are legal but nobody uses them as the start of a variable, and you shouldn’t either!). The rest of the variable name should be a combination of letters (numbers are valid too but not as the first letter of the variable name) and you may use underscore.

The recommendation is to start with a lower case letter and if the name consists of several words such as in “number of students” you should start each word with a capital letter to make the name more readable: numberOfStudents. Names should be short, but meaningful. Prefer numberOfStudents to nSt or ns etc. Think that your colleagues should immediately understand the meaning of a variable (and you too should understand it when you read the code after a year or two!).

There is a special form of variables for values that do not change over time, called constants. Constants usually have names with only upper case letters and words separated by underscore such as in UPPER_CASE_LETTER, MAX_VALUE or HTTP_NOT_FOUND.

Q: “Are there some words that are forbidden to use as variable names, even though they obey the lexical rules?”
A: Sure there are! There are words that are reserved as part of the language itself (or future part). There is a whole list of such reserved words here: [1] We have actually seen some of them already but not talked about them in detail. The reserved words you already have seen include: class, import, package, private, public and void. The names of the primitive types are also reserved.

Q: “In Java, where are variables declared?”
A: It’s a little early in the course to give a full answer to that without listing places that we haven’t talked about yet. But so far, we have at least seen a few places where variable names (they are also sometimes called identifiers in some sources - identifiers are names we come up with of variables, classes, methods, arguments etc but we are focusing on variables in this chapter!) are declared. The first variable name we saw was actually the parameter to the main method. The main method had parentheses, remember? And in the parentheses it said String[] args where args is a variable name. That it is called exactly args is just a convention by the way. The next place we saw a variable name being declared was in the main method. We had some Greeter reference variables named hello and hi. So, apart from being parameters, variable names can be declared inside methods. Such variables are called “local variables”. And lastly, we have already seen one more place where a variable was declared. Do you remember where?

Q: “I don’t remember the third place where a variable was declared. Where was that?”
A: The third place we have seen so far, was in the Greeter class declararation! We said that Greeter objects had state - a way to remember and hold data at some point of their lifetime. The Greeter objects had an internal thing called greeting which was a variable holding information on what String to use when asked to greet(). The greeting variable was declared inside the class definittion of the Greeting class in Greeting.java but not inside any method. Variables that every object of a class has their own copy of (to hold a part of their state) are called instance variables (because an object is also called “an instance of a class”).

Q: “What was the list of primitive types?”
A: The primitive types are the following eight types: boolean, byte, short, char, int, long, float, and, double.

Q: “And then there were reference types. Is there a list of them too?”
A: No, there is no list. Reference types are types storing a kind of address to objects of some type. Object types are described in classes (and constructs similar to classes such as Enum and interface and arrays). Primitive types were pretty straightforward - they had a predefined set of legal values, which is why the Java designers didn’t think that they needed normal objects described in classes in order to implement these types. The values (in the legal range for each type) can be thought of as stored directly in the variable. But objects are much more complex creatures! They have state which can be a combination of many values (even references to other objects!) and behaviour (which is expressed in so called methods like greet() ). For this reason, it is hard to implement a reference type that would hold all of this directly in the variable. Numbers and boolean values are much easier to store than complex constructs like objects. Also, objects need to be created before they exist and can be used. So there is a need to allow for reference variables to be declared before they refer to any particular object.

But the main reason we can’t give you a list of reference types, is that much of programming in Java deals with declaring and writing code for classes. When we make a class up, like the authors did when they created the Greeter class, we come up with a name ourselves. So the list of reference types is not fixed! You are going to write your own classes etc later in the course, and each new class is a reference type.

I think it might be good to say something about the naming conventions for reference types here, if you don’t mind! Reference types like classes should always start with a capital letter! This is only a convention and standard, but it really helps when reading some source code. Names (identifiers as some call them) that start with a capital letter signals that these are exactly that, reference types! We directly see that a variable whose type starts with a capital letter (like String) must be a reference type. We don’t have to remember the eight primitive types in order to see this. The capital S in String gives away the information we need, this must be a reference type (such as a class)!

Q: “What is a declaration of a variable and when do I need it?”
A: The declaration of a variable is a very common instruction in Java programs (and programs in many other languages). Java is a language where types are very important and thoroughly checked by the compiler and runtime system. That means that types are important in Java and the reason it is so important to check the types, is that it helps us from doing mistakes (as we humans are so prone to do). If we have a variable that we plan to use to hold some numeric information and we by mistake store a string of text in it, the program will most likely not work the way we planned and hoped. So that kind of behaviour is forbidden in the Java programming language. So, in order for the compiler to help us check things like this, we need to declare what types our variables have - that is what legal values can later be stored in the variables. So when we declare that we want to use a new variable, we also say what type it has and then what name we want to use. If we want a variable capable of storing integral numbers (in the range that matches the legal values in the int primitive type) we could say like this:

 int numberOfLines;

After that declaration statement (statement is just a fancy word for instruction), we are free to use the variable numberOfLines in our program in later statements. The compiler will now help us so we don’t try anything stupid as trying to store text in the variable. Only integers in the range for the int primitive types are now possible to store in numberOfLines.

Inside methods, it is common to start the code by declaring all the variables that will be used in the method. When we declare a class, it is common to start with variables before constructors and methods (but this is also just a convention and not a rule).

Q: “What’s the difference between declaration and initialization?”
A: Declaration is about deciding type and name of a variable before it can be used. Initialization is all about giving the variable its first value. You can do the steps one-by-one like this:

 int numberOfPages;
 numberOfPages = 0;

Or in one statement in one go like this:

 int numberOfPages = 0;

You can choose the version that you find most convenient or intuitive. However, you cannot use a local variable (as a part of an expression, that is: using it as having a value) before it has been assigned a value. Instance variables are a different story, but we’ll talk about them in chapters to come!

Q: “Is it correct that assignment is used when we want to change the value a variable holds? If so, where does the value come from? It seems odd that we already know what values a variable will hold already when we write the program...”
A: It is correct that assignment is used to store a new value in a variable. The values we know beforehand are usually the initial values. Typically, as the program is running, new situations occur and we need to change the state of the program according to external events. Depending on the domain of the program we are writing, a number of sources can be found for the new values. On program might be used to order some product. In order to process the order, the user of the program must indicate in some way what product or products is to be ordered. Depending on the user’s actions (and how we respond to them) the information about the order will probably be stored in some way using variables and assignment. When the customer wants the order to be shipped, the customer might be presented with a form where the customer enters name, address, email, phone number etc. The program would typically use the values entered by the customer and store them in variables using assignment.

Another program might be used to get information about text files. It could, perhaps, count the number of characters, words and lines of any text file the user provides as an argument. Since the number of lines, for instance, is not known beforehand, the program would probably read the file and count how many lines it can find in the file. The count of lines would typically be stored in a variable (perhaps called numberOfLines). The value of the variable would change by being increased by one for every new line the program finds while reading through the file. That could also be accomplished using assignment.

We think it is safe to say that most assignments are results of some operation rather than typed in literally when the program is written. But since we don’t know how to get information from users, or how to read files etch, we show examples using typed in values directly in the source code. Such values are sometimes referred to as “hard coded values”.

Q: “What is the relation between assignments and types?”
A: That is an important but a little tricky to answer question. We’ll try our best! In an assignment there are two parts. The part on the left (maybe we could think of it as the assignee - the variable which is being assigned a value) is always a variable. And all variables have, as we now know, a type. The other part, on the right-hand side, is some kind of value. The value could be typed in (hard coded) or it could be something more complicated like another variable. It could also be the result of some calculations like in

 numberOfChildren = numberOfSons + numberOfDaughters;

There are more things that result in a value which would fit in on the right-hand side but we haven’t learned those yet. The important thing to understand here is that not only variables have a type. In Java, values too have a type! For instance, if you type in an integer such as 7 and use that as a value in, say, an assignment, Java will consider the 7 as being of primitive type int. If you instead type in a real number, say 3.14, that value will be interpreted as being of primitive type double. We have already seen that variables can be used as the right-hand side of an assignment, and we know that variables have a type. Now we have also told you that even hard coded values have a type.

The relation between assignments and types is that we have type security (we get help checking types) in Java. Before we can compile some code containing an assignment, our friend, the compiler, checks the types on both sides of the assignment operator. It starts by looking at the type of the variable to be assigned, and then checks the type of the value on the right-hand side (this sometimes is non-trivial - there are rules for determining the type of a calculation for instance). If the type of the variable to be assigned can hold values of the type of the value on the right-hand side, the compiler will not complain. If, however, the value on the right-hand side is not compatible with the type of the left-hand side variable, we get a compilation error with a message describing the problem.

Q: “What is compatibility then? When is a value of some type compatible with some other type?”
A: First of all, numeric types can only hold numeric values. We can never assign for instance a boolean value to a numeric type in Java. But there are 6 numeric types in Java. Four integer types: byte, short, int, long and two real number types: float, double. Why the need for four integer types, you may ask? The answer has to do with the storage space for the various types. For small values, only a smaller space in the memory is required to represent all valid values. For an integer between -128 and +127, only eight bits are required (a bit is the smallest unit of memory, a space that only can hold a 0 or a 1). The standard integer type int has 32 bits memory space (which allows for really small and really large integer values). Since both byte and int are for integer values, they are compatible at least in one direction. You are always safe to assign a byte value to an int variable and the compiler will always allow this.

Now, if we want to assign a variable of type byte (with only 8 bits space) a value of type int, there might be a problem. It is far from certain that an int value will be inside the allowed range of a byte. For int type values (32 bits) that are unknown at compile time (such as variables) i.e. not hard coded, such values won’t be allowed as the right-hand side of an assignment to a byte (8 bits) or a short (16 bits). If we insist of doing so, we must first convert the value to the corresponding left-hand type of the variable to be assigned.

Q: “How does one convert a type to another type?”
A: This is done using a type-cast. To convert an expression (a value, a calculation, a variable, etc) of type int to type byte, for instance, we write like this:

(byte)intExpression

That is, we put the target type in parentheses before the source type. Now, we must be aware that this is a risky business! To store a value from a huge storage space of 32 bits inside a small space of only 8 bits, there is a huge risk that something will go wrong and information will be lost. The problem is similar to pouring the water from a large glass into a smaller glass. If the large glass only holds a small enough amount of water to fit inside the small glass, everything is fine. But if the large glass is holding much more water than the small glass, pouring all the water into the smaller glass will result in a loss of water (and probably a wet floor).

Links

Further reading

Where to go next

Next page has the exercises for this chapter: Variables and types - Exercises

« PreviousBook TOCNext »