JAVA vs C++
http://pages.cs.wisc.edu/~hasti/cs368/JavaTutorial/
Contents
In Java, every variable, constant, and function (including main) must be inside some class. Here's a simple example program:
class Test { public static void main( String [] args ) { System.out.println("Hello world!"); } }
Things to note:- There is no final semi-colon at the end of the class definition.
- Function main is a member of class Test.
- In general, main must:
- Be inside some class (there can be more than one main function -- there can even be one in every class!)
- Be public static void.
- Have one argument: an array of String. This array contains the command-line arguments. You can use args.length to determine the number of arguments (the number of Strings in the array).
- To write to standard output, you can use either of the following:
System.out.println( ... ) System.out.print( ... )
The former prints the given expression followed by a newline, while the latter just prints the given expression.Like the C++ <<>
System.out.print("hello"); // print a String System.out.print(16); // print an integer System.out.print(5.5 * .2); // print a floating-point number
The + operator can be useful when printing. It is overloaded to work on Strings as follows:
If either operand is a String, it
- converts the other operand to a String (if necessary)
- creates a new String by concatenating both operands
Example
int x = 20, y = 10; System.out.println("x: " + x + "\ny: " + y);
The output is:x: 20 y: 10
This is because the argument to println is an expression of the form:- op1 + op2 + op3 + op4
The only operator is +, so the expression is evaluated left-to-right (if there were another operator with higher precedence, the sub-expression involving that operator would be evaluated first). The leftmost sub-expression is:
- "x: " + x
- "x: 20"
Evaluation of the argument to println continues, producing as the final value the String shown above (note that \n means the newline character):
x: 20 y: 10
Assume the following declarations have been made:
int x = 20, y = 10;What is printed when each of the following statements is executed?
System.out.println(x + y); System.out.println(x + y + "!"); System.out.println("printing: " + x + y); System.out.println("printing: " + x * y);
C++ Files vs Java Files
A C++ programmer deals with source files, object files, and executable files:
Source Files: .h and .cc (or .cpp or .C)
created by: you (the programmer) contain : C++ source code two kinds : .h (header files) contain class definitions and function specifications (just headers - no bodies) must be included by every file that uses the class / calls the functions .cc contain implementations of class member functions and "free" functions, including the main function
Object Files: .o
created by: the compiler, when called w/ -c flag; for example: g++ -c main.cc compiles main.cc creating main.o contain : object code (not executable) source code is compiled, but not linked/loaded
Executable Files
created by: the compiler (no -c flag) contain : executable code Code is compiled if necessary, then linked and loaded. These are the files that you can actually run, just by typing the name of the file. name : default = a.out any other name is possible via the -o flag; for example: g++ main.o -o test creates an executable named "test"
A Java programmer deals with source files and bytecode files (no executable files):
Source Files: .java
created by : you (the programmer) contain : Java source code (one or more classes per file) restrictions : (1) each source file can contain at most one public class (2) if there is a public class, then the class name and file name must match Examples If a source file contains the following: public class Test { ... } class Foo { ... } class Bar {... } then it must be in a file named Test.java If a source file contains the following: class Test { ... } class Foo { ... } class Bar {... } then it can be in any ".java" fileSmall digression:
- Every function must be part of a class.
- Every class is part of a package (packages are discussed in a later set of notes.).
- A public class can be used in any package.
- A non-public class can only be used in its own package.
Bytecode Files: .class
created by: the Java compiler contain : Java bytecodes, ready to be "executed" -- really interpreted -- by the Java interpreter names : for each class in a source file (both public and non-public classes), the compiler creates one ".class" file, where the file name is the same as the class name Example If a source file contains the following: public class Test { ... } class Foo { ... } class Bar {... } then after compiling you will have three files: Test.class Foo.class Bar.class
Here's how to compile and run the example "hello world" program given above, assuming that it is in a file named "tst.java":
- to compile the source code, type: javac tst.java
- to run the interpreter using the name of the class whose main function you want to run, type: java Test
Remember, when compiling a program, you type the full file name, including the ".java" extension; when running a program, you just type the name of the class whose main function you want to run.
Write a complete Java program that uses a loop to sum the numbers from 1 to 10 and prints the result like this:
The sum is: xxxNote: Use variable declarations, and a for or while loop with the same syntax as in C++.
Make sure that you are able to compile and execute your program!
Java Types
In Java, there are two "categories" of types: primitive types and reference types:
- Primitive Types
boolean | same as bool in C++ |
char | holds one character |
byte | 8-bit signed integer |
short | 16-bit signed integer |
int | 32-bit signed integer |
long | 64-bit signed integer |
float | floating-point number |
double | double precision floating-point number |
- Reference Types
arrays |
classes |
Notes:
- no struct, union, enum, unsigned, typedef
- arrays and classes are really pointers!!
C++ Arrays vs Java Arrays
- In C++, when you declare an array, storage for the array is allocated. In Java, when you declare an array, you are really only declaring a pointer to an array; storage for the array itself is not allocated until you use "new":
C++ int A[10]; // A is an array of length 10 A[0] = 5; // set the 1st element of array A JAVA int [] A; // A is a pointer to an array A = new int [10]; // now A points to an array of length 10 A[0] = 5; // set the 1st element of the array pointed to by A
int [] A = {1, 222, 0}; // A points to an array of length 3 // containing the values 1, 222, and 0
Type | Value |
boolean | false |
char | '\u0000' |
byte, int, short, int, long, float, double | 0 |
any pointer | null |
int [] A = new int[10]; ... A.length ... // this expression evaluates to 10 A = new int[20]; ... A.length ... // now it evaluates to 20
Write a Java function called NonZeros, using the header given below. NonZeros should create and return an array of integers containing all of the non-zero values in its parameter A, in the same order that they occur in A.
public static int[] NonZeros( int [] A )
Write a complete Java program that includes a main function as well as the NonZeros function. The main function should test NonZeros by creating several arrays, and calling NonZeros with each array. It should print the array it passes to NonZeros as well as the returned array. So for example, when you run your program, your output might look like this (if your NonZeros function is implemented correctly):
passing [0,1,2,3,2] got back [1,2,3,2] passing [0,0] got back [] passing [22,0,-5,0,126] got back [22,-5,126] passing [1,0] got back [1]
Note that the destination array must already exist (i.e., new must already have been used to allocate space for that array), and it must be large enough to hold all copied values (otherwise you get a runtime error). Furthermore, the source array must have enough values to copy (i.e., the length of the source array must be at least srcPos+count). Also, for arrays of primitive types, the types of the source and destination arrays must be the same (so for example, you cannot copy from an array of int to an array of double or vice versa). For arrays of non-primitive types, System.arraycopy(A, j, B, k, n) is OK if the assignment B[0] = A[0] would be OK.
The arraycopy function also works when the source and destination arrays are the same array; so for example, you can use it to "shift" the values in an array:
int [] A = {0, 1, 2, 3, 4}; System.arraycopy(A, 0, A, 1, 4);After executing this code, A has the values: [0, 0, 1, 2, 3].
int [][] A; // A is a two-dimensional array A = new int[5][]; // A now has 5 rows, but no columns yet A[0] = new int [1]; // A's first row has 1 column A[1] = new int [2]; // A's second row has 2 columns A[2] = new int [3]; // A's third row has 3 columns A[3] = new int [5]; // A's fourth row has 5 columns A[4] = new int [5]; // A's fifth row also has 5 columns
For each of the following code fragments, fill in the number of the picture that best illustrates the value of A after the code executes, or fill in "error" to indicate that executing the code causes a runtime error. (In the pictures, a diagonal line indicates a null pointer.)
Code | Corresponding Picture or Error |
int [] A; | |
int [] A = new int [4]; | |
int [][] A = new int[4][3]; | |
int [][] A = new int[4][];
A[1] = new int[4]; A[3] = new int[2]; | |
int [] A = new int[4];
int [] B = {0,1,2,3,4,5,6,7,8,9}; System.arraycopy(B,2,A,0,4); | |
int [] A = new int[4];
int [] B = {2,3,4}; System.arraycopy(B,0,A,0,4); | |
int [] A = new int[4];
int [] B = {0,1,2,3,4,5,6,7,8,9}; System.arraycopy(B,8,A,0,4); | |
int [] A = {1,1,1,1};
int [] B = {2,2,2}; System.arraycopy(A,0,B,1,2); System.arraycopy(B,0,A,0,3); | |
int [] A = new int[4];
int [] B = {0,1,2,3,4,5,6,7,8,9}; System.arraycopy(B,0,A,0,10); | |
int [][] A = new int[4][3];
int [] B = {1,2,3,4,5,6,7,8,9,10}; System.arraycopy(B,0,A[0],0,3); System.arraycopy(B,1,A[1],0,3); System.arraycopy(B,2,A[2],0,3); System.arraycopy(B,3,A[3],0,3); |
(1) | (2) | (3) |
(4) | (5) | (6) |
(7) | (8) | (9) |
(10) | (11) | (12) |
(13) | (14) | (15) |
C++ Classes vs Java Classes
- In C++, when you declare a variable whose type is a class, storage is allocated for an object of that class, and the class's constructor function is called to initialize that instance of the class. In Java, you are really declaring a pointer to a class object; no storage is allocated for the class object, and no constructor function is called until you use "new". Assume that you have defined a List class as follows:
class List { public void AddToEnd(...) { ...} ... }
C++ List L; // L is a List; the List constructor function is called to // initialize L. List *p; // p is a pointer to a List; // no list object exists yet, no constructor function has // been called p = new List; // now storage for a List has been allocated // and the constructor function has been called L.AddToEnd(...) // call L's AddToEnd function p->AddToEnd(...) // call the AddToEnd function of the List pointed to by p JAVA List L; // L is a pointer to a List; no List object exists yet L = new List(); // now storage for a List has been allocated // and the constructor function has been called; // note that you must use parentheses even when you are not // passing any arguments to the constructor function L.AddToEnd(...) // no -> operator in Java -- just use .
Aliasing Problems in Java
The fact that arrays and classes are really pointers in Java can lead to some problems:
Problem 1: Simple assignment causes aliasing:
Java code conceptual picture (all empty boxes contain zeros) +--+ +---+---+---+ int [] A = new int[3], A: | -|-----> | | | | +--+ +---+---+---+ B = new int[2]; +--+ +---+---+ B: | -|-----> | | | +--+ +---+---+ +--+ +---+---+---+ A[0] = 5; A: | -|-----> | 5 | | | +--+ +---+---+---+ +--+ +---+---+---+ B = A; A: | -|-----> | 5 | | | +--+ +---+---+---+ ^ +--+ | B: | -|-------+ +--+ +--+ +---+---+---+ *** NOTE ** B[0] = 2; A: | -|-----> | 2 | | | the value of A[0] +--+ +---+---+---+ changed, too! ^ +--+ | B: | -|-------+ +--+
Problem 2: In Java, all parameters are passed by value, but for arrays and classes the actual parameter is really a pointer, so changing
- an array element, or
- a class field
void f( int [] A ) { A[0] = 10; // change an element of parameter A A = null; // change A itself } void g() { int [] B = new int [3]; B[0] = 5; f(B); *** B is not null here, because B itself was passed by value *** however, B[0] is now 10, because function f changed the first element *** of the array }In C++, similar problems can arise when a class that has pointer data members is passed by value. This problem is addressed by the use of
For each of the following Java code fragments, say whether it causes a compile-time error, a run-time error, or no error. If there is an error, explain why.
1. int A[5]; 2. int [] A, B; B = 0; 3. int [] A = {1,2,3}; int [] B; B = A; 4. int [] A; A[0] = 0; 5. int [] A = new int[20]; int [] B = new int[10]; A = B; A[15] = 0;
Type Conversion
Java is much more limited than C++ in the type conversions that are allowed. Here we discuss conversions among primitive types. Conversions among class objects will be discussed later.
Booleans cannot be converted to other types. For the other primitive types (char, byte, short, int, long, float, and double), there are two kinds of conversion: implicit and explicit.
Implicit conversions: An implicit conversion means that a value of one type is changed to a value of another type without any special directive from the programmer. A char can be implicitly converted to an int, a long, a float, or a double. For example, the following will compile without error:
char c = 'a'; int k = c; long x = c; float y = c; double d = c;For the other (numeric) primitive types, the basic rule is that implicit conversions can be done from one type to another if the range of values of the first type is a subset of the range of values of the second type. For example, a byte can be converted to a short, int, long or float; a short can be converted to an int, long, float, or double, etc.
Explicit conversions: Explicit conversions are done via casting: the name of the type to which you want a value converted is given, in parentheses, in front of the value. For example, the following code uses casts to convert a value of type double to a value of type int, and to convert a value of type double to a value of type short:
double d = 5.6; int k = (int)d; short s = (short)(d * 2.0);Casting can be used to convert among any of the primitive types except boolean. Note, however, that casting can lose information; for example, floating-point values are truncated when they are cast to integers (e.g., the value of k in the code fragment given above is 5), and casting among integer types can produce wildly different values (because upper bits, possibly including the sign bit, are lost). So use explicit casting carefully!
Fill in the table below as follows:
- If the declaration will compile as is, put a check in the second column, and write the value of the declared variable in the last column.
- If the declaration will not compile as is, but can be made to compile by adding an explicit cast, rewrite the declaration with the correct explicit cast in the third column, and write the value of the declared variable in the last column.
- If the declaration will not compile, and cannot be fixed by adding an explicit cast, put a check in the fourth column.
Declaration | Correct | Rewrite with cast | Never correct | Variable's value |
double d = 5; | X | 5.0 | ||
int k = 5.6; | ||||
long x = 5.4; | ||||
short n = 99999; | ||||
int b = true; | ||||
char c = 97; | ||||
short s = -10.0; |
Solutions to Self-Study Questions
Test Yourself #1
System.out.println(x + y); ==> 30 System.out.println(x + y+ "!"); ==> 30! System.out.println("printing: " + x + y); ==> printing: 2010 System.out.println("printing: " + x * y); ==> printing: 200
Test Yourself #2
class Test { public static void main( String[] args ) { int sum = 0; for (int k=1; k<=10; k++) sum += k; System.out.println("The sum is: " + sum); } }
Test Yourself #3
class Test { public static int[] NonZeros( int[] A ) { // count # nonzero values int nonz = 0; for (int k=0; k
Test Yourself #4
CODE CORRESPONDING PICTURE ---- --------------------- int [] A; 9 int [] A = new int[4]; 6 int [][] A = new int[4][3]; 3 int [][] A = new int[4][]; A[1] = new int[4]; A[3] = new int[2]; 1 int [] A = new int[4]; int [] B = {0,1,2,3,4,5,6,7,8,9}; System.arraycopy(B,2,A,0,4); 14 int [] A = new int[4]; int [] B = {2,3,4}; System.arraycopy(B,0,A,0,4); error int [] A = new int[4]; int [] B = {0,1,2,3,4,5,6,7,8,9}; System.arraycopy(B,8,A,0,4); error int [] A = {1,1,1,1}; int [] B = {2,2,2}; System.arraycopy(A,0,B,1,2); System.arraycopy(B,0,A,0,3); 12 int [] A = new int[4]; int [] B = {0,1,2,3,4,5,6,7,8,9}; System.arraycopy(B,0,A,0,10); error int [][] A = new int[4][3]; int [] B = {1,2,3,4,5,6,7,8,9,10}; System.arraycopy(B,0,A[0],0,3); System.arraycopy(B,1,A[1],0,3); System.arraycopy(B,2,A[2],0,3); System.arraycopy(B,3,A[3],0,3); 10
Test Yourself #5
int A[5]; Compile-time error: Can't specify array dimension in a declaration. This is C/C++ syntax. int [] A, B; B = 0; Compile-time error: Incompatible type for =. Can't convert int to int[]. B is an array reference, not an int, and 0 is not equiv to null as in C/C++. int [] A = {1,2,3}; int [] B; B = A; No errors. int [] A; A[0] = 0; Compile-time error: Variable A may not have been initialized. The array was never allocated. int [] A = new int[20]; int [] B = new int[10]; A = B; A[15] = 0; Runtime error: ArrayIndexOutOfBoundsException: 15 A now references the same array as B, which only has length 10
Test Yourself #6
Declaration Correct Rewrite with cast Never correct Variable's value ------------------------------------------------------------------------------ double d = 5; X 5.0 int k = 5.6; int k = (int) 5.6 5 long x = 5.4; long x = (long) 5.4 5 short n = 99999; short n = (short) 99999 -31073 int b = true; X char c = 97; X 'a' short s = -10.0; short s = (short) -10.0 -10
No comments:
Post a Comment