Chapter 2

It’s Java!

In This Chapter

check1 How computers, phones, and other devices run Java programs

check1 The parts of a typical Java program

Before I became an Android guy, I was a Java guy. A Java guy is a person who revels in the workings of Java programs. I wrote Java programs, read about Java programs, went to Java user group meetings, and wore Java T-shirts. That’s why I was thrilled to learn that Android’s application programming language is Java.

In the early 1990s, James Gosling at Sun Microsystems created Java. He used ideas from many programming language traditions, including the object-oriented concepts in C++. He created an elegant platform with a wide range of uses. In mid-2014 (which is “now” as far as my chapter-writing goes), Java runs on 88 percent of all desktop computers in the United States, and on 97 percent of all enterprise desktops, with nine million Java developers worldwide.* Do you have a Blu-ray player? Under the hood, your player runs Java.

In this minibook (Book II), this chapter and Chapters 3 and 4 introduce the ins and outs of the Java programming language. But these chapters don’t offer a comprehensive guide to Java. (To badly paraphrase Geoffrey Chaucer, “This book never yet no complete not Java coverage.”) Instead, these chapters hit the highlights of Java programming. For a more complete introduction to Java, read Java For Dummies, 6th Edition or Java Programming for Android Developers For Dummies (both published by John Wiley & Sons, Inc.). (Yes, I wrote those books, too.)

From Development to Execution with Java

Before Java became popular, most programs went almost directly from the developer’s keyboard to the processor’s circuits. But Java added an extra translation layer, and then Android added yet another layer. This section describes the layers.

What is a compiler?

A Java program (such as an Android application program) goes through several translation steps between the time you write the program and the time a processor runs it. The reason for this is simple: What’s convenient for processors to run is not convenient for people to write.

People can write and comprehend the code in Listing 2-1.

Listing 2-1: Java Source Code

public void checkVacancy(View view) {

    if (room.numGuests == 0) {

        label.setText("Available");

    } else {

        label.setText("Taken :-(");

    }

}

 

The Java code in Listing 2-1 checks for a vacancy in a hotel. You can’t run the code in Listing 2-1 without adding several lines. But at this stage of the game, those additional lines aren’t important. What’s important is that by staring at the code, squinting a bit, and looking past all the code’s strange punctuation, you can see what the code is trying to do:

If the room has no guests in it,

    then set the label’s text to "Available".

Otherwise,

    set the label’s text to "Taken :-(".

 

The stuff in Listing 2-1 is Java source code.

The processors in computers, phones, and other devices don’t normally follow instructions like the instructions in Listing 2-1. That is, processors don’t follow Java source code instructions. Instead, processors follow cryptic instructions like these:

A3 86 01 00  2A 85 00 00  00 4D 00 00  00 50 00 00

00 55 55 55  55 00 00 00  02 4D 00 05  00 07 00 80

00 14 00 80  40 38 25 00  00 40 4D 40  00 00 40 32

45 00 80 40  14 6B 65 72  6E 65 6C 00  5F 70 75 74

49 6E 4D 65  6D 6F 72 79  00 5F 6D 61  6B 65 49 6E

74 65 72 72  75 70 74 32  31 00 5F 69  6E 74 65 72

72 75 70 74  32 31 53 65  72 76 69 63  65 52 6F 75

74 69 6E 65  00 69 6E 74  72 00 5F 69  6E 74 65 72

72 75 70 74  00 20 60 55  89 E5 1E 8B  46 04 8B 76

06 8A 4E 08  8E D8 88 0C  1F 5D C3 55  89 E5 8B 46

04 1E 8C CB  8E DB BE 02  80 32 00 57  88 44 01 1F

8B 46 06 8B  5E 08 8B 4E  0A 8B 56 0C  CD 00 B4 00

5D C3 BA 80  4D 00 52 1E  B8 00 00 8E  D8 BE 84 00

8C C8 89 44  02 89 14 1F  C3 00

 

To be fair, this gobbledygook that I call “instructions” isn’t really numbers and letters. It’s just 0s and 1s. So the first A3 in my “instructions” is shorthand for 10100011.

I once participated in a three-part translation conversation. I spoke English to my mother, who translated it into Yiddish for her cousin, who translated it into Russian for the cousin’s husband. A similar kind of thing happens when you create an Android app. You start by writing Java source code, like the code in Listing 2-1. Your development computer translates the Java source code into Java bytecode. For a look at Java bytecode, see Listing 2-2.

Listing 2-2: Java Bytecode

 0 aload_0

 1 getfield #19 <com/allmycode/samples/MyActivity/room

 Lcom/allmycode/samples/Room;>

 4 getfield #47 <com/allmycode/samples/Room/numGuests I>

 7 ifne 22 (+15)

10 aload_0

11 getfield #41 <com/allmycode/samples/MyActivity/label

 Landroid/widget/TextView;>

14 ldc #54 <Available>

16 invokevirtual #56

 <android/widget/TextView/setText(Ljava/lang/CharSequence;)V>

19 goto 31 (+12)

22 aload_0

23 getfield #41 <com/allmycode/samples/MyActivity/label

 Landroid/widget/TextView;>

26 ldc #60 <Taken :-(>

28 invokevirtual #56

 <android/widget/TextView/setText(Ljava/lang/CharSequence;)V>

31 return

 

When you write a Java program, you write source code instructions (like the instructions in Listing 2-1). After writing the source code, you run the code through a program — you apply a tool to your source code, in other words. The program is a compiler. The compiler translates your source code instructions into Java bytecode instructions. In other words, the compiler takes code that you can write and understand (such as the code in Listing 2-1:) and translates your code into code that a computer can execute (such as the code in Listing 2-2).

