6 Weeks in Review
This is only the beginning of our sixth week of Java and Object-Oriented Programming, but we have already covered a lot of ground. Today's lesson is going to review the ealier topics. Most of it will hopefully make more sense now that you have better context for understanding it.
Comparing Java to C
By now you have had several weeks of experience in Java. You should have some feel for how it compares to C in terms of:
- usability
- friendliness of the compiler
- online documentation
- compartmentalization
We have not run a side-by-side speed test of the two languages, however most people generally agree that Java is faster to develop, but C runs faster.
One of the biggest design mistakes that Software Engineers make is to automatically select the language they are most comfortable with for any project. You should instead pick the one that will meet the requirements for the least cost. That is why it is important to understand each language's relative strengths and weaknesses.
Java compiler
- The compiler we use is named 'javac'
- Inputs a source code file with the extension .java
- Outputs byte-code that can run on any JVM
- Output files have the extension '.class'
- You can compile on one OS and run the .class files on another, e.g. Windows -> Linux
Java Virtual Machine
- We run java programs with the command 'java' plus the name of the class to run
- 'java' runs the JVM
- JVM Reads a .class file
- The JVM looks for an runs a 'public static void main(String[])' function in the .class file.
- The Java 'interpreter' It converts the bytecode into commands that can run on the JVM. The phrases 'JVM' and 'interpreter' are often used interchangably, but technically the interpreter is a part of the JVM.
- A JVM on any OS can read the same bytecode from a .class file. The JVM will convert the commands into something that can be run on the local processor.
File name conventions
You should be able to answer any of the following question. Hover the mouse over them to see the correct answers.
- If a file is named 'HelloWorld.java', what must be the name of its outer class?
- What is the full command to compile HelloWorld.java to bytecode?
- What file does this produce?
- What is the full command to run the bytecode?
Every program in Java requires a class
Every program in Java must have a class. That is a design decision that was made by the developers.
Decades later this decision is still controvertial. Some people say that Java takes OOP a step too far by insisting that it be used everywhere. Other people point out that since every program uses OOP, we do not have to worry about learning two different sets of syntax.
The lesson here? People like to argue. Computer scientists especially. Whether you believe that Java uses too many classes or too few, we need to understand how its classes work. Let's take a closer look at our HelloWorld program:
1 public class HelloWorld {
2 public static void main(String[] args) {
3 System.out.println("Hello, World!");
4 }
5 }
This seems like a lot of code to print two words. In reality, it is one line of code to print "Hello, World". The remaining lines (1,2,4,&5) are the minimum lines required for any Java program. Let's break them down one at a time:
- Line 1 creates a public class. The class name matches the file name. This lets the compiler ('javac') and the JVM ('java') know what class to look for inside the files. Note that "HelloWorld" is the "outer" class in the file. This class may also include inner "nested classes" that do not' match the file name. We saw one of these in HW3.
- Line 5 ends the outer class. Nothing may be defined after the description of the outer class ends. You cannot create a second class after it.
- Line 2 is the "public static void main(String[])" method. This line is required for any class that you want to run from the command-line: e.g. "java HelloWorld" -> runs the main() method. You do not have to put a main() method in yoru classes, but they will not run. Take a look at the classes you created for Lab03. The Point.java and Line.java did not have main() methods, but they compiled just fine. Try to run them with "java Point" or "java Line" and see what happens. Add a proper main() method and they will run.
- BLUF - when you run "java HelloWorld", the JVM immediately looks for a public static void main(String[]) method and runs whatever code it contains. If you import the class as a library, you do not need main().
Primitive Java variables
"Primitive" types are predefined by the language and identified by named keywords. All primitives except for char "signed". Here are are eight primitives:
| Type | Size in Bits | Min | Max |
|---|---|---|---|
| byte | 8 | -128 | 127 |
| short | 16 | -32,768 | 32,767 |
| int | 32 | -2,147,483,648 | 2,147,483,647 |
| long | 64 | -9,223,372,036,854,775,808 | 9,223,372,036,854,775,807 |
| float | 32 | 1.40e-45 | 3.40e+38 |
| double | 64 | 4.94e-342 | 1.80e+308 |
| boolean | Undef. | false | true |
| char | 2 (unsigned) | Unicode 0 | Unicode 65,535 |
| Data Type | Default Value |
|---|---|
| byte | 0 |
| short | 0 |
| int | 0 |
| long | 0L |
| float | 0.0f |
| double | 0.0d |
| boolean | false |
| char | '\u0000' |
| Any Object (incl. String) | null |
Conversion from one primitive variable type to another
Explicit conversion: Casting from one type to another.
Explicit conversions are allowable as long as the user specifies them in a cast statement.
Implicit conversions are allowable whenever there is no possible loss of precision.
Explicit Conversion Examples:
double d = 1.0d;
float f = (float)d // Explicit conversion (cast); Allowed by compiler
The following example is an implicit cast that fails:
double d = 1.0d;
float f = d // Error: possible loss of precision. Implicit cast fails
The following example is an implicit cast that succeeds:
float f = 1.0f // Correct definition for a float
double d = f; // Implicit conversion allowed; No possible loss of precision
Note that you use the trailing characters in the right column to indicate the type for a numeral. If you do not, then the numeral will default to a type of int or double:
float a = 1.0f; // Correct definition for a float
float a = 1.0d; // Error: possible loss of precision; Implicit cast from double to float
float a = 1.0; // Error: possible loss of precision; Assumes 1.0 is a double
float a = 1; // Implicit cast to float succeeds; Assumes 1 is an int
Note that the user is responsible for ensuring precision is not lost during an explicit conversion.
Strings
Strings are a type of class object specified in java.lang.
Strings are not primitive data objects in Java. Note that the word "String" does not highlight like "int" or "float" in most editors.
The complete definition for class String can be found here
Each character us stored in a 16-bit char.
Strings are immutable - once created, they cannot be changed. Wouldn't it be more useful to have a String that can be modified? There are similar classes that can be modified, such as StringBuffer and StringBuilder.
Reserved Keywords
Reserved keywords cannot be used as variable or method names.
They generally show up as a special color in editors.
Take a look at the following lines. Which ones compile?
float a = 1.0f; // Compiles as expected
float int = 1.0f; // Does not compile - 'int' is reserved, cannot be used as a variable name
float String = 1.0f; // Compiles; 'String' is now a variable of type float with value == 1.0f
Arrays
An array is a collection of Objects or primitives. The size of an array must be specified when it is created:
int[] intArray1 = new int[10];
int[] intArray2;
intArray1[5] = 99; // Compiles, since intArray1 has a size of 10.
intArray2[5] = 99; // Error: intArray2 is a null pointer. Needs a call to 'new' to use a pointer.
The immutable size of Arrays can be a problem. If you need an array whose size changes while the program runs, try the ArrayList.
Arrays can be multi-dimensional:
int[][] x = new int[10][20];
int[][][][][] y = new int[10][20][30][40][50];
x[0][0] = 1;
y[0][0][0][0][0] = 1;
Custom Classes
The code below shows you how to create and use a class:
class Point {
float x, y;
public Point(float a, float b) {
x = a;
y = b
}
}
...
Point p = new Point(1.0f, 2.0f);
A class variable is actually a pointer. It defaults to a value of 'null' unless you create an object with new and point the pointer to it. The following line will fail:
Point p;
p.x = 3.0f; // p is a null pointer. There is no Point object allocated.
Pass-by-Value vs. Pass-by-Reference
There are two ways of passing a variable to a method in most languages: by 'Value' and by 'Reference'.
Java always uses 'Pass-by-Value'. But (why is there always an exception?) sometimes methods act like they are Pass-by-Reference.
Primitive data types use 'pass-by-value'. This makes a copy of the data. If the method changes the copy, that does not change the original variable.
Objects also use 'pass-by-value', BUT only the pointer gets passed by value. Since the pointer points to the original data object, a method may modify the original data. However, the method may not change the original pointer.
The result is behavior that sometimes looks like pass-by-reference, and sometimes like pass-by-value. It is easier to understand with an example:
Consider the following code:
public class Point {
float x, y;
public Point(float a, float b) {
x = a;
y = b;
}
}
...
public class Pass {
// Does not change the value of the original int
public static void testPrimitive(int i) {
i = 99;
}
// Changes the value of the original Point.
public static void testObject1(Point p) {
p.x = 99.0f;
}
// Does not change the value of the original String
public static void testObject2(String s) {
s = "Goodbye";
}
public static void main(String[] args) {
int int1 = 0;
System.out.println("Before: int1: " + int1);
testPrimitive(int1);
System.out.println("After: int1: " + int1);
Point point1 = new Point(0,0);
System.out.println("Before: point1.x: " + point1.x);
testObject1(point1);
System.out.println("After: point1.x: " + point1.x);
String mystr = "Hello";
System.out.println("Before: mystr: " + mystr);
testObject2(mystr);
System.out.println("After: mystr: " + mystr);
}
}
Here is the output:
Before: point1.x: 0.0 After: point1.x: 99.0 Before: int1: 0 After: int1: 0 Before: mystr: Hello After: mystr: Hello
The best way to understand this is to compile a few examples and experiment for yourself.
Like ideas in computer science, this one is controversial. Try Googling "Java pass by reference" if you want to read online arguments full of abusive language on this topic.
Format for 6-week exam
This is a three-part exam:
- Written portion. Closed book, no electronics. Short answer, multiple-choice, True/False, writing small code examples from scratch with no reference.
- Written portion. Closed book, no electronics. Debugging code and modifying code samples.
- Practical programming exercise. Using lab workstation. Open book, Internet search engines are available. You can use the Internet, the only restrictions are that you cannot log into any website or service, and you cannot post messages anywhere. This is to prevent communication with programmers or other students. You can browse to any page that does not require a login or password, and you can read any page as long as you do not send any messages.