Java4Python Companion

There are specific examples of translations from Python to Java in Java4Python, but since it is mostly translation, it is a lot denser than the Python text for total newbies: Rather than have a lot of little snippets testing one bit of syntax at a time, it is mostly larger examples with translation information.

You may well want to play more with little bits of syntax, like you already did in Python, and which did help solidify your memory. Now since you have tested out little snippets in Python, you can make up your own little snippets translated into Java to test.

In Python one place to check little snippets was the Python shell. Thankfully, starting with Java 9, there is corresponding tool for Java called jshell. If you have installed Java 9+, you call start jshell from a terminal. IntelliJ Idea can a built in terminal where you can start it, too. You can start right off testing for the arithmetic operation differences from Python.

Java Data Types Notes

Read up to Data Types

Numeric Notes

Because the Java primitive types are stored in fixed-size spaces, as a Python float is, they have restrictions. In particular int is not of unlimited size. Java has a number of sizes. The most common integer types are int and the larger long.

char
A char is a single character, with literals in single quotes, like ‘x’. In Java this is distinct from a String, even a String with one character, like “x”. Technically char is a small numeric type: It just prints as a character, but can be used in arithmetic expressions. (More later.)

Because the Java primitive types are stored in fixed-size spaces, like a Python float is, they have restrictions. Limits are accessible in Java with wrapper class static values: Integer.MAX_VALUE, Integer.MIN_VALUE, Double.MAX_VALUE, .... Here is some of the data collected:

long
64 bits; range -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
int
32 bits; range -2,147,483,648 to 2,147,483,647
double
64 bits; maximum magnitude: 1.7976931348623157(10308); about 15 digits of accuracy
float
32 bits; maximum magnitude: 3.402823(1038); about 7 digits of accuracy

In the temperature conversion program, I would follow the usual form, and use the smaller and more efficient primitive type double, not the object type Double. We will use object wrapper classes only in the few places where they are required.

Another thing to notice is in the creation of the Scanner object: Java is verbose when calling a constructor for an object type like Scanner. The constructor must be preceded by the keyword new, as in in = new Scanner(System.in);

You can skip the final GUI example using the Swing class.

Operators

Java does arithmetic in the temperature conversion program. More detailed discussion of operators is in order:

Just as some Java data types correspond closely Python, while others have less in common, the same is true of operators.

Addition, subtraction, multiplication and negation correspond closely, except if the result does not fit in the range of the result type, an overflow error occurs, silently in Java! This could be a huge, hard to debug problem in Java!

Java does not use // for any division. (Rather // starts a comment.) Instead / does double duty, based on the type of the operands. If at least one operand is a double, it behaves like Python /. If both are ints, it behaves like Python // when both operands have the same sign, but not when the real number result would be negative: Python returns the floor of the real division (greatest integer <= real result) while Java truncates toward 0.

In the Fahrenheit conversion program, note that the expression (fahr - 32) * 5.0/9.0 evaluates correctly, and would have the same result if written (fahr - 32) * 5/9. Evaluating from left to right starting with double variable fahr means every intermediate operation produces a double result. However, the expression (fahr - 32) * (5/9) would not be the same! The parentheses around 5/9 means this integer quotient is calculated separately. The int operands means it would be the same as Python 5//9, so it equals 0! In Java 5/9 is not anything like 5/9 in math.