technicalstuff You might put your source code in a file named HotelActivity.java. If so, the compiler probably puts the Java bytecode in another file named HotelActivity.class. Normally, you don’t bother looking at the bytecode in the HotelActivity.class file. In fact, the compiler doesn’t encode the HotelActivity.class file as ordinary text, so you can’t examine the bytecode with an ordinary editor. If you try to open HotelActivity.class with Notepad, TextEdit, KWrite, or even Microsoft Word, you see nothing but dots, squiggles, and other strange looking stuff. To create Listing 2-2, I had to apply yet another tool to my HotelActivity.class file. That tool displays a text-like version of a Java bytecode file. I used Ando Saabas’s Java Bytecode Editor (www.cs.ioc.ee/~ando/jbe).

remember No one (except for a few crazy developers in some isolated labs in faraway places) writes Java bytecode. You run software (a compiler) to create Java bytecode. The only reason to look at Listing 2-2 is to understand what a hard worker your computer is.

Like the language relay involving me, my mother, and my mother’s cousins, the translation from source code to 0s and 1s doesn’t end with Listing 2-2. In 2007, Dan Bornstein at Google created Dalvik bytecode — another way of representing instructions for processors to follow. (To find out where some of Bornstein’s ancestors come from, run your favorite Map application and look for Dalvik in Iceland.) Dalvik bytecode is optimized for the limited resources on a phone or a tablet device. Listing 2-3 contains some sample Dalvik instructions.*

Listing 2-3: Dalvik Bytecode

.method public checkVacancy(Landroid/view/View;)V

.limit registers 4

; this: v2 (Lcom/allmycode/samples/MyActivity;)

; parameter[0] : v3 (Landroid/view/View;)

.line 30

    iget-object

    v0,v2,com/allmycode/samples/MyActivity.room

    Lcom/allmycode/samples/Room;

; v0 : Lcom/allmycode/samples/Room; , v2 :

  Lcom/allmycode/samples/MyActivity;

  iget v0,v0,com/allmycode/samples/Room.numGuests I

; v0 : single-length , v0 : single-length

  if-nez v0,l4b4

; v0 : single-length

.line 31

  iget-object

  v0,v2,com/allmycode/samples/MyActivity.label

  Landroid/widget/TextView;

; v0 : Landroid/widget/TextView; , v2 :

  Lcom/allmycode/samples/MyActivity;

  const-string v1,"Available"

; v1 : Ljava/lang/String;

  invoke-virtual

  {v0,v1},android/widget/TextView/setText

  ; setText(Ljava/lang/CharSequence;)V

; v0 : Landroid/widget/TextView; , v1 : Ljava/lang/String;

l4b2:

.line 36

  return-void

l4b4:

.line 33

  iget-object

  v0,v2,com/allmycode/samples/MyActivity.label

  Landroid/widget/TextView;

; v0 : Landroid/widget/TextView; , v2 :

  Lcom/allmycode/samples/MyActivity;

  const-string v1,"Taken :-("

; v1 : Ljava/lang/String;

  invoke-virtual

  {v0,v1},android/widget/TextView/setText ;

  setText(Ljava/lang/CharSequence;)V

; v0 : Landroid/widget/TextView; , v1 : Ljava/lang/String;

  goto l4b2

.end method

 

technicalstuff Java bytecode instructions use a stack machine format. In contrast, Dalvik bytecode instructions use a register machine format. The upshot of this (for those who don’t know much about machine language formats) is that a typical Dalvik instruction is longer and more complicated than a Java bytecode instruction. Despite what you see in Listings 2-2 and 2-3, a big Dalvik instruction normally replaces several little Java bytecode instructions.

When you create an Android app, Android Studio performs at least two compilations. The first compilation creates Java bytecode from your Java source files. (Your source filenames have the .java extension; the Java bytecode filenames have the .class extension.) The second compilation creates Dalvik bytecode from your Java bytecode files. (Dalvik bytecode filenames have the .dex extension.) To perform the first compilation, Android Studio uses a program named javac, or the Java compiler. To perform the second compilation, Android Studio uses a program named dx (known affectionately as the dx tool).

Android Studio compiles Java bytecode (Listing 2-2) to get Dalvik bytecode (Listing 2-3). Does the compiling end here? Not at all. When a user’s mobile device gets ahold of some Dalvik bytecode, the device does even more compiling. One way or another, the device runs a virtual machine. “And what,” you ask, “is a virtual machine?” It’s funny that you should ask this question. Your question is the title of the very next section!

What is a virtual machine?

The instructions in Listings 2-2 and 2-3 are meant for processors to use, not for people to use. Even so, the processors in computers and mobile phones don’t execute Java bytecode instructions (Listing 2-2) or Dalvik bytecode instructions (Listing 2-3). Instead, each kind of processor has its own set of executable instructions, and each operating system uses the processor’s instructions in a slightly different way.

Imagine that you have two different devices — a smartphone and a tablet computer. The devices have two different kinds of processors. The phone has an ARM processor, and the tablet has an Intel Atom processor. (The acronym ARM once stood for Advanced RISC Machine. These days, ARM simply stands for ARM Holdings, a company whose employees design processors.) On the ARM processor, the multiply instruction is 000000. On an Intel processor, the multiply instructions are D8, DC, F6, F7, and others. Many ARM instructions have no counterparts in the Atom architecture, and many Atom instructions have no equivalents on an ARM processor. An ARM processor’s instructions make no sense to your tablet’s Atom processor, and an Atom processor’s instructions would give your phone’s ARM processor a virtual headache.

So what’s a developer to do? Does a developer provide translations of every app into every processor’s instruction set? No.

Virtual machines create order from all this chaos. Dalvik bytecode is something like the code in Listing 2-3, but Dalvik bytecode isn’t specific to one kind of processor or to one operating system. Instead, a set of Dalvik bytecode instructions runs on any processor. If you write a Java program and compile that Java program into Dalvik bytecode, your Android phone, your Android tablet, and even your grandmother’s supercomputer can run the bytecode. (To do this, your grandmother must install Android-x86, a special port of the Android operating system, on her Intel-based machine.)

