/* A BRIEF C++ TO JAVA TUTORIAL Chuck Liang Hofstra University Computer Science Revision of November, 2001 This short, informal tutorial is designed to allow students who are already familiar with C++ to begin writing programs in Java as quickly as possible. It is not intended to be a comprehensive guide to the Java language. Those who wish to write substantial Java applets and applications should consult full-scale references. I mainly address the *intersection* of C++ and Java here. Most advanced features are left out. This document contains real Java source code. To compile this file on Hofstra University's Sun workstations, first set your path to jdk1.2 with setenv PATH /usr/java1.2/bin:$PATH setenv CLASSPATH ./ ( put these lines in your .cshrc file to make them permanent ) Save this file as "quickcj.java" - the file name is important (see below). Type "javac quickcj.java" to compile the program. Type "java quickcj" to run it. The program that will be executed will be the last example of this tutorial, which is uncommented. JDK, or "java developer's kit", is a free java environment available from Sun. Procedures for compilation and execution in jdk are similar on all platforms. This document is available at www.cs.hofstra.edu/~cscccl/cs123/quickcj.java ---- FIRST EXAMPLE The Java programming language was invented as a simplification, or "cleaning up" of C++. Syntactically, the two languages are very similar. (There are however, many fundamental differences underneath.) Let's start by looking at a simple java program. The lines are numbered in comments (comments are inserted in the same way as C++). // start of program public class firstprog // 1 { // 2 private int factorial(int n) // 3 { int i; // 4 int answer = 1; for(i=2;i<=n;i++) // 6 answer = answer * i; return answer; // 8 } private int rfact(int n) // 10 { if (n<2) return 1; else return n*rfact(n-1); // 12 } public static void main(String[] args) // 14 { firstprog prog = new firstprog(); int m = 5; // 16 System.out.println("The factorial of " + m + " is " + prog.factorial(m)); System.out.println("With the recursive version it's also " + prog.rfact(m)); } // 19 } // end of class firstprog (note: no ";" at the end of classes) // end of program The first thing you should notice is that everything is inside a class definition. Java is *more* object oriented than C++, which retains many aspects of the non-object oriented C language. All code must be inside classes. There can be more than one class defined in the same file, but only one class in any file can be prefixed "public", as on line 1. The sole public class will contain the "main" function (or "method"), which must be prefixed "public static void". The main function is the entry point of the entire program, as in C++. The argument to main is an array of strings representing optional command line arguments. ( In C/C++ they would be main(int argnum, char* args[]) ). What's more, the file that contains this program *must* be called "firstprog.java" - it must correspond to the name of the one public class. Note that all elements of a class (functions as well as variables) must be predicated with "public", "private", (or "protected"), as opposed to C++, which lets you predicate entire sections (e.g, "public:"). The meaning of the "public", "private" and "protected" modifiers are the same as in C++. If an explicit modifier is omitted, the item defaults to being "public". With the exception of the "private" predicate, the definitions of factorial and rfact (iterative and recursive versions of the factorial function) are the same as they would be in C/C++. Because even "main" is part of a class, you must define an *instance* of the class before you can call any of its functions (factorial and rfact). This is the purpose of the first line of main, which defines "prog" to be an instance of the "firstprog" class. Note that the functions "factorial" and "rfact" are called as elements of the "prog" object. I will discuss further how classes and objects are defined in the next section, but it is necessary to emphasize that using classes is NOT A CHOICE in java: you MUST use them! Simple console output is accomplished with System.out.println. The C++ equivalent of line 17 would be cout << "The factorial of " << m << " is " << factorial(m) << endl; The "+" symbol in Java is used for string concatenation. It automatically converts numbers (m) into printable string form (as with cout). If you don't want to automatically print a carriage return at the end of the line, use System.out.print (as opposed to ...println). Note also that the end of the class definition do not have a ";", as is required in C++ class definitions. OBJECTS, JAVA STYLE So far the differences between java and C++ we've seen are mostly syntactic. From now on we'll be dealing with more important differences. Let's take a closer look at classes and objects in Java. I've always thought that a bank account offers the simplest example of a class: public class secondprog { public static void main(String[] args) { account myaccount = new account(200.0,1); // "account" defined below account youraccount = new account(300.0,2); // note "new" used myaccount.withdraw(30.0); youraccount.deposit(40.0); // etc ... } } // end of public class secondprog class account { private double balance; // 64 bit floating point number private int accountId; // a real account will contain more info public account(double b, int id ) // constructor { balance = b; // sets initial balance accountId = id; } public void deposit(double ammount) { balance = balance + ammount; } public void withdraw(double ammount) { if (ammount >= balance) balance = balance - ammount; } } // end of class account // end of program Notice that the account class comes *after* the public class, where it is referred. This is not possible in C++ without a prototype or header file. Java, on the other hand, allows for "forward referencing", which just means that elements (variables, functions and classes), can be defined after the point in the file where they're used. This is an advanced language feature that was not commonly available when C/C++ was standardized. What other differences are there compared to a C++ class? A WHOLE LOT!! The most important difference is that ALL OBJECTS ARE REFERENCED THROUGH POINTERS (repeat this to yourself 100 times) In the above program, the expression "myaccount.withdraw(30.0)" would be written in C++ as "myaccount->withdraw(30.0)". In Java, there is a fixed convention for pointers. All variables of primitive type, such as int, char and double, are direct variables (non-pointers). All complex data, including arrays, strings and all class instances, can only be defined using pointers. I emphasize that this is a fixed convention: you can not just put a "&" in front of an int variable to make it into a pointer. The use of pointers in Java is more restricted. Because of this fixed convention, you do not use "*" and "->" to indicate that pointers are being used. They are IMPLICIT, since all variables that represent objects are pointers (that's why I used "new" to create the objects). Thus the syntax is misleading if you read the above program as a C++ program. "A.B" in Java corresponds to "A->B" in C++. The C++ expression "A.B" has no equivalent in Java. This point is so important that I will say it again: ****** REALLY IMPORTANT!!! ****** In Java all variables of primitive type are non-pointers, and all variables of class type are pointers. The "*", "&" and "->" symbols are not used in Java. "A.B" in Java corresponds to "A->B" in C++. The C++ expression "A.B" has no equivalent in Java. ******* DON'T FORGET!!! ******* Class inheritance has the following syntax in Java: class savings_account extends account { ... } Whereas in C++ you would have written class savings_account : account { ... }; You may not define a method for a class outside of the class. That is, in C++ we often do void classname::methodname() {...}. This is not possible in Java. There are some other differences between Java and C++ classes (such as the lack of multiple inheritance) that you should consult a full-scale reference for. WHERE IS THE DESTRUCTOR? Although syntactically resembling C++, the Java language incorporates advanced programming language features that represent years of research. One of these features is automatic memory management or "garbage collection." The Java virtual machine will automatically reclaim the memory for objects that are nolonger pointed to by anything in your program. Thus there is no need to define a destructor for a class, and no need to use "delete" or "free" to deallocate memory manually, as you must do in C/C++. "Happy Happy Joy Joy!" TYPES A major improvement of Java over C++ is that Java is "type safe". This means, for example, that a value of type character array will never end up as a value of type "int". In C++ this is unfortunately not true and is a primary reason why the language is messy. For example, the following C++ segment is actually valid! (because a pointer is represented as an integer): int A[4]; // see java syntax for arrays below int x = 0; if (A>x) x++; // not ok in java if ( (int) A > x ) x++; // still not ok in java But the two if statements would not be valid in Java. You can not compare an array with an integer! Even explicit type casting between certain types (such as arrays and integers) are forbidden. Most people now recognize the virtues of a stronger typing discipline. Microsoft's new "C#" language also claims to have this improvement. Booleans, arrays, and strings also illustrate how Java have a "cleaner" treatment of types: BOOLEANS: Java defines the "boolean" type with constants "true" and "false". You can not use 0 for false and non-zero values for true, as you do in C++. The following statement would be valid in C++: while (4 && 5) { cout << "4 and 5 are both true!"; } But it doesn't make much sense. Java prevents such idiosyncracies. The boolean operators (&&, ||, etc ...) are the same as they are in C++ The following segment illustrates booleans in Java (what does it do?): boolean A = true; boolean B = false; while (A || B) { A = !B; B = A && B; } ARRAYS: The statements int[] myarray; myarray = new int[5]; or int myarray[] = new int[5]; would declare an array of 5 integers in Java. Note the word "new". What does this mean? It means that arrays are *objects* in Java. As objects they have members. For example, 'myarray.length' would return the length of the array (5 in the above case). However, the syntax for using array objects is specialized. A[i] would refer to the i+1st element of the array. Array indices work the same way as they do in C++ (they start from 0). Now, since arrays are objects, variables such as 'myarray' above are therefore actually pointers. The consequence of this is that, if you pass an array into a function, and make a change to some element of the array, then the change is reflected outside the function as well (just as C++ arrays). But remember that the pointer operations (* and &) are not allowed in Java, so you can not do something like *(myarray+2) to access the 3rd element of the array. You've got to do it with standard array notation (myarray[2]). Multiple-dimensional arrays are declared as in int[][] twodarray = new int[5][5]; STRINGS: The Java statement String greeting = "hello"; corresponds to the C++ statement char greeting[] = "hello"; A string in java should *not* be thought of as a pointer to a character (char *). Like arrays, STRINGS ARE OBJECTS. They have methods. For example, 'greeting.length()' would return the length of the string (in this case 5). The '+' symbol can be used to concatenate strings: ("abc" + "def") will return the string "abcdef". Since in Java all objects are pointers, you can not use '==' to test for string equality (== would test for pointer equality). The Java String class contains an "equals" method that should be used to test for string equality. That is, the expression greeting.equals("hello") would return true. (makes sense, right? greeting is an object with a method that allows it to be compared with other string objects). STREAM IO You might have noticed that in the first sample program there is nothing to take input from the keyboard. Unfortunately there is nothing in Java as convenient to use as "cin" in C++. However, IO in java do follow an object-oriented structure. Java I/O, be it with the keyboard, a diskfile, or a TCP/IP socket, are done through "streams", which are defined using a hiearchy of classes. It is out of the scope of this tutorial to go into much detail here. For now, just follow the steps below to set up keyboard IO: 1. put a line at the beginning of the file that says import java.io.*; "import" is like "include" in C/C++. The above line includes everything in the java.io library. 2. When you use standard IO in any part of your code, you need to enclose it in a "try-catch" clause that catches exceptions. Inside this clause you need to define a "BufferedReader" object. Once this object is created, textual input can be accomplished using the "readLine" method of the object: try { String inputstring; // string to hold input int inputvalue; // integer value of input BufferedReader BR; // object to read from stdio BR = new BufferedReader( new InputStreamReader(System.in) ); inputstring = BR.readLine(); // reads line from stdin // converts string to integer, e.g., from "12" to 12: inputvalue = Integer.parseInt(inputstring); BR.close(); // closes BufferedReader } catch (Exception E) {System.out.println(E);} The "BR" BufferedReader object corresponds to cin in C++. It has methods other than readLine, but readLine is commonly used. You can convert the string returned by readLine to other formats. For example, Integer.parseInt("12") will return the integer 12. The output complement to BufferedReader is "PrintWriter": PrintWriter PR; PR = new PrintWriter(new OutputStreamWriter(System.out)); PR.println("hello"); When enclosed in a try-catch clause the above three lines are actually equivalent to System.out.println("hello"); This may seem like a lot of hassle just to do simple IO, but the same mechanism can be used for more sophisticated IO operations: BR = new BufferedReader(new InputStreamReader (new FileInputStream("myfile"))); PR = new PrintWriter(new OutputStreamWriter (new FileOutputStream("myfile"))); would allow the BR and PR objects to read from and write to the file "myfile." That is, 'readLine' will read an ascii line from the file and 'println' will write to it. import java.net.*; ... Socket www = new Socket(InetAddress.getByName("www.hofstra.edu"),80); BR = new BufferedReader(new InputStreamReader(www.getInputStream())); PR = new PrintWriter(new OutputStreamWriter(www.getOutputStream()),true); This would allow communication with the Hofstra web server via the same simple 'readLine' and 'println' commands. The statements "BR.close();" and "PR.close();" should be used to close the IO objects and streams when you're finished. You'll need to read more if you really want to do sophisticated file and socket IO. The point is that the above code would make more sense once you understand that it belongs to a well-structured, object-oriented system for IO. The program at the end of this tutorial again illustrates the BufferedReader input mechanism. If keyboard IO is all that you need, then there is a nice module developed by Prof. Pillaipakkamnatt that encapsulates most of the details described above. The file is available at www.cs.hofstra.edu/java/Console.java. Put the file in the same directory where it's to be used. The file contains detailed descriptions of the interface. The last program in this tutorial also illustrates how this module can be used to trivialize console io. Lose Ends and Conclusion There are a couple of more things that needs to be mentioned before we wrap up: A. The NULL pointer in Java is not equivalent to 0. The keyword "null" represents the null pointer. The null pointer is used in the last program. B. When you declare a variable as in "int x;" as a memeber of a class, that variable is automatically initialized to zero when an instance of the class is created. However, when you declare such a variable within a method, it must be explicitly initialized (C++ would still compile code even if you do not give variables initial values). Similarly, when you declare an object variable as in "account x;" the variable is automatically initialized to null if it is declared as a class member. But it must be explicitly given a value if it declared inside a method. I stress again that this is only meant as a quick introduction. Do not assume that these examples represent the only way to accomplish something in Java. The SOLE purpose of this tutorial is to allow the initial transition from C++ to Java to be as painless as possible. Most advanced features are left out. Java comes fully equipped with a set of features for IO, graphics, concurrency, security, etc... I did not even touch on graphical programming, which is a strength of Java because of its platform independence. C++ programs fail to be cross-platform compatible once more advanced IO features (graphics) are involved. Unfortunately, any discussion of these useful mechanisms would be out of the scope of this tutorial, which is designed to simply allow you to start programming in Java as quickly as possible. I conclude this tutorial with a sample Java program that inputs integers into an array and inserts every element of the array into a linked list. It brings together the points we've addressed above. Read, compile, and run it! */ import java.io.*; // needed for all i/o except System.out.println import javax.swing.*; // needed for graphical io class cell // class for integer linked list cells { int head; // it's public by default, same as 'public int head;' cell tail; // no *, but it's a pointer by convention! public cell(int h, cell t) // constructor { head = h; tail = t; } // no ~cell() ? Java does it for me. Praise Java! public void print() // prints contents of list { cell ptr = this; // 'this' is same as in C++ while (ptr != null) // 'null' is a keyword, must be lowercase { System.out.print(ptr.head + " "); // + is string cat. ptr = ptr.tail; // '.' in java is '->' in C++ } System.out.println(""); // same as System.out.print("\n"); } } // no extra ';' at end of classes public class quickcj // sole public class; this file must be called { // quickcj.java public static void main(String[] args) // required header for main { int i; // loop counter, String input; // string representation of input int A[] = new int[5]; // array of 5 elements cell L = null; // a linked list, initially null try { // all non-trivial IO must be inside a try-catch clause BufferedReader BR; // allows for easy input from stream BR = new BufferedReader( new InputStreamReader(System.in) ); for(i=0;i=0;i--) // convert Array to list L = new cell(A[i],L); // add number to front of list System.out.println("Contents of list:"); L.print(); // prints contents of linked list BR.close(); // closes input stream } catch (Exception E) { System.out.println(E); } // closes try } // end of main // The following, alternate version of main uses the Console.java module // to encapsulate the details of keyboard IO. As it is, it will not // be executed as part of this program. It will compile if Console.java // is in the same directory where this file is stored. If not, comment // out or delete this function: /* public static void main2(String[] args) // required header for main { int i; // loop counter, int A[] = new int[5]; // array of 5 elements cell L = null; // a linked list, initially null for(i=0;i=0;i--) // convert Array to list L = new cell(A[i],L); // add number to front of list Console.writeln("\nContents of list:"); L.print(); // prints contents of linked list } // end of main2 */ } // end of public quickcj class /* This document may be freely distributed as long as it's unmodified and used only for academic purposes. */ /* EXTRA EXTRA SPECIAL NOTE ON JAVA IO: In the tutorial the Java IO I described using the BufferedReader class is fairly complex. Here's another way to do IO. First put the following line at the top of your file: import javax.swing.*; The following expression returns a String, which is the user input: String s; s = JOptionPane.showInputDialog(null,"enter something: "); The following statement displays a string in a dialog box: JOptionPane.showMessageDialog(null,"hello"); To convert the input string to a numerical value, use: int x = Integer.parseInt(s); // where s is a string such as "12" double y = Double.parseDouble(s); For example, to input a circle's diameter and return the circumference: String s = JOptionPane.showInputDialog(null,"enter diameter: '); double x = Double.parseDouble(s); JOptionPane.showMessageDialog(null,"the circumference is " + 3.14*x); You can also convert anything in Java to a string representation by concactenating the empty string in front of it, e.g. ""+3.14 gives "3.14". */