CS61B: Frequently Asked Questions (FAQ)


Administrative Questions

  1. How are labs and homeworks graded? How do they contribute to the overall grade?
  2. Are there lab and homework solutions?
  3. How do I change my password, or the name listed in emails for my account?


  1. What are the "standard output" and the "standard error"?
  2. What is the "standard input", and what exactly does it mean to reach an "end-of-file" on it?
  3. I have some compiled Java code in a JAR file. How do I get Java to load it?
  4. What are nested classes all about?

Java Language Issues

  1. Can nested classes use "this"? If so, what does it refer to?
  2. Can an enclosing class access the private methods/variables of its nested classes?
  3. When several methods have the same name, how does Java select which is called?
  4. When I compare two strings with "==", I get unexpected results. Why?
  5. What are these unchecked/unsafe operations that the compiler warns me about? Should I worry about them?


  1. When I read the input \\(hello\\) from the terminal into a String variable and then use it as a Pattern, it does not match the String "(hello)". Why not?


  1. How do I save my work on the Subversion repository?
  2. How do I submit an assignment?
  3. When I attempt to commit my files, the commit operation fails, saying "Access denied". What's wrong?
  4. Why would a commit fail with a message such as ".../foo.java: No such file"?
  5. How can I incorporate changes in a staff skeleton file into my own copy?


Administrative Questions

Q: How are labs and homeworks graded? How do they contribute to the overall grade?

A: Please see the first-day informational handout, which is also available on web page.

Q: Are there lab and homework solutions?

A: Yes, we will post them sometime after the due date.

Q: How do I change my password, or the name listed in emails for my account?

A: From your Unix account, log in to update server on an xterm window using ssh update. The name officially listed for your account is under the "Change your Cecos" entry.


Q: What are the "standard output" and the "standard error"?

A: Unix supplies programs with two streams of output to which they can write text. These are called the standard output, which is intended for normal output, and the standard error, which is intended for error, warning, or logging messages. You should observe this convention in your own programs, writing error messages to System.err.

From the point of view of a program, these streams look like ordinary output files. Various programming languages provide different notations and library calls to refer to them. In Java programs, the standard output appears as the variable System.out and the standard error as System.err. Anything written to these (by, say, the printf method) comes out on the respective stream.

By default, both streams go to the terminal (or "console"). Unix shells provide various ways of directing them instead into separate files. Unfortunately, the various shells are inconsistent in how to do this. To run a command FOO (e.g., java solve test1.in), and send the output and error to various destinations:
Desired effect csh-like shell bash-like shell
Std. output -> blah
Std. error -> terminal
FOO > blah FOO > blah
Std. output -> blah
Std. error -> blah
FOO >& blah FOO > blah 2>&1
Std. output -> blah1
Std. error -> blah2
(FOO > blah1) >& blah2 FOO > blah1 2> blah2

You can also redirect the output of FOO to be the input of another command, BAR:
Desired effect csh-like shell bash-like shell
Std. output -> BAR
Std. error -> terminal
Std. output -> BAR
Std. error -> BAR
FOO |& BAR FOO 2>&1 | BAR
Std. output -> BAR1
Std. error -> BAR2
(FOO | BAR1) |& BAR2 (FOO | BAR1) 2&>1 | BAR2

We use all this in the autograder to separate or combine the output and error streams, as needed.

Q: What is the "standard input", and what exactly does it mean to reach an "end-of-file" on it?

