Part 0: Setup & some background reading

In your CS department Unix home directory, create a directory named ic211. Inside that directory, create a directory lab01 (you can nest it inside a lab directory if you like!). Inside the lab01 directory is where all the files you create for this lab will reside.

The structure of a simple Java program
It's worth taking a second to compare the simplest programs in C++ and Java. Note that they do nothing!
Ex0.cpp —The Simplest C++ Program Ex0.java — The Simplest Java Program
int main()
{
  return 0;
}
public class Ex0
{
  public static void main(String [] args)
  {
    return;
  }
}

The source code for the simplest C++ programs consist of

  1. a file named something.cpp
  2. that defines a function int main().
Interestingly, since there can be only one definition for a given function prototype in a program, two such files can never be used together in the creation of a new program. Already we see how reuse of code can be problematic!

The source code for the simplest Java program consists of

  1. a file named is something.java
  2. that consists solely of the definition of a public class named something   ← i.e. it matches the file name!
  3. that defines a member function public static void main(String[] args).   ← Note: member functions are called methods in Java parlance.
Two such files can be used together as parts of a new program because the full name of the function main(String[] args) defined in the class Something is actually Something.main(String[] args), so that main functions defined in different classes technically have different names ... no conflict! Already we see how the format of a Java program makes reusing and combining code easier!

Note: It is not the case that public static void main(String[] args) has to be the only member function (or, as Java programmers prefer, method) in the class definition. You can add more function/method definitions in your class just as you would add multiple function definitions in your .cpp file while writing a C++ program.

Creating, Compiling and Running HelloWorld in Java
Is Java a compiled language or an interpreted language? Yes! Java is compiled because you run the Java compiler (javac) to translate source code (.java files) into lower-level code (.class files). It's also interpreted, because .class files do not contain machine instructions to be executed by the physical computer, but instead contain instructions for the Java Virtual Machine (JVM), which is itself just a program — i.e. the JVM is an interpreter for the low-level language (called Java bytecode) contained in the .class files.

Let's look at how to compile and run the Java version of everybody's friend: Hello World.

Use an editor to create the file HelloWorld.java containing the source code for the program. Java source code files are plain ol' text files, just like C++ source code. No magic there!
Note that the print statement
System.out.println("foo");
is really not that different from cout << foo;, because, although you've likely been blissfully unaware of this, the long version of the C++ statement is
std::cout.operator<<("foo");
... which maps pretty nicely to the Java version.
Use a compiler (javac) to translate the human-readable Java source code into the class file HelloWorld.class, which containins Java bytecode, the language the JVM interprets. Run the JVM (java) and have it execute the code in the .class file. In particular, it calls the function:
public static void main(String[] args) 
... from the class whose name matches the name of the file. In this csase, because the file is named HelloWorld.class, the JVM will execute the main function defined in the class HelloWorld. If no such class exists, or no such function appears in the class, you get an error.

Step 1. Writing/Compiling/Running Java code

  1. Using your favorite text editor (as long as it's emacs or vi) put the following Java code into a file named Lab1a.java:
    public class Lab1a 
    {
      public static void main(String[] args) 
      {
            
      }
    }
    Note: The name of the file must be exactly Lab1a.java. Yes, upper-case vs. lower-case matters!
  2. Add the following to the main method:
      int[] x = new int[10];
      int k = 0;
      while(K < 10) {
         x[k] = k*k;
         k++;
      }
      for (int j = 0; j < 10;j++) {
         System.out.println(j + " squared is " + x[j]);
      }
    What do you think it will do when run?
  3. Now it is time to compile this program. You do this by typing the command
    javac Lab1a.java
    (javac = "java compiler"). If you typed it in exactly as above, you should have gotten an error. Take a look at it, and notice how helpful javac is being. Fix the error.
  4. Recompile the program (so you got no errors). If you type
    ls
    you'll notice a new file, Lab1a.class, which is the bytecode to be run by the java interpreter. Run the interpreter on your program with the command
    java Lab1a
  5. Modify the program by replacing the while loop with a for loop. Compile it and run it again.

Step 2. Your first Program

  1. Make a new file called Lab1b.java. Write the lines you need to write to make it a Java program.
  2. Add the line
    import java.util.*;
    at the very top of the file saying This is like #include <iostream> in C++. It allows us to use the Scanner class.
  3. Add the following code to main. Run to see what it does:
    Scanner in = new Scanner(System.in);
    System.out.print("Please input an integer ");
    int n = in.nextInt();
    System.out.print("Please input a second integer ");
    int k = in.nextInt();
    System.out.println("The two ints were " + n + " and " + k);
  4. What happens if you type your name instead of an integer? Try it! What you should see is that the JVM prints out the call stack, i.e. the stack of function call records as it appeared when the error occurred. One nice feature of an interpreted language is that when a run-time error occurs, the interpreter can tell you all sorts of things about the state of the program when the error occurred. This is really nice. For programs running on the CPU, the only information you get when a run-time error occurs is a message like "seg-fault".
  5. Scanner is a class that is part of Java's utility package (java.util). A package is "roughly" analogous to a C++ library. Scanner is used to facilitate reading information from an input stream. In this case, we are reading from System.in which is that standard input stream. In order to use the Scanner class, you have to import the java.util package. That's the purpose of the 'import' line of the file.
  6. Did you know that if you want to play a simple lottery where there are n possible numbers (the number of balls), and you have to pick k of them, then your odds of winning are 1 in (n * (n-1) * (n-2) * ... * (n-k+1))/k!, where ! means "factorial". If not, don't worry. Your discrete math course will teach you these kinds of things. Just accept this formula for purposes of the lab.
  7. Anyway, modify your program so that it reads in the n and k, and computes that value. You should be able to do this with code that (not counting I/O) looks just like C++.
  8. You may wonder what else the Scanner class can do. The Scanner class, and much of the rest of what is built into Java, is described in your book. Documentation for the complete "Java API", i.e. descriptions of all packages/classes that are part of the language standard, is available online: Java 6 API Documentation. To find Scanner, look under java.util.*, and it is alphabetical from there (alternatively, google for "java scanner"). You'll notice a long list of functions included in the Scanner class. Which one do you think will read in a whole line? What type does it return? Change your code so that before the integers are entered, the user enters his/her name, and this is printed back to him in the final println() command.
  9. Add a function which takes an int and returns the factorial of that integer. Place that function immediately before the main function, i.e. still inside the class definition. Functions (for now) should start with the magic incantation public static, otherwise they look just like C++ functions. Note that, unlike C++, there are no function prototypes separate from function definitions. Test your function before continuing on.
  10. Add another function which, given n and k from the above program, returns the product n*(n-1)*...*(n-k+1).
  11. Modify your main function to use these two new functions to calculate and output the odds from the above section.

Step 3. Your second program

The following line creates a pseudo-random number generator, seeded on the current time in milliseconds.
Random rand = new Random(System.currentTimeMillis());
After that point, every time we call rand.nextInt(k), where k must be an int, it will return a random number between 0 (inclusive) and k (exclusive). Random, by the way, is in java.util, and has a lot more interesting functions you can see in your book.

Write a program that generates a random number between 0 and 10 (inclusive!), and then asks the user for a guess until they get it correct. The more violent the berating on each wrong guess, the better. Code this in a file called Lab1c.java.