| Practice Final Exam (PDF) | |||||||||||||||||||||||||||||||
| 1. E | We
are looking for the situation where the expression !(a && b) &&
(a || b) evaluates to true. In order to get a true result when we have
an &&, we must have both sides evaluate to true; this means
that !(a && b) must be true, or if we remove the negation,
that (a
&& b) must evaluate to false. Likewise, (a || b) must also evaluate
to true. Let's draw a table to look at this:
We can see that in order to have (a && b) evaluate to false, we must either have both values false, or one false and the other true. In order to have (a || b) evaluate to true, we must either have both values true, or one false and one true. The only options that match for both tables are to have one value true and one false - so choice E is the answer. |
||||||||||||||||||||||||||||||
| 2. C | Note that based on the curly braces, the outer for loop has as its body the inner for loop. For the inner for loop, its body is the first print statement. The second println() statement therefore won't execute until all the printing of the asterisks is finished. Knowing this, we can get the answer with multiplication - for every time that the outer loop runs, the inner loop will do a complete cycle of 5. This means we will have 10 sets of 5, or a total of 50 asterisks printed, followed by the println(). | ||||||||||||||||||||||||||||||
| 3. A | In a switch statement, you should recall that once any case is matched, all the code from that point downward will execute unless a break statement is encountered, which stops the code execution. The problem with the code as written is that it has no break statements; therefore, if case 1 matches (the number is odd), both statements will print. To fix it, we need to have odd numbers print that statement, then stop - so we should include a break statement at the end of line 2, following the print statement. | ||||||||||||||||||||||||||||||
| 4. E | To
evaluate these segments of code, you should try them with each of the
three cases and see how they differ. Suppose x = 0 when the code begins...
Segment 1 will have the while loop fail right away - x is NOT > 0 -
and it will then print "x = 0". Segment 2 will begin by decrementing
x to -1, then the test happens, it fails, and the loop ends. The print
statement will therefore print "x = -1" - NOT the same between
the two segments. Suppose x = 1 when the code begins... Segment 1 will have the test in the while loop succeed, so x is decremented to 0, then the test is done again, and now it fails (0 is NOT > 0). The print statement will print "x = 0". In segment 2, beginning with x = 1, it initially decrements x to 0, then tests for x > 0, and the test fails. It will then print "x = 0", so these two segments have done the same thing. Suppose x = -1 when the code begins... Segment 1 will test and fail, then print "x = -1". Segment 2 will decrement x to -2, then do the test and fail, and it will print "x = -2". Again we have a difference between segments. When we look at the answer choices, we see that option E lists both the first and third condition - so it is our answer. |
||||||||||||||||||||||||||||||
| 5. A | We can determine the parameters that the method needs by simply looking at what is or is not put into the parens when the method is called. In this case, we have empty parentheses, so the method does not take any arguments. This eliminates choices B, D, and E, all of which state there are arguments. This leaves options A and C. We can also note that there is an int variable declared, and that it is receiving an assignment from the method - so the method must return an int. This eliminates option C, and the correct answer is A. | ||||||||||||||||||||||||||||||
| 6. D | Note that we're using the 'next' array to get the indices of the elements we add onto the sum from the 'val' array. We begin with i = 2, so we add val[2], or 4, to the sum. i then changes to next[2], or 4. We get val[4], or 1, and add it to the sum, and then change i to next[4], or 5. We get val[5], or 3, and add it to the sum, and change i to next[5], or 1. We get val[1], or 2, and add it to the sum, and change i to next[1] or 0. At this point, the test for ( i != 0 ) that we have been doing in this loop fails, so the loop ends. Adding these up, we have 4 + 1 + 3 + 2 = 10, so the correct answer is Choice D. | ||||||||||||||||||||||||||||||
| 7. E | Choice A doesn't list the types of the variables, so it is not legal. Choice B tries to put the size of the array inside the square braces, but we don't do that when we list the array name, so it also is not legal. Choice C has two arguments and lists their types, but the second name contains an illegal character for a variable name: '+'. Choice D lists two variables with a type, but you are not allowed to list them with commas in a method declaration. Therefore, none of the options are legal and the answer is choice E. | ||||||||||||||||||||||||||||||
| 8. B | Remember
that a linear search begins at the start of the array, and continues one
by one through the elements to the end. A linear search can be done on
any array, sorted or not, but we're told that this array is sorted. A
binary search requires a sorted array, which we have. It begins by looking
at the middle element. If that is not the item we want, it tests whether
the desired item is greater than or less than the middle, and discards
the part of the array where the item won't be found. The subarray then
has its middle element checked, and if it doesn't match the item we want,
we repeat the process. If the value is not in the array, the binary search will be faster, because larger parts of the array are eliminated each time. If the element is the last element, we'll get to it sooner because the parts are eliminated more quickly. If the element is the middle element, a binary search will find it on the first test. However, if the item is the first element in the array, a sequential search will test the first element to begin, and will find it immediately - so the answer is choice B. |
||||||||||||||||||||||||||||||
| 9. A | We've spoken about the Java principle of data abstraction - making variables (or data members) private and methods public - as a means of making code easier to maintain and to modify. This doesn't necessarily affect the efficiency, and it doesn't impose any restrictions on making methods public or private, but it DOES allow us to change the names and data types of variables without requiring changes to code which uses the class - so choice A is the answer. | ||||||||||||||||||||||||||||||
| 10. B | To solve this problem, you'll simply need to work through the code line by line. We begin in main by creating n and setting it to 3. Next the method fum is called and passed the values 3 and 6, which are copied into the method's parameter (local) variables n and b. Inside the method the two values are multiplied together, then the result stored back inside n. The second statement in the method increments n by 1, and the third statement returns the value in n, which is 19 - so the result printed is 19 and the answer is choice B. | ||||||||||||||||||||||||||||||
| 11. D | Choice A combines the two strings into a third String using concatenation, which will work fine. Choice B tests to see if both String variables point to the same String object - testing with '==' checks memory addresses of objects, rather than contents. However, this also will work fine, and will print if they are indeed the same. Choice C compares the length of the two Strings, again a fine thing to do and one that won't cause any errors. Choice E first converts String s1 to upper case, then asks for the index of the String "blah". If the String is upper case, a lower-case String won't be found, but it won't cause an error. Choice D asks for the character at s1.length - however, we know that Strings index from 0 to length - 1, so this request will cause a StringIndexOutOfBoundsException, and the answer is D. | ||||||||||||||||||||||||||||||
| 12. C | This is similar to our situation in Choice B of the preceding question. As long as objects are of the same type, we can assign one variable to point to the same object that the other one points to. This is what the line of code in problem 13 does. Therefore, we can eliminate choices A and B, as there is no error caused. Choice D is incorrect - using the assignment operator for the object's reference variable doesn't change the contents of an object. Choice C is the correct answer - and this eliminates choice E. | ||||||||||||||||||||||||||||||
| 13. B | Choice A is not legal, because we can't put the size of an array into the left side of the declaration. Choice C tries to do the same thing, just changes the order slightly. Choice D fails to include the square brackets on the left side of the declaration, and they are required. Choice B is correct Java code - which rules out Choice E. | ||||||||||||||||||||||||||||||
| 14. | The
content of array foo [] after this loop is: [1, 0, 2, 0, 0, 0,
4, 1, 0, 1]. The lines of code split off one digit at a time
using remainder, and count the number of occurrences of the various
digits. |
||||||||||||||||||||||||||||||
| Problem 15 |
| (a) You are asked to first find three errors in the code and fix
them.
The first error is that the battingAvg() method returns
a double, but it is adding together int values, and then dividing
them by an int, the atBats variable. This is integer division,
and is most likely not really what we want here. To fix this
error, you must cast one side or the other of the return statement
to a double (which automatically will promote the other part): return (double) (singles + doubles + triples + homeruns) / atBats; The other two errors are in the constructor. For the second error, a constructor should NOT have a return type declared, since it makes the new object and assigns it to its variable, so the word void should be deleted. For the third error, you have a parameter variable called 'name', and you have an instance variable (at class scope) called 'name', so the statement in the constructor, name = name; does not do what it is intended to do. In order to access the instance variable called 'name' from inside the method, we must use the keyword, 'this'. Then we can assign the argument to it. The resulting code will be: this.name = name; |
| (b) You
are also asked to write the atBats() method as an instance method
for the class. To do so, you should take a look at the problem
details, the method description, and the program in main
with its sample output to see what the method is doing. The problem
tells us that when a player is atBat(), the player makes a hit
or an out, and that the hits are added up and divided by the
total number of atBats to get the batting average. In the description,
we're told that the method is called whenever a player goes to
bat. We are also told how the numeric argument is intended
to function, to indicate what the player scored. In main, we see the method called by an object, and taking a number as a parameter. Then there is a final print statement about the batting average. When we look at the output, we see only one statement about a bad argument being passed, then the batting average statement. So we know the method only prints something when it's given an illegal value. What do we gather from all of this? The method does not need to return anything, but takes an int argument. Inside the method, it needs to count the total number of atBats the player has, as well as managing the counts for what happens during each of them - whether the player got a homerun, a double, a triple, etc. Finally, the method also needs to test for valid input, and print an error message if it is given bad data. Given all of this, our method might look like the following:
public void atBats( int hitType )
{
// count the particular type of hit and check for bad data
switch( hitType ) {
case 0: break;
case 1: singles++; break;
case 2: doubles++; break;
case 3: triples++; break;
case 4: homeruns++; break;
default: System.out.println( "Bad arg -- " + hitType +
" -- passed to method atBat!!" );
return; // leave the method after a bad arg
}
atBats++;
}
|
| Problem 16 |
In
this problem you are asked to fill in some lines for a recursive
method to print stars. You are given the following code:
public void writeStars( int n )
{
if( n == 0 ) {
// fill in missing statement(s)
}
else {
// fill in more missing statement(s)
}
}
When we deal with recursion, the two things we need to have absolutely
clear are a base case, when the answer is known and can simply be returned
without further calculation, and a recursive case, which can be gradually
reduced until it will eventually reach the base case. It is common in
a recursive method (as is done here) to first test for the base case,
then go to the recursive case. So if our method is printing stars, then
the simplest case is when there are 0 starts left to print - we can print
a newline to close the row of stars, and that's all that's needed.This leaves the recursive case to write. We know that we need to print 'n' stars, and that we want 'n' to become smaller and smaller until it reaches 0, our base case. Therefore, in the else, we should print one of the stars, and then call the method recursively to print the remaining 'n - 1' stars. These two items can be done in either order. As we keep printing 'n - 1' stars, we'll get to the point where 'n - 1' comes to equal 0. Therefore, the finished version of the method looks like this:
public void writeStars( int n )
{
if( n == 0 ) {
System.out.println();
}
else {
System.out.print("*");
writeStars( n - 1 );
}
}
|
| Problem 17 |
In
this problem you are shown the bubblesort() method we discussed
in lecture, which sorts arrays of int values. However, we would
like to change it so that it will work for Strings, which should
be sorted into alphabetical order. You are also told about the
compareToIgnoreCase() method, with examples of what the method
returns, and we see that if the String in the implicit argument
(calling the method) is alphabetically later than the String in
the explicit argument, they need to be swapped. With this info,
you should be able to identify the three places where the code
will need to be changed, and to make the required updates:
// 1. NOTE that we've change the array type in the parameter to a String array, not ints
static void bubblesort( String [ ] a, it size )
{
for( int i = 1; i < size; i++ )
{
for( int j = size - 1; j >= i; j++ )
{
// 2. NOTE that we've changed the test from a simple ">" to use the method recommended
// When the object calling the method is "greater than" the parameter, the value returned
// will be greater than 0, according to the documentation
if( a[j - 1].compareToIgnoreCase( a[j] ) > 0 )
{
// 3. NOTE that we've changed the temp variable to a String rather than an int
String temp = a[j - 1];
a[j - 1] = a[j];
a[j] = temp;
}
}
}
}
|