Which of the following method call gives the position of the first occurrence of x that occurs after n th position in the string s1?

JAVA HAS A BUILT-IN TYPE, String, to represent strings of characters. This type differs from the eight primitive types because a value of type String is an object. A String is not just a data value; it also has "methods." (A method is a subroutine that is part of an object.) For example, if str is a variable of type String, you can call the method str.length(), which is a function that returns the number of characters in the string. There's a lot more you can do with strings. This section covers some of the details.

One thing that you cannot do with strings is to use the relational operators <, >, <=, and <= to compare them. You can legally use == and != to compare Strings, but because of peculiarities in the way objects behave, they won't give the results you want. (The == operator checks whether two objects are stored in the same memory location, rather than whether they contain the same value. Occasionally, for some objects, you do want to make such a check -- but rarely for strings. I'll get back to this in a later chapter.) Instead, you should use the methods equals() and equalsIgnoreCase(), which are described below, to compare two Strings.

The String class defines a lot of methods. Here are some that you might find useful. Assume that s1 and s2 are Strings:

  • s1.equals(s2) is a boolean-valued function that returns true if s1 consists of exactly the same sequence of characters as s2.
  • s1.equalsIgnoreCase(s2) is another boolean-valued function that checks whether s1 is the same string as s2, but this function considers upper and lower case letters to be equivalent. Thus, if s1 is "cat", then s1.equals("Cat") is false, while s1.equalsIgnoreCase("Cat") is true.
  • s1.length(), as mentioned above, is an integer-valued function that gives the number of characters in s1.
  • s1.charAt(N), where N is an integer, is a char-valued function that returns the N-th character in the string. Positions are numbered starting with 0, so s1.charAt(0) is the actually the first character, s1.charAt(1) is the second, and so on. The final position is s1.length() - 1.
  • s1.substring(N,M), where N and M are integers, returns a String containing a substring of the characters in s1. The substring consists of the characters in s1 in positions N, N+1,..., M-1. Note that the character in position M is not included.
  • s1.indexOf(s2) returns an integer. If s2 occurs as a substring of s1, then the returned value is the starting position of that substring. Otherwise, the returned value is -1. You can also use s1.indexOf(ch) to search for a particular character, ch, in s1. To find the first occurrence of x at or after position N, you can use s1.indexOf(x,N).
  • s1.compareTo(s2) is an integer-valued function that compares the two strings. If the strings are equal, the value returned is zero. If s1 is less than s2, the value returned is -1, and if s1 is greater than s2, the value returned is 1. (If the strings consist entirely of lowercase letters, then "less than" and "greater than" refer to alphabetical order.)
  • s1.toUpperCase() is a String-valued function that returns a new string that is equal to s1, except that any lower case letters in s1 have been converted to upper case. There is also a method s1.toLowerCase().
  • s1.trim() is a String-valued function that returns a new string that is equal to s1 except that any non-printing characters such as spaces and tabs have been trimmed from the beginning and from the end of the string. Thus, if s1 has the value "fred  ", then s1.trim() is the string "fred".

For the methods s1.toUpperCase(), s1.toLowerCase() and s1.trim(), note that the value of s1 is not changed. Instead a new string is created and returned as the value of the function. The returned value could be used, for example, in an assignment statement such as "s2 = s1.toLowerCase();".

Here is another extremely useful fact about strings that I haven't mentioned so far: You can use the operator + to concatenate two strings. The concatenation of two strings is a new string consisting of all the characters of the first string followed by all the characters of the second string. For example, "Hello" + "World" evaluates to "HelloWorld". (Gotta watch those spaces, of course.)

Even more surprising is that you can concatenate values belonging to one of the primitive types onto a String using the + operator. The value of primitive type is converted to a string, just as it would be if you printed it to the standard output. For example, the expression "Number" + 42 evaluates to the string "Number42". And the statements

TextIO.put("After "); TextIO.put(years); TextIO.put(" years, the value is "); TextIO.put(principal);

can be replaced by the single statement:

TextIO.put("After " + years + " years, the value is " + principal);

Obviously, this is very convenient. It would have shortened several of the examples used earlier in this chapter.

You can even use the += operator to add something onto the end of a String. For example, if you want to read a sequence of letters from standard input and store them in a String, you could do it like this:

String str = ""; // start with an empty string char ch = TextIO.getChar(); // read one character while ( (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ) { // ch is a letter, so append it to the string // and read the next character. str += ch; // (note: same as str = str + ch;) ch = TextIO.getChar(); } // end of while loop End of Chapter 2

Page 2

ONE WAY TO BREAK UP A COMPLEX PROGRAM into manageable pieces is to use subroutines. A subroutine consists of the instructions for carrying out a certain task, grouped together and given a name. Elsewhere in the program, that name can be used as a stand-in for the whole set of instructions. That is, as a computer executes a program, whenever it encounters a subroutine name, it executes all the instructions necessary to carry out the task associated with that subroutine.

Subroutines can be used over and over, at different places in the program. A subroutine can even be used inside another subroutine. This allows you to write simple subroutines and then use them to help write more complex subroutines, which can then be used in turn in other subroutines. In this way, very complex programs can be built up step-by-step, where each step in the construction is reasonably simple.

As mentioned in Section 2.6, subroutines in Java can be either static or non-static. This chapter covers static subroutines only. Non-static subroutines, which are used in true object-oriented programming, will be covered in the next chapter.

Sections in Chapter 3:


Page 3

