CS1: Lecture 6 – String
Dear students,
We have been looking at the computer’s role as a calculator, but we will deviate from this theme today. Numbers are not the only thing that computers are good at crunching. They are also really good at crunching communication. They can send out our words (and propaganda) as fast as electricity travels. So, today we’ll talk about text. We introduce the String
class, which stands for a String
of characters.
Char
Last time we built a catalog of seven different types: boolean
for true/false values; byte
, short
, int
, and long
for whole numbers; and float
and double
for real-ish numbers. There’s an eighth type for holding two-byte Unicode characters: char
.
We can declare and assign a char
variable just like the others, except we must surround char
literals in single-quotation marks:
char c = '/';
Only one character is allowed between the quotation marks. If we want more, we’ll have to use a different type, which we’ll see in a moment.
Primitive vs. Objects
First, we should make it clear that there are two types of citizens in Java: primitives and objects. Primitives are the dregs of society, they are simple numbers or letters or trues or falses. Their type names are all lowercase. Objects are bigwigs, having their type names capitalized. We create them in slightly different ways:
Type myObject = new Type(...); type myPrimitive = ...;
We also act upon them in different ways. Primitives are bullied about with operators like +
and %
. Objects are deferentially asked to do things through their methods:
prim1 + prim2 + prim3 // operators object.pleaseDeleteAllMyFiles() // method call
So, we can make this analogy:
operators : primitives :: methods : objects
The data type of an object is its class
. We’ve formally met one object class so far: Scanner
. Now it’s time to meet String
.
String
Based on our discussion above, we create a String
like this:
String name = new String("Frank Lee");
The thing is, we use String
s so often, the Java folks have allowed us to say it more compactly:
String name = "Frank Lee";
The String
class provides a handful of useful methods for dealing with text:
length() charAt(int i) substring(int from) substring(int from, int to) indexOf(char c) lastIndexOf(char c) equals(Object that) startsWith(String prefix) endsWith(String prefix) isEmpty() contains(String that)
Additionally, Scanner
provides two methods for retrieving text: next
, which grabs the next “word” of the input between whitespace boundaries; and nextLine
, which grabs the next line of input.
Exercises
We’ll discuss how String
s are laid out in memory, how we can index into them, extract substrings and so on, through a few example problems:
- You ask the user for a credit card number. Print it back to the console with all but the last four digits as asterisks.
- Students and teachers get a discount at your website. How can you tell if someone’s a student or teacher?
- You ask 125 people for their UWEC username—and username only. All of them append
@uwec.edu
anyway. How can you clean up one such input? - You are writing a MUD and want to respond only to the commands
north
,south
,east
, andwest
. But the players are entering in all sorts of perversions of this likeNORTH
andeast
(with trailing spaces). How can you “canonicalize” their input to what you expect? - Display at most 10 characters of a customer’s first name.
- Ask the user for a mod problem (
100 % 3
) and compute its value.
Static vs. Instance
Notice that calling methods on String
s is different than calling methods of the Math
class:
char first = name.charAt(0);
double score = Math.floor(points);
In the case of length
, we call this method on an instance of the String
class. There may be many instances of String
s in our program, and length
will give back a different result for each one. With floor
, there’s no instance of Math
. We call it directly on the class.
This difference is what static
refers to. Math.floor
is a static
method. String.charAt
is not.
If something is static, like static electricity, it is not moving. It is in stasis. The Math
class is not moving behind the scenes. String
s, however, are a moving target, as each String
will have different contents.
Casting
We’ve got four integer types and two floating point types. Sometimes we need to move data from one type to another. Whether that’s legal or not depends on the direction you are going in this ladder:
String
double
float
long
int
short
byte
If you are going from a lower type to a higher type, then you can freely transition. This is called an upcast. For instance, let’s store a byte
in an int
:
byte b = 100;
int i = b;
But if you go the other direction in a downcast, you face the potential loss of information. The higher types can store a broader range of numbers that might not fit in the smaller type. The Java compiler requires that we sign off on this potential information loss with a cast:
int i = 10000;
byte b = (byte) i;
Promotion
Sometimes casting happens automatically. Consider this code:
int radius = 2;
int area = Math.PI * radius * radius;
This doesn’t compile. Math.PI
is a double
, and as soon as you involve a double
in an operation, we’re going to get a double
result. There’s no explicit cast, but there’s an implicit one. This is called promotion.
TODO
Here’s your TODO list of things to complete before next class:
- CS 145, be sure to complete lab 1 before lab tomorrow. We will mark checkpoints only the first 10 minutes of tomorrow’s lab.
- CS 145, lab 2 is posted. You are invited to complete it early.
- Read about The Git Sandwich and Updating SpecCheckers to ensure a healthy Git experience.
See you next class!
P.S. It’s time for a haiku!
Words and computers
They’re natural companions
Like lightning and drought
P.P.S. Here’s the code we wrote together in class…