A: There seems to be vast confusion about end-of-file in general. The confusion arises from the fact that people have formed an inseparable link in their minds between keyboard input, the "standard input", and System.in (and are unfamiliar with how to make keyboard input "end"). So here's a brief tutorial:
  1. Analogous to what happens with standard output, all Unix programs are supplied with a standard stream of text input called the standard input.
  2. There are no necessary connections between keyboard input, the standard input, and System.in except that by default, the standard input comes from the keyboard and System.in is by default the Java "handle" by which programs access the standard input.
  3. One can obtain the standard input from sources other than the keyboard in Unix by using input redirection or pipes:
    1. The command line
               java foo < SOMEFILE
      runs foo but takes the standard input from SOMEFILE (a file name) rather than the keyboard. This works for any command, not just 'java'.
    2. The command line
               SOMECOMMAND | java foo
      runs SOMECOMMAND (any command) and java foo, taking the standard output from SOMECOMMAND and using it as the standard input for java foo.
  4. Although System.in by default gives a program access to the standard input to the program, you can change this with
            System.setIn (SOMEINPUTSTREAM)
    where SOMEINPUTSTREAM can be any Java expression that yields an InputStream, such as
            new FileInputStream (SOMEFILENAME)
            new StringBufferInputStream (SOMESTRING)
  5. You can, in fact, get end-of-file on keyboard input. On our system by default, the character ^D (Control-D) signals the shell that it should send end-of-file to whatever program is reading from the terminal (the ^D is never transmitted). However, you almost never want to do this. In general, your test input really ought to come from files, so that you aren't constantly retyping it.

Q: I have some compiled Java code in a JAR file. How do I get Java to load it?

A: All classes loaded by a running Java program come from one of the locations indicated by the class path, which is a list of directories and JAR (Jave ARchive) files. JAR files, in effect, are directories full of files all collected into a single ordinary file in such a way that the original constituent files are easily found and extracted. The Java runtime system looks for a class bar in package foo by looking at each item in the class path in turn. If the classpath item is a directory, D Java looks for a file D/foo/bar.class (reverse the slashes on Windows). If the item is a JAR file, Java treats it as a directory and again finds the desired class file in it. Typically, the current directory will be part of the classpath, although it need not be.

Eclipse provides a "Java build path" window under Project->Properties. The Libraries tab on that window will give you an "Add External Jar" selection. In plain UNIX, you add the Jar file to the CLASSPATH environment variable, which is a list of files separated by colons.

Q: What are nested classes all about?

A: Nested classes are "members" of the enclosing class, just as are instance variables, constructors, and methods. They may be public, private, protected, or package private (default). The meaning of public, protected, etc., is exactly the same for classes as it is for instance variables and methods: it determines where else in the program you may mention the name of the member.

Static nested classes are just plain classes, like non-nested ones. The only thing that distinguishes them is where their names can be mentioned, and how they are referred to (class Nested inside class Enclosing is called Enclosing.Nested).