WHEREAS A SUBROUTINE represents a single task, an object can encapsulate both data (in the form of instance variables) and a number of different tasks or "behaviors" related to that data (in the form of instance methods). Therefore objects provide another, more sophisticated type of structure that can be used to help manage the complexity of large programs.

This chapter covers the creation and use of objects in Java. It also discusses the object-oriented approach to program design.

Sections in Chapter 4:


Page 4

JAVA IS A PROGRAMMING LANGUAGE DESIGNED for the world of modern networked computers. Java programs are meant to be downloaded over a network to run on any computer that implements the Java virtual machine. Java is fast becoming an integral part of the World Wide Web, the most interesting and fastest-growing Internet service, in the form of "applets" that can be directly embedded into Web pages.

A Java applet uses a GUI (graphical user interface), in which the user interacts with components such as buttons, menus, and text input boxes. User interactions with these components generate events, and an applet is programmed by specifying how it should respond to the various kinds of events that can be generated. An applet that wants to carry out some activity, such as an animation, independently of user events can create a separate thread to do so. Similar GUI's can be used in stand-alone applications as well as in applets.

This chapter covers some of the basics of applets, graphics, and GUI's. There is a section about the Web and about HyperText Markup Language (HTML), the language used for writing Web pages. I've also included a long section covering threads and animation. While threads are often used to animate applets, they have much wider use beyond the context of GUI's. The discussion of applets and GUI's will continue in the next chapter with a more complete discussion of components and events.

Sections in Chapter 5:


Page 5

MOST COMPUTERS TODAY HAVE A Graphical User Interface (GUI). With a GUI, the user interacts with the computer through windows, buttons, menus, and other components which are drawn on the screen. There are several different GUI's, for different types of computers. Although each GUI has its own look-and-feel, they all have certain features in common, and these common features make it possible to write platform-independent programs that use a GUI.

The Java packages java.awt and java.awt.event contain classes for writing programs that use a graphical user interface. The previous chapter introduced several of these classes, including the class Button. An object of type Button represents a push-button that the user can click on to perform some action. When the programmer creates an instance of this class, it will appear on the screen as a button appropriate to the platform on which the program is running. Even though the button will appear different on different platforms, its "logical" or "abstract" behavior will be the same. The Java programmer only has to worry about this abstract behavior; the platform-dependent details are left to the Java implementation on each platform. This is why the Java GUI system is called the Abstract Windowing Toolkit (AWT).

This chapter continues the study of GUI programming that was begun in the previous chapter by looking at a much wider selection of components, events, and layout managers. Section 4 introduces a new Java language feature, nested classes, that is useful for event-handling but that can be very useful in other contexts as well. Section 5 shows how a graphical user interface can be used in standalone applications, rather than just in applets. The final section of the chapter looks at how events were handled in the original version of Java, Java 1.0. The Java 1.0 event model can still be used in Java 1.1, and might even be more convenient than the Java 1.1 model in some cases.

Sections in Chapter 6:


Page 6

COMPUTERS GET A LOT OF THEIR POWER from working with data structures. A data structure is an organized collection of related data. An object is a type of data structure (although it is in fact more than this, since it also includes operations or methods for working with that data). However, this type of data structure -- consisting of a fairly small number of named instance variables -- is only one of the many different types of data structure that a programmer might need. In many cases, the programmer has to build more complicated data structures by linking objects together. But there is one type of data structure that is so important and so basic that it is built into every programming language: the array.

An array is a data structure consisting of a numbered list of items, where all the items are of the same type. In Java, the items in an array are always numbered from zero up to some maximum value. For example, an array might contain 100 integers, numbered from zero to 99. The items in an array can be objects, so that you could, for example, make an array containing all the Buttons in an applet.

This chapter discusses how arrays are created and used in Java. The last section introduces several other data structures that are available as standard classes in Java.

Sections in Chapter 7:


Page 7

IT IS AN UNFORTUNATE TRUTH that sometimes when programs are running, errors occur. There are programming errors, such as an array index that is out of the actual range of indices for the array or an attempt to divide a number by zero. Then there are errors over which the programmer has less control or none at all, such as when the user types in a word when the program is expecting a number or when the system runs out of memory.

Often, when an error occurs, the program simply crashes (or worse, goes on to produce incorrect results). However, Java provides a neat mechanism for handling errors and other "exceptional conditions." This exception-handling capability is one of the topics of this chapter. The other topic is Java's built-in input/output facilities, which are implemented through objects called Streams, Readers and Writers. It turns out to be impossible to use these objects without some understanding of exceptions.

Sections in Chapter 8:

  1. Exceptions, try, and catch
  2. Streams, Readers, and Writers
  3. Files
  4. Networking

Page 8

WHEN I WROTE THE FIRST VERSION OF THESE NOTES in 1996, Java was still a very new programming language. Although it had already caused a lot of excitement, it's long-term prospects were not entirely clear. Now, in the middle of 1998, I think it is clear that Java is an important language and will remain so for the long term. However, it is true at least for now that most "serious" programming is done in C and C++. Fortunately, these languages share a lot of features with Java. The older language, C, has no object-oriented features. C++ is a much larger language, which extends C with classes, objects, and other features. This chapter serves as a brief introduction to C++ for someone who already knows Java. The coverage here is very incomplete, and is meant only as a starting point for learning about C++.

You'll find that a lot of the basics ("programming in the small") are almost identical in Java and C++. However, both the programming philosophy and the large-scale structure of programs ("programming in the large") in C++ are quite different from Java.

Sections in Chapter 9: