Which is better? 26-Jul-16

advertisement
Which is better?
26-Jul-16
Which is better?

Assume s1 and s2 are Strings:
A. if (s1 == s2) { ... }
B. if (s1.equals(s2)) { ... }
?
2
Answer: B



s1 == s2 tests whether s1 and s2 reference the
same string; s1.equals(s2) tests whether they
reference equal strings
String s1 = "ABC";
String s2 = s1;
String s3 = "ABC";
String s4 = "AB" + "C"
All these strings are equal; but s4 is in a different
memory location than the others, so the == test
yields false
3
Which is better?

Assume s1 is a String:
A. if (s1.equals("OK")) { ... }
B. if ("OK".equals(s1)) { ... }
?
4
Answer: B


s1.equals("OK") sends a message to s1 asking if it is
equal to "OK"
"OK".equals(s1) sends a message to "OK" asking if it
is equal to s1


This is legal, because "OK" is a String
If s1 is null, then:
s1.equals("OK") gives a NullPointerException
"OK".equals(s1) gives false
5
Which is best?

Assume int numbers[ ] = new int[100];
A. for (int i = 0; i < 100; i++)
numbers[i] = i;
B. for (int i = 0; i <= 99; i++)
numbers[i] = i;
C. for (int i = 0; i < ARRAY_SIZE; i++)
numbers[i] = i;
D. for (int i = 0; i < numbers.length; i++)
numbers[i] = i;
?
6
Answer: D

D is best: for (int i = 0; i < numbers.length; i++)


C is OK: for (int i = 0; i < ARRAY_SIZE; i++)


Changing ARRAY_SIZE will fix this loop if array size is changed
B is poor: for (int i = 0; i < 100; i++)



numbers.length changes automatically if array size is changed
Uses a “magic number”
Must track down and change each occurrence if array size is changed
A is worst: for (int i = 0; i <= 99; i++)




This has all the same problems as B
B is more traditional and therefore less “surprising”
The array size is 100, not 99, so it’s more obvious where the number came from
 You have to do some arithmetic to get 99
If you change the array size, a search for 100 won’t find the loop that uses 99
7
Which is better?

Assume finished is a boolean variable:
A. if (finished == true) {...}
B. if (finished) {...}
?
8
Answer: B

finished == true is redundant:



If finished is true, then finished==true will be true
If finished is false, then finished==true will be false
The extra words don’t gain you anything



finished==true might seem more readable to a beginner, but
you quickly learn to read the shorter form
Brevity in programming, as in writing, is a virtue
You can avoid the possible mistake of saying
if (finished = true) { ... }
9
Which is better?

Assume foo, bar, and larger are integers
A. if (foo > bar) larger = foo;
else larger = bar;
B. larger = foo > bar ? foo : bar;
?
10
Answer: neither


For each of these, you have to look at the code carefully
to make sure it is correct
larger = Math.max(foo, bar);
is easier to read and more obviously correct
11
Which is better?
A. String s = "Hello";
B. String s = new String("Hello");
?
12
Answer: A


"Hello" is special syntax to implicitly construct a string
String s = new String("Hello"); actually constructs
two strings: "Hello" constructs the first string, then it is
given as a parameter to an explicit constructor, which
constructs the second string
13
Which is better?

Suppose p is a Panel with a BorderLayout and
okButton is a Button:
A. p.add(okButton, BorderLayout.NORTH);
B. p.add(okButton, "North");

Note: BorderLayout.NORTH == "North"
?
14
Answer: A


p.add(okButton, BorderLayout.NORTH); is
strongly recommended over the shorter form
p.add(okButton, "North") -- but why?
Answer: The former gives better error detection


If you type p.add(okButton, "north"), there is no error, but
it doesn’t do what you want
If you type p.add(okButton, BorderLayout.North) you
will get a syntax error, because BorderLayout has no such
variable as North
15
Which is best?

Suppose n is an int and s is a String:
A. s = Integer.toString(n);
B. s = String.valueOf(n);
C. s = new Integer(n).toString();
D. s = n + "";
?
16
Answer: D

I prefer D (s = n + ""; ) because:



It’s a common idiom, therefore easily recognized
It’s short
It works for any type
17
Which is best?

Assume n is an integer:
A. if (n < 0) n = 0;
B. if (n < 0)
n = 0;
C. if (n < 0) {
n = 0;
}
?
18
Answer: C

If, later on, you want to add a statement, it’s easy to
make this mistake with B:


if (n < 0)
System.out.println("n was " + n);
n = 0;
You won’t make this mistake with A or C


With C (using braces), you don’t have to change anything
that’s already there
However, A (all on one line) is often convenient
19
Which is better?

Assume n is an integer:
A. int factorial = 1;
for (int i = 2; i < n; i++) {
factorial *= n;
}
B. int factorial = 1;
int i;
for (i = 2; i < n; i++) {
factorial *= n;
}
?
20
Answer: A

In most cases, you don’t care about the index of a for
loop outside the loop



You typically give it an initial value in the loop
You typically already have its final value in some variable or
by some simple computation
If you don’t need a variable, you shouldn’t have that
variable

It doesn’t help anything, and it might get in the way
21
Which is better?
A. int search(int[] array, int target) {
for (int i = 0; i < array.length; i++) {
if (array[i] == target) return i;
}
return -1;
}
B. int search(int[] array, int target)
throws NotFoundException() {
for (int i = 0; i < array.length; i++) {
if (array[i] == target) return i;
}
return new NotFoundException();
}
?
22
Answer: A


Exceptions should be used for exceptional cases, not for
normal program control
In almost all cases, not finding something in an array
search is one of the expected outcomes
23
Which is better?
A. private void combinations(int n, int t)
throws InvalidArgumentException {
if (t < 0 || t > n) {
throw new InvalidArgumentException();
...
B. private void combinations(int n, int t) {
assert t >= 0 && t <= n;
...
?
24
Answer: B

The method is marked private, so you (the person
writing this class) will be the only one using this
method


If you call it incorrectly, it’s a bug, not just an unexpected
external event, and should be fixed, not tested for
Besides, using an assert statement is a lot less work
25
Which is better?
A. class Line {
public Point start;
public Point end;
public double length;
...
}
B. class Line {
public Point start;
public Point end;
public int length() {...};
...
}
?
26
Answer: B

Two main reasons:

The DRY principle says: Don’t repeat yourself



The length variable makes the object vulnerable to
inconsistent changes



The length variable is a subtle kind of repetition; its value is
determined by the start and end points
Whenever you have the same information represented in two places,
you have the extra requirement to keep them consistent
If some external agency changed only the start or the end point, the
length variable would become incorrect
The length method would continue to give correct results
If efficiency is a critical issue, use setters and getters
27
Which is better?

You need to write a class which splits input lines into fields:
A. class Split {
public Split(InputStreamReader reader) // constructor
public void readNextLine() throws IOException {...}
public int numFields() {...}
public String getField(int fieldNumber) {...}
}
B. class Split {
public Split(String line) {...} //constructor
public int numFields() {...}
public String getField() {...}
}
?
28
Answer: B

The second SplitLines class just splits lines; it isn’t
concerned with where the lines come from

The first version can only split lines that come from an input
stream, and is therefore less versatile
29
Conclusions


There are various ways to do things
One way may be better than another because:




It’s easier to read and understand
It’s more familiar—the way things are usually done
It’s less error prone, or provides better error detection
It’s more efficient

This is a good reason when the savings are dramatic enough to be
noticable
30
The End
31
Download