Both Java bytecode and Dalvik bytecode have virtual machines. With a virtual machine, you can take a bytecode file that you created for one Android device, copy the bytecode to another Android device, and then run the bytecode with no trouble at all. That’s one of the many reasons why Android has become popular so quickly. This outstanding feature, which gives you the ability to run code on many different kinds of computers, is called portability.

Imagine that you’re the Intel representative to the United Nations Security Council. (See Figure 2-1.) The ARM representative is seated to your right, and the representative from Texas Instruments is on your left. (Naturally, you don’t get along with either of these people. You’re always cordial to one another, but you’re never sincere. What do you expect? It’s politics!) The distinguished representative from Dalvik is at the podium. The Dalvik representative speaks in Dalvik bytecode, and neither you nor your fellow ambassadors (ARM and Texas Instruments) understand a word of Dalvik bytecode.

image

Figure 2-1: An imaginary meeting of the UN Security Council.

But each of you has an interpreter. Your interpreter translates from Dalvik bytecode to Intel instructions as the Dalvik representative speaks. Another interpreter translates from bytecode to ARM-ese. And a third interpreter translates bytecode into Texas Instruments speak.

Think of your interpreter as a virtual ambassador. The interpreter doesn’t really represent your country, but the interpreter performs one of the important tasks that a real ambassador performs. The interpreter listens to Dalvik bytecode on your behalf. The interpreter does what you would do if your native language was Dalvik bytecode. The interpreter pretends to be the Intel ambassador and sits through the boring bytecode speech, taking in every word, and processing each word in some way or other.

You have an interpreter — a virtual ambassador. In the same way, an Intel processor runs its own bytecode interpreting software. That software is a virtual machine.

A virtual machine is a proxy, an errand boy, a go-between. The virtual machine serves as an interpreter between run-anywhere bytecode and your device’s own system. As it runs, a virtual machine walks your device through the execution of bytecode instructions. The virtual machine examines your bytecode, bit by bit, and carries out the instructions described in the bytecode. The virtual machine interprets bytecode for your ARM processor, your Intel processor, your Texas Instruments chip, or whatever kind of processor you’re using. That’s a good thing. It’s what makes Java code and Dalvik code more portable than code written in any other language.

Back in 2007, along with Dalvik bytecode, the folks at Google created a Dalvik virtual machine. This virtual machine runs Android apps on devices running Cupcake, Donut, and all the desserts up to and including KitKat. But in 2013, Google announced a replacement for Dalvik called ART. (The acronym ART stands for Android RunTime.) ART still uses Dalvik bytecode of the kind shown in Listing 2-3. (Despite what you read in the tabloids, Dalvik hasn’t gone away entirely.) But after your code is translated to Dalvik bytecode, ART takes advantage of the enhanced horsepower in newer smartphones. In general, an app that’s executed with ART runs much faster than the same app executed with Dalvik. By default, every app created for the Android Lollipop (and beyond) target runs on the newer ART virtual machine.

technicalstuff One of the big differences between the Dalvik and ART virtual machines is the time when a final translation step takes place. The Dalvik machine uses just-in-time (JIT) compilation, which means that the final translation takes place as needed while the app runs on a user’s device. But wait! Doesn’t that final translation take up time during the run? Doesn’t the user notice slower performance while the phone does a last translation step on the code? Yes! JIT compilation slows down the run of an app. In contrast to Dalvik’s JIT compilation, ART uses ahead-of-time (AOT) compilation. With AOT, an app’s final translation takes place when the app is being installed on a device. By the time a user runs the app, the app’s code has already been translated. That’s one of the reasons why ART’s virtual machine is faster than Dalvik’s.

Grasping Java Code

When you create a new project, Android’s tools create a small, no-nonsense Java class. I’ve copied the Java class in Listing 2-4.

Listing 2-4: A Minimalistic Android Activity Class

package com.allmycode.samples;

import android.app.Activity;

import android.os.Bundle;

import android.view.Menu;

import android.view.MenuItem;

public class MyActivity extends Activity {

   @Override

   protected void onCreate(Bundle savedInstanceState) {

      super.onCreate(savedInstanceState);

      setContentView(R.layout.activity_my);

   }

   @Override

   public boolean onCreateOptionsMenu(Menu menu) {

      getMenuInflater().inflate(R.menu.my, menu);

      return true;

   }

   @Override

   public boolean onOptionsItemSelected(MenuItem item) {

      int id = item.getItemId();

      if (id == R.id.action_settings) {

         return true;

      }

      return super.onOptionsItemSelected(item);

   }

}

 

This chapter covers the Java language features used in Listing 2-4. So in this chapter, android.app.Activity (from the second line of Listing 2-4) is only the name of something to import — nothing more. To read about the meaning of the word Activity and the word’s implications for Android, see Book III, Chapter 1.

The Java class

Java is an object-oriented programming language. So, as a developer, your primary goal is to describe objects. Your closely related goal is to describe objects' close cousins — namely, classes.

In Java, nothing happens unless it happens inside an object or a class. The code in Listing 2-4 is a class. I created the code, so I get to make up a name for my new class. I chose the name MyActivity because the code in Listing 2-4 describes one screen full of stuff on an Android device (and in Android, a screen full of stuff is an activity). So the code in Listing 2-4 contains the words public class MyActivity.

The words public and class are Java keywords. What that means is that no matter who writes a Java program, the word class always has the same meaning. The same holds true of the word public (although some classes aren’t declared to be public).

On the other hand, the word MyActivity in Listing 2-4 is an identifier. I made up the word MyActivity while I was creating the example for this chapter. (I could have changed the word to MainActivity, YourActivity or BoopADoop if I wanted to do so.) The word MyActivity is the name of a particular class — the class that I’m creating by writing this program.