The remainder operation % is the same in both languages if the sign of both operands is the same, but not with different signs. With integers d and n, d*(n//d) + n%d always equals n in Python, and d*(n/d) + n%d always equals n in Java, but since integer division works differently with different signs, so does %.

Boolean operator and, or and not in Python correspond exactly to Java &&, || and ! if operands have Boolean values.

Java also allows the modification operators like +=. Incrementing and decrementing by 1 have special operators ++ and --, as illustrated in the List section.

While == with primitive numeric data checks for mathematical equality, when two objects are compared in Java using the == operator they are tested to see if they are exactly the same object, that is do the two objects occupy the same exact space in the computers memory (Python is operator).

Declaring Variables Notes

In the temperature conversion example above, lines 5—7 do contain variable declarations, but if we use double rather than Double, then fahr and cel are going to refer directly to spaces that store the primitive double data. The variable in will reference a Scanner object. This means that if we were to try an assignment like fahr = "xyz" the compiler would generate an error because "xyz" is a string and fahr is supposed to be a double. ` When creating a new object, like a new Scanner, Java requires an explicit new before the type being constructed.

For Python programmers the following error is likely to be even more common. Suppose we forgot the declaration for cel and instead left line 6 blank. What would happen when we type javac TempConv.java on the command line?

TempConv.java:13: cannot find symbol
symbol  : variable cel
location: class TempConv
         cel = (fahr - 32) * 5.0/9.0;
         ^
TempConv.java:14: cannot find symbol
symbol  : variable cel
location: class TempConv
         System.out.println("The temperature in C is: " + cel);
                                                          ^
2 errors

When you see the first kind of error, where the symbol is on the left side of the equals sign it usually means that you have not declared the variable. If you have ever tried to use a Python variable that you have not initialized the second error message will be familiar to you. The difference here is that we see the message before we ever try to test our program. More common error messages are discussed in the later section on common mistakes.

The next section on casts is not in Java4Python at all:

Numeric Type Conversions

This section is not in Java4Python.

We had fewer numeric types in Python, so there were fewer conversion issues. We already saw in Python that 2.3 + 5 (float + int) made sense: the less general type int is converted implicitly to the more general type float. The same is true in Java.

In Python constructors could do explicit conversion, including where information is lost:

x = 2.8      # float
y = int(x)   # int 2
x = -5.7     # float
y = int(x)   # int -5

Converting a float to an int truncates toward 0 - losing the fractional part.

The exact same idea appears in Java with very different notation, called casting. A cast involves the new type name in parentheses before the value to be converted:

double x = 2.8;
int y = (int) x;
x = -5.7;
y = (int) x;

The resulting int values are truncations like in Python. An explicit cast is generally only needed when the new type holds less information. The other direction can be implicit:

double z = 2;

The Java char type can be trickier. It is a numeric type smaller than an int. Binary arithmetic operations with numeric types smaller than int get automatically converted to int operations. The character 'A' has numeric value (its ASCII code) 65. The following letters of the alphabet have successive numeric values.

char ch = 'A';
int v = ch; // 65
ch++;  // now ch is 'B'
v = ch; // 66
ch = (char)(c+1);  // 'C'  Note cast!!
int diff = ch - 'A' //2: 'C' 2 after 'A'
boolean isPast = ch > 'A'; // true

If the cast had been left out in the third to last line:

ch = ch + 1;

there would be an error, since ch + 1 is a char plus an int, where the char is implicitly converted to an int for the arithmetic, but then the larger type int cannot be assigned back to the smaller type char without an explicit cast.

The error in IntelliJ IDEA 2018 if the cast is omitted is:

java: incompatible types: possible lossy conversion from int to char

What if you want to round rather than truncate a double. There is a method Math.round, but it produces a double, This can be combined with casting to int:

double x = 2.8;
int r = (int)Math.round(x);  // r is 3, not 2.

We have been discussing casts with primitives. The same word, cast, and notation are used with objects with a totally different interpretation. It will only make sense after you study inheritance in your next class.

While Python has simple conversion syntax to change a string to a number, Java is more verbose:

int i = Integer.parseInt("-22");  // i is -22
double d = Double.parseDouble("-3.5");  // d is 3.5

The shortest notation to convert a number v, or anything else, to a String is "" + v using the conversion ability of + with a String.

Conversion and Op Exercises

  1. What is printed?

    int x = 7, y = 2;
    double d = 5.678;
    char ch = 'H';
    ch--;
    System.out.println(x/y);
    System.out.println((int)d);
    System.out.println(ch);
    System.out.println('J' - ch);
    System.out.println('B' > ch);
    
  2. This is not obvious for many. What is printed? Explain.

    int x = 2, y = 3;
    System.out.println('Sum is ' + x + y);
    

    How would you fix it without further setting the value of a variable?

Input / Output / Scanner Notes

The table of Scanner methods ends with nextLine(). This is like Python input() (no prompt) IF you are at the start of input or last used nextLine() for the previous line. The difference is that in Python, you always read a whole line at a time, but the other Java Scanner input methods, like nextInt(), read to the end of a token,(even through several lines if there is only whitespace in between), but not necessarily to the end of a line. Calling nextLine() reads through the next '\n', which could just be the rest of a line after a token read with something like nextInt().

String Notes

Though concat is a method, you can still use + for two strings like in Python.

There is a major difference with + in Java: In Python, if you have one string operand, both must be strings explicitly, so in Python, if x is an int, then "Number " + x is illegal and you need an explicit conversion, "Number " + str(x). In Java the former is fine - the string conversion is done implicitly. Also OK with the string second like x + " choices".

Here are a few more examples. Suppose x is a float/double:

Python Java Description
s.replace("me", "I") same as Python Replace all occurrences of first parameter by second
s.upper() s.toUpper() Return string in uppercase; similarly Java toLower
'v: {:7.2f}\n'.format(x) String.format("v: %7.2f%n", x) Return a formatted string

String.format is used much like a Python string with the string format method. The % followed by modifiers is used much like the {} in Python format strings. A method producing the same string is System.out.format except in that case it is directly printed to System.out, not returned. This is more important in Java, since System.out.println and System.out.print can only take a single argument, unlike the allowed list in Python for print.

Java format modifiers end with a type designation: s prints anything as a string, d is for ints, and f is for doubles. A field width can be given after the %, with a negative number indicating left justification. You can show field width and precision for a double, like in Python.

The Java format component %n is special: It does not format the next parameter. It just inserts an operating system appropriate newline. While the println alternative to print adds an extra newline, there is no alternate to format that automatically inserts newline.

In general you should not use '\n' in Java: In Python, C#, and C++, '\n' is replaced in file output by whatever newline sequence is used by the current operating system. (Windows and Unix/Mac are different.) These days most applications are newline format agnostic, but not all. It may have changed recently, but the classic Windows Notepad does not know what to do with a plain '\n'.

The example for split in the original String table was chosen carefully. For Java there must be a parameter, and it is a regular expressions, or regex for short: another specialized language with variants embedded in many programming languages. To match the behavior of a Python string parameter, treated verbatim, you need to escape any of the following characters you use: []{}()+*^$?

The regex escape character is \, but unfortunately that is also the string escape character, so to get it to the regex, it, too, needs to be escaped. So if you wanted to split on +, you would need str.split("\\+").

The analog for str.split() (no Python parameter) is trickier! Python ignores white space on either end, and splits out tokens with any number of whitespace characters in between. Java will generate empty strings in the list if there is whitespace at the beginning, and you need a regex to handle multiple whitespace characters together, so to match Python you need the mouthful str.trim().split("\\s+").

List Notes

Always give the element type for an ArrayList! This is a place you do need the wrapper type in place of a primitive type.

Note that the different types of loops are discussed in more detail in the later Loops and Iteration section. This section gives a preview.

The Java program here initially sets Scanner in = null;. We use Python None much like Java null, but the value null may only be assigned to a variable of object type, not primitive type.

We have not discussed the last Python example to translate, though zip is covered in FOPP Chapter 23.

  • for x,y in zip(range(10),range(0,20,2)) [hint, you can separate statements in the same clause with a ,]

Note that zip creates a sequence of tuples or corresponding elements of multiple sequences. zip(range(10),range(0,20,2))) produces the sequence (0, 0), (1, 2), (2, 4), (3, 6), (4, 8), (5, 10), (6, 12), (7, 14), (8, 16), (9, 18).

List method comparison: Suppose w and w2 are lists of strings --

Python Java notes
value of w[3] w.get(3) Return item in 3rd position
w[3] = 'a' w.set(3, "a") Set item in 3rd position
w.append('a') w.add("a") Append item
len(w) w.size() Return the number of items in the list
w.find('x') w.indexOf("x") Find index of the first occurrence of x, or -1
w += w2 w.addAll(w2) add all of list w2, modifying w
'x' in w w.contains("x") membership test
not bool(w) w.isEmpty() Python w is True if not empty
w[:]=[] w.clear() Remove all items
w.pop(2) w.remove(2) remove and return item at position 2
w.sort() Collections.sort(w) sort according to natural ordering

If you want to iterate over w[2:4] and not change anything in the list, w.subList(2,4) is an analog, but it does not create a new list: it is a view of w. The analog of w2 = w[2:4], which copies item references to a new list, is w2 = new ArrayList<String>(w.subList(2,4)).

String method join takes a string sequence as parameter. To separate with ", " the strings in list sList:

', '.join(sList) in Python
String.join(", ", sList) in Java

In Python and Java sList can be a more general iterable sequence of Strings, In Java that includes an array of Strings.

For more extensive use of Java ArrayLists, you will want to see its documentation, https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html.

See also the java.util.Collections class.

Array Notes

The initialization of the array count (which could better have elements of type int) demonstrates the way to assign initial values inside braces.

However in this particular situation it is verbose, if we switch to primitive element type int.

All newly created objects in Java are fully initialized. Numeric data defaults to 0. A shorter initialization would just instantiate a new array of length 10, and the 0 element values would follow automatically:

int[] count = new int[10];

Automatic initialization for other element types: new boolean[5] sets all 5 elements to false.

Recall char is technically a numeric type, but the character with numeric value 0 is unprintable. A way to initialize a char array is using String method toCharArray():

char[] letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".toCharArray();

Any array of objects gets all item values null by default, so :

Integer[] count = new Integer[10];

would not supply all 0's, but null values!

Arrays have a length attribute -- accessed with no parentheses after it. The length of array a is a.length. This is unlike Strings! The length of String s is s.length(). The length cannot be changed for either an array or string.

It is also easy to conflate syntax for list lengths. Lists can be changed: A different method name is used for the (current) length of ArrayList al: al.size().

Here is a function to return a new array containing the squares of the numbers in a passed array. See the use of the length attribute:

public static int[] squares(int[] nums)
{
    int n = nums.length;
    int[] sq = new int[n];
    for (int i = 0; i < n; i++) {
        sq[i] = nums[i]*nums[i];
    }
    return sq;
}

Dictionary Notes

We will generally use HashMap. The discussion of the implementations comes in Data Structures.

The TreeMap has both keys and values, so two types are specified TreeMap<keyType, valueType>. This needs to occur both when the type is declared and later where the constructor is used.

The method hasNext with no type appended to the name is checking if there is any token next.

Python also has a get method for dictionaries, but the usage when there is no element is different: Python causes an error unless a default value is included as a second parameter. Java does not trigger an error, but just returns null.

Here there is a ++ operator, but the ++ is before the variable ++wordCount. If ++wordCount were used as a separate statement, it would be equivalent to wordCount++ (just increment wordCount), but here is is an expression whose value is used in a larger statement: With the ++ first, the value of the expression is the new value, after incrementing. With the ++ second, the value of the expression is the original value, before incrementing. To avoid these fine points, you are encouraged not to use either where the expression value is used in the same expression. Same idea for the decrement operator --.

The method System.out.fprint is usually replaced by the identically behaving System.out.format, You may want a formatted string, but not to print it immediately. The String class has a format method that works exactly like that with System.out, except the String is returned rather than being immediately printed.

The Java getKeys() method is like the Python keys() method. The extra step to sort the keys in Python is needed since a dict corresponds to a Java HashMap, generating keys in an unpredictable order. This Java example used a Treemap, which has slower access, but maintains the keys in order.

Dict/HashMap comparison:

Python Java
d = dict() d = new HashMap<keyType, valueType>()
d[key] = v d.set(key, v)
v = d[key] v = d.get(key) // may be null
d.keys() d.getKeys()

Conditionals Notes

Be very careful not to end the line of an if or while heading with a semicolon! like

if (x < 2);   // WRONG !!!
{
   System.out.println("Always printed, even if x is 1!")
}

After the close parenthesis a Java if statement expects one statement (simple or compound), and ; alone is technically a statement! That means the statement in braces is the second statement after the if test - not a part of the if statement at all!

This causes lots of errors for Python programmers, generally forgetting semicolons, and madly trying to add them.

A switch statement is error prone. (Omitting a break; is legal but generally wrong.) You may see them. You are not required to write them.

Boolean Operators

Java does have the ugly syntax:

condition ? trueValue : falseValue

Python recently added a corresponding construction (much more like English!):

trueValue if condition else falseValue

Loops and Iteration Notes

Definite Loop Notes

Technically the direct translation of

for i in range(100,-1,-5):
    print(i)

to Java would be:

for (int i = 100; i > -1; i -= 5)
    System.out.println(i);

The comparison to -1 in the Python is a strict inequality.

Indefinite Loops

The do { ... } while (condition); loop is the one place in Java where there is a semicolon after a condition!

Loop and Array Exercises

  1. Write a static void method printNums with int array parameter that prints out all the elements of the parameter on one line, blank separated. Use it for tests of methods below.

  2. Write a program including a static void method called noNeg to mutate its int array parameter so all negative elements become 0. Include a test in main. For your tests remember the easy way to initialize an array with braces.

  3. Write a program including a static method called allUpper with a String array parameter that does not modify the parameter array, but returns a String array with all the strings of the parameter array in upper case. (Use string method toUpper: "Hello".toUpper() returns "HELLO".) Include a test in main. Use a for-each loop to display the contents of the returned array.

  4. Write a program including a static boolean method called isIncreasing with an int array parameter that returns true if the array elements are strictly increasing, and false otherwise. Include thorough tests in main. It is easy not to have diverse enough tests!

  5. Write the body of

    public static int factorial(int n)
    

    where factorial(n), or n! in math, means 1*2*...*n for positive n. By convention 0! is 1. 1! is 1; 2! is 1 * 2 = 2; 3! is 1*2*3 = 6.

    What is the largest value of n for which you get the correct answer in Java? (In Python there is no limit until you run out of system memory.) If you get a negative answer, it is clearly screwy, but overflow answers do not need to be negative. You might write some extra code to help with the test.

  6. Same as the last problem by with int type everywhere replaced by long.

  7. Is this method legal? What would it print if so?

    public static void alphabetData()
    {
       for (char ch = 'A', ch <= 'Z'; ch++)
       {
           System.out.println(ch + " is " + (ch - 'A') + " past A.");
       }
    }
    
  8. Improve the dictionary/word-count program to not include punctuation in words.

Defining Classes in Java

I am completely replacing this Java4Python section. My replacement is lengthy, and in a separate document, userdefinedjavaobjects.html.

Do finish up with the remaining Java4Python sections.

Common Mistakes Notes

The Forgetting a Semicolon example might be elaborated: The caret (^) clearly does not show a place where you need a semicolon. It is the first place the compiler realizes you omitted a semicolon! This error and missing closing parenthesis are among the common mistakes where you need to look back to the previous line.

Recall the extra semicolon error mentioned in the Conditionals notes.

Here is one additional error to note, match Wrong if With else:

In Python it is easy to find the if that goes with an else: look upward to find an if with the same indentation. In Java you are encouraged to indent much like Python, but it has no intrinsic meaning to the compiler!

If you do not consistently put the sub-statements for the true and false choices inside braces, you can run into problems from the fact that the else part of an if statement is optional. Even if you use braces consistently, you may well need to read code that does not place braces around single statements. If Java understood indentation as in the recommended formatting style (or as required in Python), the following would be OK:

if (x > 0)
   if (y > 0)
      System.out.println("positive x and y");
else
   System.out.println("x not positive, untested y");

Unfortunately placing the else under the first if is not enough to make them go together. (Remember the Java compiler ignores extra whitespace). The following is equivalent to the compiler, with the else apparently going with the second if:

if (x > 0)
   if (y > 0)
      System.out.println("positive x and y");
   else
      System.out.println("x not positive, untested y");

The compiler is consistent with the latter visual pattern: an else goes with the most recent if that could still take an else. Hence if x is 3 and y is -2, the else part is executed and the statement printed is incorrect: in this code the else clause is only executed when x is positive and y (is tested and) is not positive.

If you put braces everywhere to reinforce your indentation, as we suggest, or if you only add the following one set of braces around the inner if statement:

if (x > 0) {
   if (y > 0)
      System.out.println("positive x and y");
}
else
   System.out.println("x not positive, untested y");

then the braces enclosing the inner if statement make it impossible for the inner if to continue on to an optional else part. The else must go with the first if. Now when the else part is reached, the statement printed will be true: x is not positive, and the test of y was skipped.

Java Documentation Online Notes

The initial documentation links may still be bad. Instead: All Java class libraries are documented and available online. Here is the official resource: https://docs.oracle.com/javase/8/docs/api/index.html?overview-summary.html

If you know the package that a class is in, you can reach it through the package. If you do not know the package, you can go to the Index, click the link for the starting letter. Then you can do a browser search in the (huge) page. Class entries have the class name, a space and a dash. Searching for that combination may help.

I also have a concise summary of much of this conversion to Java data in this course: javaNotes.html.