Android Programming for Beginners
上QQ阅读APP看书,第一时间看更新

Storing and using data with variables

We can think of a variable as a named storage box. We choose a name, perhaps variableA. These names are kind of like our programmer's window into the memory of the user's Android device.

Variables are values in memory ready to be used or altered when necessary by using the appropriate name.

Computer memory has a highly complex system of addressing, which fortunately we do not need to interact with. Java variables allow us to devise our own convenient names for all the data we need our program to work with. The DVM will handle all the technicalities of interacting with the operating system, and the operating system will, in turn, interact with the physical memory.

So, we can think of our Android device's memory as a huge warehouse just waiting for us to add our variables. When we assign names to our variables, they are stored in the warehouse, ready for when we need them. When we use our variable's name, the device knows exactly what we are referring to. We can then tell it to do things such as: get variableA and add it to variableC, delete variableB, and so on.

In a typical app, we might have a variable named unreadMessages, perhaps to hold the number of unread messages the user has. We could add to it when a new message arrives, take away from it when the user reads a message, and show it to the user somewhere in the app layout, so they know how many unread messages they have.

Some situations that might arise are:

  • User gets three new messages so add three to the value of unreadMessages.
  • User logs into app so use Toast to display a message along with the value stored in unreadMessages.
  • User sees that a bunch of the messages are from someone she doesn't like and deletes six messages. We could then subtract six from unreadMessages.

These are fairly arbitrary examples of names for variables and as long as you don't use any of the characters or keywords that Java restricts, you can actually call your variables whatever you like.

In practice, however, it is best to adopt a naming convention so that your variable names will be consistent. In this book, we will use a loose convention of variable names starting with a lowercase letter. When there is more than one word in the variable's name, the second word will begin with an uppercase letter. This is called camel casing.

Something like:

  • unreadMessages
  • contactName
  • isFriend

Before we look at some real Java code with some variables, we need to first look at the types of variables we can create and use.

Types of variables

It is not hard to imagine that even a simple app will probably have quite a few variables. In the previous section, we introduced the unreadMessages variable as a hypothetical example. What if the app has a list of contacts and needs to remember each of their names? We might then need variables for each contact.

And what about when an app needs to know whether a contact is also a friend, or just a regular contact? We might need code that tests for friend status and then adds messages from that contact into an appropriate folder so the user knows whether they were messages from a friend or not.

Another common requirement in a computer program, including Android apps, is the right or wrong calculation. Computer programs represent right or wrong calculations using true or false.

To cover these and many other types of data you might want to store or manipulate, Java has types.

Primitive types

There are many types of variables and we can even invent our own types as well. But for now, we will look at the most used built-in Java types. And to be fair, they cover just about every situation we are likely to run into for a while. These examples are the best way to explain types.

We have already discussed the hypothetical unreadMessages variable. This variable is of course a number, so we have to tell the Java compiler this by giving it an appropriate type. The hypothetical contactName will of course hold the characters that make up the contact name. Jumping ahead a couple of paragraphs, the type that holds a regular number is called int and the type that holds name-like data is called String. And if we try to store a contact name, perhaps "Ada Lovelace" in an int like unreadMessages, meant for numbers, we will certainly run into trouble, as we can see from the next screenshot:

As we can see, Java was designed to make it impossible for such errors to make it into a running program. With the compiler protecting us from ourselves, what could possibly go wrong?

Here are the main types in Java, then we will see how to start using them:

  • int: The int type is for storing integers, whole numbers. This type uses 32 pieces (bits) of memory and can therefore store values with a magnitude a little in excess of two billion, including negative values too.
  • long: As the name hints at, long data types can be used when even larger numbers are required. A long type uses 64 bits of memory and 2 to the power of 63 is what we can store in this. If you want to see what that looks like, here it is: 9,223,372,036,854,775,807. Perhaps, surprisingly, there are uses for long variables but the point is, if a smaller variable will do, we should use it because our program will use less memory.

    Note

    You might be wondering when you might use numbers of this magnitude. The obvious examples would be math or science applications that do complex calculations, but another use might be for timing. When you time how long something takes, the Java Date class uses the number of milliseconds since January 1, 1970. A millisecond is one thousandth of a second, so there have been quite a few of them since 1970.

  • float: This is for floating point numbers. That is, numbers where there is precision beyond the decimal point. As the fractional part of a number takes memory space just as the whole number portion, the range of a number possible in a float is therefore decreased compared to non-floating point numbers. So, unless our variable will definitely use the extra precision, float would not be our data type of choice.
  • double: When the precision in float is not enough we have double.
  • boolean: We will be using plenty of Booleans throughout the book. The boolean variable type can be either true or false; nothing else. Perhaps Booleans answer questions such as:
    • Is the contact a friend?
    • Are there any new messages?
    • Are two examples for Boolean enough?
  • char: A single alphanumeric character is stored in char. It's not going to change the world on its own but could be useful if we put lots of them together.

    Tip

    I have kept this discussion of data types to a practical level that is useful in the context of this book. If you are interested in how a data type's value is stored and why the limits are what they are, then have a look on the Oracle Java tutorials site here: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html. Note that you do not need any more information than we have already discussed to continue with this book.