A Java identifier can be any word containing only letters, digits, and underscores ( _ ). An identifier must not begin with a digit. Other than that, there are no restrictions. Words like MainActivity, LaFong3, and a_b_c are valid Java identifiers. A word like 1Mississippi isn’t valid because it begins with a digit. A phrase like my activity isn’t valid because it contains a blank space. A string like one~two is invalid because the tilde (~) isn’t a letter, a digit, or an underscore.

warning tHE jAVA PROGRAMMING LANGUAGE IS cASe-sEnsITiVE. iF YOU CHANGE A lowercase LETTER IN A WORD TO AN UPPERCASE LETTER, YOU CHANGE THE WORD’S MEANING.

If you define a public class named DogAndPony, the class’s Java code must go in a file named DogAndPony.java, spelled and capitalized exactly the same way as the class name is spelled and capitalized. If you define a class named MySecretStuff and write class MySecretStuff instead of public class MySecretStuff, you can put the MySecretStuff code in any file whose extension is .java. (Go ahead. Call your file Urkshjk98t.java. See if I care.)

Classes and objects

When you program in Java, you work constantly with classes and objects. Here’s an analogy: A chair has a seat, a back, and legs. Each seat has a shape, a color, a degree of softness, and so on. These are the properties that a chair possesses. What I describe is chairness — the notion of something being a chair. In object-oriented terminology, I’m describing the Chair class.

remember In the preceding paragraph, I refer to the Chair class, not to the chair class. If you want to look like a very inexperienced developer, start the names of your Java classes with lowercase letters. With a class name such as chair, your code does what you want it to do, but you’re committing a stylistic faux pas. Real Java developers start the names of their classes with uppercase letters.

Now peek over the edge of this book’s margin and take a minute to look around your room. (If you’re not sitting in a room right now, fake it.)

Several chairs are in the room, and each chair is an object. Each of these objects is an example of that ethereal thing called the Chair class. So that’s how it works — the class is the idea of chairness, and each individual chair is an object.

remember A class isn’t quite a collection of things. Instead, a class is the idea behind a certain kind of thing. When I talk about the class of chairs in your room, I’m talking about the fact that each chair has legs, a seat, a color, and so on. The colors may be different for different chairs in the room, but that doesn’t matter. When you talk about a class of things, you’re focusing on the properties that each of the things possesses.

It makes sense to think of an object as being a concrete instance of a class. In fact, the official terminology is consistent with this thinking. If you write a Java program in which you define a Chair class, each actual chair (the chair that you’re sitting on, the empty chair right next to you, and so on) is called an instance of the Chair class.

Here’s another way to think about a class. Imagine a table displaying three bank accounts. (See Table 2-1.)

Table 2-1 A Table of Accounts

Name

Address

Balance

Barry Burd

222 Cyberspace Lane

24.02

John Q. Public

140 Any Way

–471.03

Jane Dough

800 Rich Street

247.38

Think of the table’s column headings as a class, and think of each row of the table as an object. The table’s column headings describe the Account class.

According to the table’s column headings, each account has a name, an address, and a balance. Rephrased in the terminology of object-oriented programming, each object in the Account class (that is, each instance of the Account class) has a name, an address, and a balance. So, the bottom row of the table is an object with the name Jane Dough. This same object has the address 800 Rich Street and a balance of 247.38. If you opened a new account, you would have another object, and the table would grow an additional row. The new object would be an instance of the same Account class.

Java types

What does “six” mean? You can have six children, but you can also be six feet tall. With six children, you know exactly how many kids you have. (Unlike the average American family, you can’t have 2.5 kids.) But if you’re six feet tall, you could really be six feet and half an inch tall. Or you might be five feet eleven-and-three-quarter inches tall, and no one would argue about it.

A value’s meaning depends on the value’s type. If you write

int numberOfChildren = 6;

 

in a Java program, 6 means “exactly six.” But if you write

double height = 6;

 

in a Java program, 6 means “as close to six as you care to measure.” And if you write

char keystroke = ’6’;

 

in a Java program, ’6’ means “the digit that comes after the 5 digit.”

In a Java program, every value has a type. Java has eight primitive types (types that are built into the language) and has as many reference types as you want to create.

Table 2-2 lists Java’s eight primitive types.

Table 2-2 Java’s Primitive Types

Type Name

What a Literal Looks Like

Range of Values

Whole number types

byte

(byte)42

–128  to 127

short

(short)42

–32768 to 32767

int

42

–2147483648 to 2147483647

long

42L

–9223372036854775808 to 9223372036854775807

Decimal number types

float

42.0F

–3.4 × 1038 to 3.4 × 1038

double

42.0

–1.8 × 10308 to 1.8 × 10308

Character type

char

'A'

Thousands of characters, glyphs, and symbols

Logical type

boolean

true

true, false

A literal is an expression whose value doesn’t change from one Java program to another. For example, the expression 42 means “the int value 42” in every Java program. Likewise, the expression ‘B’ means “the second uppercase letter in the Roman alphabet” in every Java program, and the word true means “the opposite of false” in every Java program.

In addition to its primitive types, Java has reference types. The code in Listing 2-4 contains the names of five reference types.

  • The reference type android.app.Activity is defined in the Android API (Android’s enormous library of ready-made declarations).

    The reference types android.os.Bundle, android.view.Menu, and android.view.MenuItem are also defined in the Android API.

  • The reference type MyActivity is defined in Listing 2-4.

How about that? Every class is a type!

When you write int numberOfChildren = 6, you declare the existence of a variable named numberOfChildren. The variable numberOfChildren has type int and has initial value 6.