Non-static (inner) nested classes are plain classes with one extra implicit field. For inner class Inner in enclosing class Enclosing, if E is an Enclosing, then new E.Inner (...) is a pointer to a new object of type Enclosing.Inner that has a private instance variable field called Enclosing.this, whose value is E. So, given

    class Enclosing {
        String myName;

        Enclosing (String name) { myName = name; }

        public String toString () { 
           return "Enclosing named " + myName; 

        Inner makeInner (String id) {
           return this.new Inner (id);  
           // OR return new Inner (id) for short ('this.' implied)

        class Inner {
           String innerName; 

           Inner (String name) { innerName = name; }

           public String toString () {
              return "Inner named " + innerName + " connected to "
                     + Enclosing.this;

we could write (in some method somewhere):
        Enclosing e = new Enclosing ("Tom");
        Enclosing.Inner i1 = e.makeInner ("Dick");
        Enclosing.Inner i2 = e.new Inner ("Harry");
        System.out.printf ("e = %s%ni1 = %s%ni2 = %s%n", e, i1, i2);
and see printed
        Enclosing named Tom
        Inner named Dick connected to Enclosing named Tom
        Inner named Harry connected to Enclosing named Tom

Java Language Issues

Q: Can nested classes use "this"? If so, what does it refer to?

A: Nested classes are just classes, and this means the same thing in them as it does in other classes: it applies in instance methods and refers to the "thing to the left of the dot" in the call. That's why we have the odd syntax "Enclosing.this" for use in inner classes to distinguish the "this's". To make life confusing, Java will "helpfully" figure out places where you "must have meant Enclosing.this" and supply it for you. So if in an instance method of Inner, above, you had written
        makeInner ("Jack")

the Java compiler would assume that you must have meant to write

        Enclosing.this.makeInner ("Jack");

Q: Can an enclosing class access the private methods/variables of its nested classes?

A: Yes. The rule on private is "can only be used within the top-level class containing its declaration," which must be (or include) the enclosing class.

Q: When several methods have the same name, how does Java select which is called?

A: In general, Java uses lexical scoping, just like Scheme. That is, a use of an unqualified simple name (i.e., an identifier that is not preceded by '.') may refer to any declaration that's in a declarative region (a class or interface declaration, a {...} block, a method, a for statement, a catch clause, the source file, the package) that contains that use. In addition, package names in the anonymous package, classes and interfaces in the package java.lang, and imported classes and interfaces can sort of be thought of as being in declarative regions that contain the use.

For qualified names, SOMETHING.x, we look for 'x' only within SOMETHING (which may be a package, class, or instance). For this purpose, we count inherited declarations as being in the class or interface that inherits them.

So far, these rules will in general pick out several possible declarations, as in the following completely legal declarations:

     class A {
    //     a
        A A;
    //  1 b

        A A (A A) { return A; }
    //  2 c  3 d           4
        A () { }
    //  e

     class B extends A {
    //               f
        void A () {
    //       g
           A A = A (new A ().A);
    //     7 h   8      9    10

Here, I have marked each use of A with a numeral and each definition with a lower-case letter.

Initially, use #8 might refer to the declarations a (same file); b, c, or e (inherited by class B), g, or h. First, however, we apply syntactic context: use #8 must refer to a method, because it is part of a method call. Therefore, it refers either to declaration c or g. Overloaded methods are disambiguated by means of the argument list, so #8 must refer to c.

Or consider #9. By context, it must refer to a class, which means declaration a, and a constructor within that class, which can only be e.

Since the thing to the left of the dot preceding #10 is an A, #10 must refer to either declaration b, c, or e. Since it is not a method call or constructor invocation, it must refer to b.

Sometimes, these considerations of context or argument lists are not sufficient, as in use #4, which might refer to either b or d. In this case, we defer to the INNERMOST declarative region, which in this case is the method containing use #4. That is #4 refers to d.

Staticness has nothing whatever to do with any of this analysis. Neither does access level (public, private, etc.), with the exception that private declarations are not visible outside their package, which may cut down on the set of possible candidate declarations. (Other access levels, such as default (package private) don't hide declarations; instead you get errors about trying to access non-public things from outside the package. I consider this a small but annoying inconsistency in Java).

Therefore, runtime selection of instance methods by dynamic type is a separate mechanism, and does not participate in determining which declaration the compiler applies to some use. It is only when the program is run that the system actually selects which method to call. It will always be one that has the same signature as the one the compiler selected.

Q: When I compare two strings with "==", I get unexpected results. Why?

A: The == operator always compares values for equality. Since the value of a String expression is a pointer to a String object, this means that == compares pointers, not the contents (character sequences) contained in the objects pointed to. You can construct the same contents two different ways, and get two different objects with the same contents. E.g.,
   x = "Hello, ";

  "Hello, world" != x + "world"
This is semantically consistent, but admittedly confusing. Use the .equals method instead:
  "Hello, world".equals (x + "world")

Q: What are these unchecked/unsafe operations that the compiler warns me about? Should I worry about them?

A: Yes, you should worry. As a general rule, you should treat almost all compiler warnings as if they were errors, because they might be errors. Warnings such as
    Note: foo.java uses unchecked or unsafe operations.
    Note: Recompile with -Xlint:unchecked for details.
in particular mean that you have a construct that cannot be checked until execution time, whereas it is usually checkable at compilation time if the program is written correctly. If you do this:
        ArrayList foo = ...
instead of
        ArrayList<String> foo =
for example, you'll get a warning. You should correct all of these (our pretests often require it, for example). In almost all cases, you can correct them without a problem. For this project, you are likely to find a couple of instances in which you run into a limitation of Java and will have to use the
        @SuppressWarnings ("unchecked")
annotation before a method or constructor. In my project #2, I had two on small methods. If you have any more than that, or if you have to attach it to an entire class, you are probably doing something wrong.

The messages ask you to run javac like this:

    javac -Xlint:unchecked foo.java
as our Makefiles are set up to do. This will give you more details. In Eclipse, you should eliminate all the little yellow warning flags.


Q: When I read the input \\(hello\\) from the terminal into a String variable and then use it as a Pattern, it does not match the String "(hello)". Why not?

A: [Kyle Wecker] The problem here is the difference between the way characters are represented inside a .java file and the way they are recognized through streams (e.g., stdin). When you are typing into a string in a .java file, in order to show that you mean '\', you must type "\\". The reason for this is that backslash is an escape character that isalso used to signal a few other characters (like '\n').

Characters in a stream or reader, on the other hand, are read verbatim, without escape sequences. So backslash is just backslash, and two backslashes are just two backslashes. So, your example is really equivalent to the Java test "(hello)".matches ("\\\\(hello\\\\)"), which is indeed false. The argument to .matches here, coming from a String literal, contains the characters backslash, backslash, left parenthesis, etc.—each pair of backslashes in the literal encodes a single backslash in the resulting String.

To make the confusion worse, backslashes have special significance in Patterns, too. So the Pattern consisting of two backslashes could be input from a file as two backslashes or else written as a String literal with four backslashes, and is interpreted by the Pattern class as matching ONE backslash!


Q: How do I save my work on the Subversion repository?

A: Generally, you'll be developing programs in a working directory that is a copy of a directory in our class repository named LOGIN/trunk/ASSIGNMENT, where LOGIN is your login account name and ASSIGNMENT is the name of the assignment. Although your working directory can have any name, the convention for this class is to call it ~/work/ASSIGNMENT. We'll assume you are currently in this directory, and that ASSIGNMENT is hw1. The command
    svn status
will show you what your Subversion client program (svn) thinks is the status of each of your files in that directory. E.g.,
    % svn status
    A      Progs.java
    ?      Progs.class
    ?      MyUtils.java
    M      HW1Test.java
This tells you that you have told svn to place Progs.java under version control (keep copies of it), but have not yet told the repository about this; that there are files named Progs.class and MyUtils.java that are in the directory but not under version control; and that the file HW1Test.java is in the repository, but the working copy here in the ~/work/hw1 directory has been modified since the last commit operation.

Presumably, you'll want to submit MyUtils.java, so tell svn with

    svn add MyUtils.java
You don't care about keeping copies of Progs.class (and we've set up the repository to refuse them if you do), so now you're ready to send a copy of the indicated files to the repository. The command is
   svn commit -m "Descriptive log message"
(again, we're assuming you are in ~/work/hw1; the commit would also work from ~/work, but would then commit any other directories with outstanding changes as well).

At this point, you will generally want to do

    svn update
as well, which says "Just check the repository to make sure we are up to date with any changes that somebody else is making." There isn't anyone else in this course, but Subversion doesn't know that.

A: First, it's important to keep the repository's copy of the work in your trunk up to date, which we describe here. Assuming you have done so, there are a couple of ways to commit your work. Assume we are handing in hw1. Our preferred method (because it checks that you've really committed everything properly) is
    svn copy -m "Submit HW#1."  \
         https://isvn.eecs.berkeley.edu/cs61b/LOGIN/trunk/hw1 \
After first committing your hw1 to the repository. (Replace LOGIN with your account name. Replace N with a sequence number (1, 2, etc.), so as to keep multiple submissions of hw1 distinct.) The trailing backslash on the first line of svn copy is the line continuation character in Unix. Fortunately, we've set up the class accounts so that you can abbreviate this considerably to:
    svn copy -m "Submit HW#1."  \
         $MYREPOS/trunk/hw1 $MYREPOS/tags/hw1-N 
or even shorter:
    svn copy -m "Submit HW#1." $MYREPOS/{trunk/hw1,tags/hw1-N}
With a Linux/MacOS account at home, you can arrange for $MYREPOS and $STAFFREPOS to mean the same things as on the instructional machines by adding lines to your startup files, such as
   export MYREPOS=https://isvn.eecs.berkeley.edu/cs61b/LOGIN
   export STAFFREPOS=https://isvn.eecs.berkeley.edu/cs61b/staff

A: One common problem is improper copying. If the commands
    cd ~/work/hw1
    svn commit -m "Fill in Progs.java"
are giving you grief, for example, type the command
      svn info ~/work/hw1
and look to see if the URL line says something like
   URL: https://isvn.eecs.berkeley.edu/cs61b/staff/hw1
This tell us that Subversion thinks that the working directory ~/work/hw1 is associated with staff/hw1 in the Subversion repository. What this tells me is that you got this directory originally with
      cd ~/work
      svn checkout https://isvn.eecs.berkeley.edu/cs61b/staff/hw1 ...
or, using our shorthand
      svn checkout $STAFFREPOS/hw1 ...
I've also seen this sort of thing:
      cd ~/work
      mv ~/staff/hw1 hw1
and this:
      cd ~/work
      cp -r ~/staff/hw1 hw1
where you've previously checked out the staff repository into ~/staff. Naturally, we can't allow you to modify the public files, so we've set up Subversion to deny access when you attempt to write to these files.

Instead, to copy files from our staff directory to your trunk, use

      cd ~/work
      svn copy $STAFFREPOS/hw1 hw1
      svn commit -m "Initial version of hw1"
If you do an 'svn info hw1' at this point, you'll see that the URL is something like URL: https://isvn.eecs.berkeley.edu/cs61b/cs61b-yu/trunk/hw1 That is, it's a whole new repository directory under your control.

A: This student did an svn commit and eventually got the message
  svn: Can't copy /home/cc/.../svn/submit/lab3/trunk/BankAccountTest.java'
  No such file or directory
and svn status shows
  A      submit/lab3/trunk
  !      submit/lab3/trunk/IntSequence.java
Those '!'s mean "he used to have this file under version control and now it has vanished mysteriously." Perhaps you mv'ed them out of submit/lab3/trunk to submit/lab3 and then svn added them to submit/lab3. Or perhaps you simply rm'ed them. Either one will do it: the files in your working directory get out of sync with what svn assumes is supposed to be there. When dealing with files A and B under version control, use
    svn move A B
instead of
    mv A B
and use
    svn remove A
instead of
    rm A
And, of course, you'll need to commit those changes at some point.

A: This is called merging in the version-control world. For the projects, we tag copies of each version of a project skeleton that is kept in repository directory .../staff/NAME in directories named tags/NAME-N, where NAME is the project designation, and the N's are sequence numbers. To update your own local version of a project with our changes, use the following steps:
  1. Commit all your current work and update your directory.
  2. Use the following commands to merge in changes (replace HOST appropriately). Choose the proj-N tag that represents the staff version that you are currently using (the one you checked out or last merged into your own files). For projects, we keep track of this version in a file called PUBLIC-VERSION.
        cd ~/work/proj2
        svn merge $STAFFREPOS/tags/proj2-N $STAFFREPOS/proj2 
    [Or, a better use of Unix for the second command:
        svn merge $STAFFREPOS/{tags/proj2-N,proj2} 
  3. You'll be prompted to fix conflicts as they occur.
  4. Use 'svn status' to see if there are any conflicts resulting from this merge (marked with a "C"). These are areas that both you and the staff changed.
    • If there are conflicts, edit each conflicted file to resolve these conflicts (you'll see them clearly marked in the file).
    • Then, for each file, FILENAME that you correct, issue the command
          svn resolved FILENAME
      to tell Subversion that this file is no longer a problem (it won't let you commit otherwise).
  5. Finally, svn commit your directory.
See also our documentation on Using Subversion.