As we just learned, each type of data that we might want to store will require a specific amount of memory; so we must let the Java compiler know the type of the variable before we begin to use it.

The previous variables are known as the primitive types. They use predefined amounts of memory and so, using our warehouse storage analogy, fit into predefined sizes of storage box.

As the "primitive" label suggests, they are not as sophisticated as reference types.

Reference types

You might have noticed that we didn't cover the String variable type that we previously used to introduce the concept of variables that hold alphanumeric data such as a contact's name.

Strings are one of a special type of variable known as a reference type. They quite simply refer to a place in memory where storage of the variable begins but the reference type itself does not define a specific amount of memory. The reason for this is fairly straightforward.

It's because we don't always know how much data will need to be stored in it until the program is actually run.

We can think of Strings and other reference types as continually expanding and contracting storage boxes. So won't one of these String reference types bump into another variable eventually?

As we are thinking about the device's memory as a huge warehouse full of racks of labeled storage boxes, then you can think of the DVM as a super-efficient forklift truck driver that puts the different types of storage boxes in the most appropriate place.

And if it becomes necessary, the DVM will quickly move stuff around in a fraction of a second to avoid collisions. Also, when appropriate, Dalvik, the forklift driver, will even incinerate unwanted storage boxes. This happens at the same time as constantly unloading new storage boxes of all types and placing them in the best place, for that type of variable. Dalvik keeps reference variables in a different part of the warehouse to the primitive variables. And we will learn more details about this in Chapter 9, Object-Oriented Programming.

So, Strings can be used to store any keyboard character. Kind of like char but of almost any length. Anything from a contact's name to an entire book can be stored in a single String. We will be using Strings regularly, including in this chapter.

There are a couple more reference types we will explore as well. Arrays are a way to store lots of variables of the same type, ready for quick and efficient access. We will look at arrays in Chapter 13, Handling and Displaying Arrays of Data.

Think of an array as an aisle in our warehouse with all the variables of a certain type lined up in a precise order. Arrays are reference types, so Dalvik keeps these in the same part of the warehouse as Strings. We might, for example, use an array to store dozens of contacts in.

The other reference type is the class that we have already discussed but not explained properly. We will be getting familiar with classes in Chapter 9, Object-Oriented Programming.

Now we know that each type of data that we might want to store will require an amount of memory. Hence, we must let the Java compiler know the type of the variable before we begin to use it. We do this with a variable declaration.

Variable declaration

That's enough theory. Let's see how we would actually use our variables and types. Remember that each primitive type requires a specific amount of real device memory. This is one of the reasons that the compiler needs to know what type a variable will be. So, we must first declare a variable and its type before we attempt to do anything with it.

To declare a variable of type int with the name unreadMessages, we would type:

int unreadMessages;

That's it, simply state the type, in this case int, then leave a space and type the name you want to use for this variable. Note also the semicolon ; on the end of the line will tell the compiler that we are done with this line and what follows, if anything, is not part of the declaration.

Similarly, for almost all the other variable types, declaration would occur in the same way. Here are some examples. The variable names in the examples are arbitrary. This is like reserving a labeled storage box in the warehouse:

long millisecondsElapsed;
float accountBalance;
boolean isFriend;
char contactFirstInitial;
String messageText;

Variable initialization

Initialization is the next step. Here, for each type, we initialize a value to the variable. Think about placing a value inside the storage box:

unreadMessages = 10;
millisecondsElapsed = 1438165116841l;// 29th July 2016 11:19am
accountBalance = 129.52f;
isFriend = true;
contactFirstInitial = 'C';
messageText = "Hi reader, Just thought I would let you know that Charles Babbage was an early computing pioneer and he invented the difference engine. If you want to know more about him you can click this link www.charlesbabbage.net. Thanks, John";

Notice that the char variable uses single quotes ' around the initialized value while the String uses double quotes ".

We can also combine the declaration and initialization steps. In the following we declare and initialize the same variables as we have previously, but in one step:

int unreadMessages = 10;
long millisecondsElapsed = 1438165116841l;//29th July 2016 11:19am
float accountBalance = 129.52f;
boolean isFriend = true;
char contactFirstInitial = 'C';
String messageText = "Hi reader, Just thought I would let you know that Charles Babbage was an early computing pioneer and he invented the difference engine. If you want to know more about him you can click this link http://www.charlesbabbage.net/. Thanks, John";

Whether we declare and initialize separately or together is probably dependent upon the specific situation. The important thing is that we must do both:

int a;
// That's me declared and ready to go?
// The line below attempts to output a to the console
Log.i("info", "int a = " + a);
// Oh no I forgot to initialize a!!

This would cause the following:

Compiler Error: Variable a might not have been initialized

There is a significant exception to this rule. Under certain circumstances variables can have default values. We will see this in Chapter 9, Object-Oriented Programming; however, it is good practice to both declare and initialize variables.