But in Listing 2-4, android.os.Bundle, android.view.Menu, and android.view.MenuItem are also types. (They’re reference types.) In fact, android.os.Bundle, android.view.Menu, and android.view.MenuItem are the names of classes that are declared as part of Android’s API. So, just as you can write int numberOfChildren in a Java program, you can write Bundle savedInstanceState in Listing 2-4. (You can abbreviate android.os.Bundle to the simpler name Bundle because of the import declaration near the top of Listing 2-4.)

Because every class is a type, and because your newly declared MyActivity type is a class, you can add a line such as

MyActivity anActivity;

 

to the code in Listing 2-4. This new line declares that the name anActivity is a placeholder for a value (a value whose type is MyActivity). In case this idea muddies your mind, Listing 2-5 has another example.

Listing 2-5: A Class Is a Type

public class Account {

    String name;

    String address;

    double balance;

}

Account myAccount = new Account();

Account yourAccount = new Account();

myAccount.name = "Burd";

yourAccount.name = "Dough";

myAccount.balance = 24.02;

 

warning Listing 2-5 doesn’t contain a complete Java program. If you try to run the code in Listing 2-5 (without first adding some other stuff to the code), you get all kinds of error messages.

Listing 2-5 declares a class named Account. This blueprint for an account has three fields. The first field — the name field — refers to a Java String (a bunch of characters lined up in a row). The second field — the address field — refers to another Java String. The third field — the balance field — stores a double value. (Refer to Table 2-2.)

A class is “the idea behind a certain kind of thing.” (I quote myself frequently.) An object is “a concrete instance of a class.” So in Listing 2-5, the variable myAccount refers to an actual Account object, and the variable yourAccount refers to another Account object. The last statement in Listing 2-5 assigns the value 24.02 to the balance field of the object referred to by myAccount.

The Java method

A method is a chunk of code that performs some actions, and (possibly) produces a result. If you’ve written programs in other languages, you may know about functions, procedures, Sub procedures, or other such things. In Java, such things are called methods.

In Listing 2-4, the code

public boolean onCreateOptionsMenu(Menu menu) {

    getMenuInflater().inflate(R.menu.my, menu);

    return true;

}

 

declares the existence of a method. The method’s name is onCreateOptionsMenu.

remember Real Java developers start the names of their methods with lowercase letters. You can ignore this convention. But if you ignore it, real Java developers will wince when they read your code.

Somewhere, buried deep inside the Android’s virtual machine caverns, lives a line of code that looks something like this:

onCreateOptionsMenu(menu);

 

That line of code calls the onCreateOptionsMenu method of Listing 2-4. In other words, when the Android’s virtual machine executes the onCreateOptionsMenu(Menu menu) statement, the flow of execution jumps to the first instruction inside the onCreateOptionsMenu method declaration in Listing 2-4.

remember A method declaration goes hand in hand with one or more calls. A method’s declaration (such as the onCreateOptionsMenu declaration in Listing 2-4) defines the actions that a method eventually performs. The method doesn’t perform any of its actions until some other piece of code executes a call to that method.

The onCreateOptionsMenu method’s call hides inside some unseen Android system code. This situation isn’t typical of methods and their calling statements. As an Android developer, you routinely declare a method in one part of your program and then call your own method in another part of the program.

The statements inside a method’s declaration are collectively called the method body. Take, for example, the onCreate method in Listing 2-4. The onCreate method’s body contains two statements (two instructions). The second statement, setContentView(R.layout.main), is a call to a method named setContentView. (The setContentView method’s declaration comes with every Android implementation, so you don’t declare the setContentView method yourself.)

Like any method call, the call setContentView(R.layout.main) starts with a method name. The stuff in parentheses after the method’s name is a parameter list. For insight into parameter lists, consider the code in Listing 2-6.

Listing 2-6: A Method and Two Method Calls

double monthlyPayment(double principal, double percentageRate, int years) {

  int numPayments = 12 * years;

  double rate = percentageRate / 100.00;

  double effectiveRate = rate / 12;

  return principal * (effectiveRate /

    (1 - Math.pow(1 + effectiveRate, -numPayments)));

}

double myPayment = monthlyPayment(100000.00, 5.25, 30);

double yourPayment = monthlyPayment(100000.00, 5.00, 15);

 

