HomepageTeaching PageResearch PageResources Page

Java Tutorial for Python Programmers

Classes and Objects

Let's create our own classes now. Python lets you get away with a lot of things here that you can't do in Java, but it's not terribly different. Some important things to keep in mind:

Creating a New Class

Let's create a new class to represent monkeys. Our class will be named Monkey, so we need to create a new text file, Monkey.java. Create that file, and add the following code to it:

public class Monkey {
        
} //end of class Monkey        
        

We can compile this to make sure it works:

$ javac *.java
Note: CodeToRun.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
$
	    

Fields

Right now our object has no fields, so it's not representing much. Let's add some fields for basic stats about each Monkey object.

public class Monkey {

    //age of this monkey, in years
    public int age;
    
    //height of the monkey, from feet to head, in meters
    public double height;
    
    //the monkey's name
    public String name;
    
} //end of class Monkey
        

Constructors

In Python, the __init__ method is the constructor, which initializes all the fields. In Java, the syntax for this is quite a bit different. It still looks like a method, except the return type isn't specified and the "name" is replaced by the class name (in PascalCase). Here's the class with the constructor added:

public class Monkey {

    //age of this monkey, in years
    public int age;
    
    //height of the monkey, from feet to head, in meters
    public double height;
    
    //the monkey's name
    public String name;
    
    //constructor
    public Monkey(int age, double height, String name) {
        this.age = age;
        this.height = height;
        this.name = name;
    }
    
} //end of class Monkey
        

Notice that this is the reference to the subject instead of Python's self. Since Java has only methods and no non-method functions, this identifier isn't listed as the first parameter.

Create an instance of this class in the main method in CodeToRun.java: (We don't need to import Monkey.java as long as both .java files are in the same folder.)

    public static void main(String[] args) {
        Monkey monkey = new Monkey(3, .65, "Banano");
        System.out.println("Banano's age: " + monkey.age);
        System.out.println("Banano's height: " + monkey.height);
        System.out.println("Banano's name: " + monkey.name);
    }
        

toString

__repr__ and __str__ become toString. Java uses toString as the default method for displaying objects, so you definitely want to write that next. This method should always take no parameters and return a string. Here I've added toString to Monkey.java:

    //constructor
    public Monkey(int age, double height, String name) {
        this.age = age;
        this.height = height;
        this.name = name;
    }
    
    //toString
    public String toString() {
        String string = "";
        string += "Monkey named " + this.name + ":\n";
        string += "  age: " + this.age + " years\n";
        string += "  height: " + this.height + " m";
        return string;
    }
        

Now we can test this by adding a line to our main method in CodeToRun:

    public static void main(String[] args) {
        Monkey monkey = new Monkey(3, .65, "Banano");
        System.out.println("Banano's age: " + monkey.age);
        System.out.println("Banano's height: " + monkey.height);
        System.out.println("Banano's name: " + monkey.name);
        System.out.println("monkey: \n" + monkey.toString());
    }
        

Now run that code:

$ javac *.java
Note: CodeToRun.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
$ java CodeToRun
Banano's age: 3
Banano's height: .65
Banano's name: Banano
monkey: 
Monkey named Banano:
  age: 3 years
  height: .65 m
$
        

Recall that Java automatically calls toString in most cases where it's looking for a string, so we can remove the .toString() in the second-to-last line:

    public static void main(String[] args) {
        Monkey monkey = new Monkey(3, .65, "Banano");
        System.out.println("Banano's age: " + monkey.age);
        System.out.println("Banano's height: " + monkey.height);
        System.out.println("Banano's name: " + monkey.name);
        System.out.println("monkey: \n" + monkey);
        return string;
    }
        

The output will be the same as before.

Access Modifiers

Unfortunately, we can do the following thing:

    public static void main(String[] args) {
        Monkey monkey = new Monkey(3, .65, "Banano");
        System.out.println("Banano's age: " + monkey.age);
        System.out.println("Banano's height: " + monkey.height);
        System.out.println("Banano's name: " + monkey.name);
        monkey.age = -17;
        System.out.println("monkey: \n" + monkey);
    }
        

-17 doesn't make a lot of sense for the age. How can we fix this? We can change the constructor so that negative ages don't work:

    //constructor
    public Monkey(int age, double height, String name) {
        this.age = age;
        if (this.age < 0) {
            //an illegal age was given, so set the age to zero.
            // (should be improved by throwing an exception instead)
            this.age = 0; 
        }
        this.height = height;
        this.name = name;
    }
        

This won't solve the entire problem, though. We want to make it so that other code doesn't have direct access to the fields of any Monkey object. We can do this by changing the declarations to specify that these fields are private instead of public. Modify your Monkey class to:

public class Monkey {

    //age of this monkey, in years
    private int age;
    
    //height of the monkey, from feet to head, in meters
    private double height;
    
    //the monkey's name
    private String name;
        

Try compiling your code again. You'll see these errors:

$ javac *.java
CodeToRun.java:6: error: age has private access in Monkey
        System.out.println("Banano's age: " + monkey.age);
                                                    ^
CodeToRun.java:7: error: height has private access in Monkey
        System.out.println("Banano's height: " + monkey.height);
                                                       ^
CodeToRun.java:8: error: name has private access in Monkey
        System.out.println("Banano's name: " + monkey.name);
                                                     ^
3 errors
$
        

Any member (field or a method) of a class has an access modifier, which can be set to one of four things:

There are some general rules to follow when choosing access modifiers, in order to best protect your code:

Getters

We might still want some access to the fields. For example, it seems reasonable to get a hold of the age of a monkey. We can do that by adding another method to Monkey.java, a "getter":

    public int getAge() {
        return this.age;
    }
        

Then, in CodeToRun.java, we can use this in the main method:

    public static void main(String[] args) {
        Monkey monkey = new Monkey(3, .65, "Banano");
        int yearsOld = monkey.getAge();
        System.out.println("Banano's age: " + yearsOld);
        yearsOld = 15;
        System.out.println("yearsOld: " + yearsOld);
        System.out.println("Banano's age: " + monkey.getAge());
    }
        

Running this, we see:

$ javac *.java
Note: CodeToRun.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
$ java CodeToRun
Banano's age: 3
yearsOld: 15
Banano's age: 3
$
        

Notice that we get access to the value of the age, but can't change the actual value in the object.

Setters

Sometimes we still want to be able to change the value, though maybe to a limited extent. We can do this by adding a "setter":

    public void setAge(int age) {
        if (age >= 0) {
            //change the age if positive
            this.age = age;
        }
    }
        

Notice that this allows us to change the value, but still protects against rogue code trying to assign it a negative number.

Test Your Understanding

Create a new class, Horse in its own file. Do each of the following steps:


Tutorial Table of Contents

  1. Intro
  2. Java Files and Classes
  3. Running Java Code
  4. Statements and Printing
  5. Comments
  6. Types and Variables
  7. Conditionals
  8. Static Methods
  9. Strings
  10. Loops
  11. Arrays
  12. ArrayLists
  13. Classes
  14. Subclasses
  15. Generic Types
  16. Javadoc
  17. Final Exam
  18. What's Next?