The code in Listing 2-6 isn’t a complete Java program. You can’t run the code without adding a bunch of stuff to it. Even so, the code illustrates some important ideas about methods and their parameters:

  • The name of the method declared in Listing 2-6 is monthlyPayment.
  • In the body of the monthlyPayment method declaration, the processor computes the monthly payments on a mortgage.

    You can follow this description of methods and method parameters without understanding anything about the calculations in Listing 2-6.

  • The body of the monthlyPayment method uses certain names as placeholders.

    For example, in the body of the monthlyPayment method, the name years stands for the number of years in the mortgage’s term. Likewise, the name principal stands for the total amount borrowed.

  • Some placeholders appear in parentheses at the beginning of the method’s declaration.

    The names principal, percentageRate, and years are the method’s parameters. Each parameter is destined to stand for a particular value. But a parameter doesn’t stand for a value until an app executes a method call.

    In Listing 2-6, the call monthlyPayment(100000.00, 5.25, 30) gives the method’s first parameter (namely, principal) the value 100000.00. That same call gives the method’s second parameter (percentageRate) the value 5.25. Finally, that method call gives the method’s third parameter (years) the value 30.

    The next method call in Listing 2-6 gives the monthlyPayment method’s parameters different values (again 100000.00 for principal, but 5.00 for percentageRate and 15 for years). Each time you call a method, you supply values for the method’s parameters.

  • The types of parameters in a method call must match the types of the parameters in a method declaration.

    The declaration of method monthlyPayment in Listing 2-6 has a double parameter (principal), another double parameter (percentageRate), and an int parameter (years). Accordingly, the first method call in Listing 2-6 has two double parameters (100000.00 and 5.25) followed by an int parameter (30). The second method call in Listing 2-6 also has two double parameters followed by an int parameter.

    technicalstuff You can declare the same method more than once, as long as each declaration has a different parameter list. For example, another method declaration in Listing 2-6 might have the same name monthlyPayment but only two parameters: double monthlyPayment(double principal, double percentageRate). To call this alternative monthlyPayment method, you write something like monthlyPayment(100000.00, 5.25). In this situation, the body of the alternative monthlyPayment method probably contains a statement like years = 30. You don’t call this two-parameter method unless you know that the mortgage’s term is 30 years.

  • A method call might stand for a value.

    The first method call in Listing 2-6 (in the listing’s next-to-last line) stands for the double value 552.20 (or a value very close to the number 552.20). The value 552.20 comes from all the calculations in the body of the monthlyPayment method when the principal is 100000.00, the percentageRate is 5.25, and the number of years is 30. Near the end of the monthlyPayment method’s body, the formula

    principal * (effectiveRate /

        (1 - Math.pow(1 + effectiveRate, -numPayments)))

    has the value 552.20, and the word return says “send 552.20 back to the statement that called this method.” So, in Listing 2-6, the end of the monthlyPayment method body effectively says

    return 552.20;

    and the next-to-last line in the listing effectively says

    double myPayment = 552.20;

    Similarly, the second method call in Listing 2-6 (the listing’s last line) stands for the value 790.79. Because of the second method call’s parameter values, the end of the monthlyPayment method body effectively says

    return 790.79;

    and the last line in the listing effectively says

    double yourPayment = 790.79;

  • A method’s declaration begins (much of the time) with the name of the return type.

    In Listing 2-6, the monthlyPayment method declaration begins with the type name double. That’s good because the value returned at the end of the method’s body (either 552.20 or 790.79) is of type double. Also, the names myPayment and yourPayment store double values, so it’s okay to assign the value of the call monthlyPayment(100000.00, 5.25, 30) to myPayment, and to assign the value of the call monthlyPayment(100000.00, 5.00, 15) to yourPayment.

    Similarly, in Listing 2-4, the onCreateOptionsMenu and onOptionsItemSelected method declarations begin (more or less) with the type name boolean. The type boolean represents only one of two possible values — true or false. So the value returned at the end of the onCreateOptionsMenu method’s body can be true. Also, if the Android’s system’s code contains a line like

    boolean menuResult = onCreateOptionsMenu(someMenu);

    then menuResult has type boolean so everything is hunky-dory.

  • A method call doesn’t necessarily stand for a value.

    In Listing 2-1, the word void in the first line of the checkVacancy method indicates that a call to checkVacancy doesn’t stand for a value. That is, a call to checkVacancy performs some actions, but the call doesn’t calculate an answer of any kind.

    Similarly, the method onCreate in Listing 2-4 doesn’t return a value.

Objects and their constructors

Earlier, I introduce you to the Chair class example, and how it’s the idea of chairness, and how each individual chair is an object … If you write a Java program in which you define a Chair class, each actual chair (the chair that you’re sitting on, the empty chair right next to you, and so on) is called an instance of the Chair class. I also encourage you to think of the table’s column headings as a class and to think of each row of the table as an object.

To drive this point home, consider the code in Listing 2-7.

Listing 2-7: What Is an Account?

package com.allmycode.samples;

public class Account {

    public String name;

    public String address;

    public double balance;

    public Account(String name, String address, double balance) {

      this.name = name;

      this.address = address;

      this.balance = balance;

    }

    /** Called at the end of each month */

    public String infoString() {

      return name + " (" + address + ") has $" + balance;

    }

}

 

Listing 2-7 is a souped-up version of the code in Listing 2-5. In Listing 2-7, an Account has a name, an address, a balance, and an infoString method. The infoString method describes a way of composing a readable description of the account.

remember The variables name, address, and balance are fields of the Account class. In addition, the variables name, address, balance, and the method infoString are members of the Account class.

The Account class also has something that looks like a method, but isn’t really a method. In Listing 2-7, the text beginning with public Account(String name is the start of a constructor. A constructor describes a way of creating a new instance of a class.

According to the code in Listing 2-7, each object created from the Account class has its own name, its own address, and its own balance. So, in Listing 2-7, the Account constructor’s instructions say:

  • this.name = name;

    When creating a new object (a new instance of the Account class), make this new object’s name be whatever name has been passed to the constructor’s parameter list. (See Figure 2-2.)

  • this.address = address;

    When creating a new object (a new instance of the Account class), make this new object’s address be whatever address has been passed to the constructor’s parameter list.

  • this.balance = balance;

    When creating a new object (a new instance of the Account class), make this new object’s balance be whatever balance has been passed to the constructor’s parameter list.

image

Figure 2-2: How an Account instance gets its name.

tip You can tell a constructor from a method by checking two things. First, the constructor’s name is the same as the class’s name. In Listing 2-7, both the class and the constructor have the name Account. Second, a constructor has no return type, not even void. In Listing 2-7, the infoString method has return type String. But the Account constructor has no return type.

Listing 2-8 shows you how to use the code in Listing 2-7. In Listing 2-8, the statement Account account1 = new Account("Burd", "222 Cyberspace Lane", 24.02) calls the constructor from Listing 2-7. As a result, the app has a brand-new instance of the Account class. The variable account1 refers to that new object.

Listing 2-8: Using the Account Class

package com.allmycode.samples;

import android.app.Activity;

import android.os.Bundle;

import android.widget.TextView;

public class MyActivity extends Activity {

    TextView textView1;

    @Override

    public void onCreate(Bundle savedInstanceState) {

       super.onCreate(savedInstanceState);

       setContentView(R.layout.main);

       Account account1 = new Account(“Burd”, "222 Cyberspace Lane”, 24.02);

       textView1 =

          ((TextView) findViewById(R.id.textView1));

       textView1.setText(account1.infoString());

    }

}

 

Later in Listing 2-8, the text account1.infoString() calls the new account1 object’s infoString method. The method returns a handsome-looking string of characters, which the activity displays on its screen.

remember To refer to a member belonging to an object, use the dot notation. For example, to call the account1 object’s infoString method, write account1.infoString(). To refer to the account1 object’s balance, write account1.balance. Method calls require parentheses, and field names don’t use parentheses.

When you run the code in Listing 2-8, you get the screen shown in Figure 2-3.

image

Figure 2-3: A run of the app in Listings 2-7 and 2-8.

Classes grow on trees

Listing 2-4 contains the words extends Activity. Apparently, the new MyActivity class, declared in Listing 2-4, is some kind of extension of something called Activity. So what’s this all about?

You can download the Android source code (the Java code that comprises Android’s many pre-declared classes). When you do, you can open the Activity.java file with your favorite editor. Listing 2-9 contains an (admittedly unrepresentative) portion of the code in that file.

crossreference For more information about downloading Android’s source code, visit http://source.android.com/source/downloading.html.

Listing 2-9: A Seriously Abridged Version of Android’s Activity Class

package android.app;

public class Activity extends ContextThemeWrapper {

   protected void onCreate(Bundle savedInstanceState) {

      mVisibleFromClient =

        !mWindow.getWindowStyle().getBoolean(

           com.android.internal.R.styleable.

           Window_windowNoDisplay, false);

      mCalled = true;

   }

   protected void onDestroy() {

      mCalled = true;

      // dismiss any dialogs we are managing.

      if (mManagedDialogs != null) {

         final int numDialogs = mManagedDialogs.size();

         for (int i = 0; i < numDialogs; i++) {

            final ManagedDialog md =

               mManagedDialogs.valueAt(i);

            if (md.mDialog.isShowing()) {

              md.mDialog.dismiss();

            }

         }

         mManagedDialogs = null;

      }

         // Close any open search dialog

         if (mSearchManager != null) {

            mSearchManager.stopSearch();

         }

   }

}

 

The Android SDK comes with an Activity class, and the Activity class contains methods named onCreate and onDestroy. (Actually, the Android’s Activity class contains at least 140 methods. But who’s counting?) In Listing 2-4, the words MyActivity extends Activity establish a relationship between the MyActivity class and Android’s Activity class. Among other things, the MyActivity class inherits fields and methods belonging to the Activity class. So without adding any code to Listing 2-4, you can rest assured that MyActivity has an onDestroy method. It’s as if you copied the onDestroy method declaration from Listing 2-9 and pasted that declaration into Listing 2-4.

Aside from the extends terminology, Java has several names for the relationship between the MyActivity class and the Activity class:

  • The MyActivity class is a subclass of the Activity class.
  • The MyActivity class is a child of the Activity class.
  • The Activity class is the superclass of the MyActivity class.
  • The Activity class is the parent of the MyActivity class.

If all this parent/child business reminds you of a family tree, you’re not alone. Java developers draw upside-down trees all the time. For example, a small part of the tree for the class in Listing 2-4 is pictured in Figure 2-4.

image

Figure 2-4: A small part of the Activity class’s family tree.

At the top of Figure 2-4, the tree’s root is Java’s ancestor of all classes — the Object class. Android’s Context class is a subclass of the Object class. The Context class has many subclasses, two of which (Application and ContextWrapper) are pictured in Figure 2-4. From there on, ContextWrapper begets ContextThemeWrapper, which begets Activity, which begets the main activity class in a typical Android app.

remember A class can have many subclasses, but a class has only one superclass. The only class with no superclass is Java’s Object class.

The Java package

Java has a feature that lets you lump classes into groups of classes. Each lump of classes is a package. The class in Listing 2-4 belongs to the com.allmycode.samples package because of the listing’s first line of code.

In the Java world, developers customarily give packages long, dot-filled names. For instance, because I’ve registered the domain name allmycode.com, I name a package com.allmycode.samples or com.allmycode.whateverIwant. The Java API is actually a big collection of packages. The API has packages with names like java.lang, java.util, java.awt, javax.swing, and so on. The Android SDK is also a bunch of packages, with package names such as android.app, android.view, and android.telephony.gsm.

An import declaration starts with the name of a package and ends with either of the following:

  • The name of a class within that package
  • An asterisk (indicating all classes within that package)

For example, in the declaration

import android.app.Activity;

 

android.app is the name of a package in the Android SDK, and Activity is the name of a class in the android.app package. The dotted name android.app.Activity is the fully qualified name of the Activity class. A class’s fully qualified name includes the name of the package in which the class is defined.

With an import declaration, you don’t have to repeatedly use a class’s fully qualified name. For example, in Listing 2-4, you could write

public class MyActivity extends android.app.Activity

 

but because of the Listing’s import declaration, you can get away with plain old

public class MyActivity extends Activity

 

In a declaration such as

import android.app.*;

 

the asterisk refers to all classes in the android.app package. With this import declaration at the top of your Java code, you can use abbreviated names for all classes in the android.app package — names like Activity, AlertDialog, Fragment, ListActivity, and many others.

A public class

A class can be either public or non-public. If you see something like

public class SomeClass

 

you’re looking at the declaration of a public class. But, if you see plain old

class SomeClass

 

the class that’s being declared isn’t public.

If a class is public, you can refer to the class from anywhere in your code. The following example illustrates the point.

In one file, you have

package com.allmycode.somepackage;

public class SomeClass {

}

 

And in another file, you have

package com.allmycode.someotherpackage;

import com.allmycode.somepackage.*;

//You CAN extend SomeClass:

class SomeOtherClass extends SomeClass {

    public void doStuff() {

        //This works too:

        SomeClass someObject = new SomeClass();

    }

}

 

If a class isn’t public, you can refer to the class only from code within the class’s package. The following code makes that crystal clear.

In one file, you have

package com.allyourcode.somepackage;

class SomeClass {

}

 

And in another file, you have

package com.allyourcode.someotherpackage;

import com.allyourcode.somepackage.*;

//You can't extend SomeClass:

class SomeOtherClass extends SomeClass {

    public void doStuff() {

        //This doesn’t work either:

        SomeClass someObject = new SomeClass();

    }

}

Other public things

The scope of a name is the range of code in which you (the developer) can use the name. So, to sum up the preceding section’s long-winded explanation:

  • The scope of a public class’s name includes all Java code.
  • The scope of a non-public class’s name is limited to the package in which the class is declared.

technicalstuff A public class’s name doesn’t really include all Java code. If I’m running a Java program on a computer at my moon base, and you’re running a program on your phone while vacationing in orbit around Mars, your phone can’t access my code’s public classes. For code to access my public classes, that code must be running on the same Java virtual machine.

A class’s members (the class’s methods and fields) can also be public. For example, the class in Listing 2-7 has the public fields name, address, and balance, and has the public method infoString. In fact, the story for class members is a bit more involved. The word public is an access modifier, and a member of a class can be public, private, or protected, or have no access modifier. (For example, the textView1 field in Listing 2-8 has no access modifier. The onCreate and onDestroy methods in Listing 2-9 have protected access.)

Your access modifier choices break down as follows:

  • A public member’s scope includes all Java code.
  • A private member’s scope includes the class in which the member is declared.
  • A protected member’s scope includes the class in which the member is declared. The scope also includes any subclasses of the class in which the member is declared and all classes belonging to the package in which the member is declared.
  • The scope of a member with no access modifier includes the class in which the member is declared. The scope also includes all classes belonging to the package in which the member is declared.

I don’t know about you, but I have trouble wrapping my head around the idea of protected access. One of the difficulties is that, contrary to my intuitions, sporting the word protected is less restrictive than sporting no access modifier at all. Anyway, when I encounter a member with protected access, I stop and think about it long enough for my queasiness to go away.

Defying your parent

In families, children often rebel against their parents' values. The same is true in Java. The MyActivity class (in Listing 2-4) is a child of the Activity class (in Listing 2-9). So at first glance, MyActivity should inherit the onCreate method declared in the Activity class’s code.

But both the Activity and MyActivity classes have onCreate method declarations. And the two onCreate declarations have the same parameter list. In this way, the MyActivity class rebels against its parent. The MyActivity class says to the Activity class, “I don’t want your stinking onCreate method. I’m declaring my own onCreate method.”

So when you fire up an app, and your phone creates a MyActivity object, the phone executes the MyActivity version of onCreate, not the parent Activity version of onCreate.

technicalstuff Like all rebellious children, MyActivity can’t break completely from its parent class’s code. The first statement in the MyActivity class’s onCreate method is a call to super.onCreate. (My kids don’t usually refer to me as super, but a class refers to its parent that way.) Anyway, the statement super.onCreate calls the parent class’s onCreate method. So, before the onCreate method in Listing 2-4 does anything else, the processor runs the onCreate method in Listing 2-9. (The creators of Android rigged things so that your onCreate method must call super.onCreate. If you forget to call super.onCreate, Android displays a blunt, annoying error message.)

Java annotations

Each @Override word in Listing 2-4 is an example of an annotation. An annotation tells Java something about your code. In particular, each @Override annotation in Listing 2-4 tells the Java compiler to be on the lookout for a common coding error. The annotation says, “Make sure that the method immediately following this annotation has the same stuff (the same name, the same parameters, and so on) as one of the methods in the Activity class. If not, display an error message.”

So if I accidentally misspell a method’s name, as in

@Override

public void nCreate(Bundle savedInstanceState)

 

the compiler reminds me that my new nCreate method doesn’t really override anything that’s in Android’s pre-declared Activity class. Oops!

Java comments

A comment is part of a program’s text. But unlike declarations, method calls, and other such things, a comment’s purpose is to help people understand your code. A comment is part of a good program’s documentation.

The Java programming language has three kinds of comments:

  • Block comments

    A block comment begins with /* and ends with */. Everything between the opening /* and the closing */ is for human eyes only. No information between /* and */ is translated by the compiler.

    A block comment can span across several lines. For example, the following code is a block comment:

    /* This is my best

    Android app ever! */

  • End-of-line comments

    An end-of-line comment starts with two slashes and goes to the end of a line of type. So in the following code snippet, the text // A required call is an end-of-line comment:

    super.onCreate(savedInstanceState); // A required call

    Once again, no text inside the end-of-line comment gets translated by the compiler.

  • JavaDoc comments

    A JavaDoc comment begins with a slash and two asterisks (/**). For example, in Listing 2-7, the text /** Called at the end of each month */ is a JavaDoc comment.

    A JavaDoc comment is meant to be read by people who never even look at the Java code. But that doesn’t make sense. How can you see the JavaDoc comment in the Listing 2-7 comment if you never look at Listing 2-7?

    Well, a certain program called javadoc (what else?) can find any JavaDoc comments in Listing 2-7 and turn these comments into a nice-looking web page. A page of this kind is shown in Figure 2-5.

image

Figure 2-5: A web page created from JavaDoc comments.

You can generate web pages like the one in Figure 2-5. Here’s how:

  1. In Android Studio’s main menu, choose Tools ⇒ Generate JavaDoc.

    When you do, a dialog box appears. The title of the dialog box is Specify Generate JavaDoc Scope (a slightly awkward title).

  2. In the dialog box’s Output Directory field, enter the name of the directory (on your computer’s hard drive) where you want the new JavaDoc pages to live.

    You can accept the defaults for other items in the dialog box.

  3. Click OK.

    When you do, Android Studio runs the javadoc program to create web pages from the comments in your project. The main page opens in your default web browser.

Notes

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.118.23.147