Skip to content
Ameen Abozaid
PublishedBEG-020-L01

Writing your first class

  • Lesson 1 of 7
  • 12 min read
  • Beginner
On This Lesson 11 topics

Lesson Overview

In the previous module you learned that a program can be organized as objects, and that a class is the blueprint those objects are built from. That module only previewed the Java syntax. From this lesson on, you write it yourself.

This lesson covers the smallest useful class: a file that declares fields, the pieces of data every object of that class will carry. We use a blueprint-and-houses picture. The class is the architect's drawing, which lists "a house has an address, a number of rooms, and a colour". Each house built from the drawing gets its own values for those items.

Why this matters: every backend class you will read, such as an Order, a Customer, or a database entity, starts as a class with fields. Getting the file naming, the field declarations, and the default values right is the base for the rest of the module.

This lesson builds on the previous module (state, behavior, classes versus objects) and on variables and types from earlier modules. It needs no other background.

Learning Objectives

By the end of this lesson you will be able to:

  • Write a class in its own .java file, with a file name that matches the class name.
  • Follow the naming convention for classes (capital first letter, one word per capital).
  • Declare fields of different types inside a class, outside any method.
  • Explain that each object gets its own copy of every instance field.
  • State the default value of a field of each basic type, and why a local variable is different.
  • Create an object with new and read and set its fields with the dot.

Written Explanation

One class, one file

Up to now your programs were a single class with a main method. A class that models something from the real world is usually a separate file, and Java has a firm rule for it: a public class must live in a file whose name is the class name plus .java. The class Account goes in Account.java.

java
public class Account {
    String owner;
    String number;
    double balance;
}

If the names do not match, the compiler refuses. Here the same class sits in a file called Acct.java:

text
Acct.java:1: error: class Account is public, should be declared in a file named Account.java
public class Account {
       ^
1 error

The usual layout is one class per file, all files in the same folder (or the same package of your IDE project). The class with main is just another class; it is often called Main.

Naming classes

By convention, a class name is a noun that starts with a capital letter, and each new word also starts with a capital: Account, BankStatement, ShoppingCart. This is called UpperCamelCase (or PascalCase). The compiler does not enforce it, but every Java developer expects it, so a class called account looks like a mistake. Variables and fields, in contrast, start with a lower-case letter (balance, accountNumber).

Fields

A field is a variable declared directly inside the class, outside every method. It is the state from the previous module, written as code. A field declaration has a type and a name, just like a local variable:

java
String owner;     // text
String number;    // text, such as "A-1"
double balance;   // a number with a fractional part

Money as double is a shortcut for this module so we can focus on classes. It is not a good way to store money, because double cannot represent many decimal amounts exactly. A better approach comes later in the course.

The class only declares the fields. It does not hold any values itself, just as the architect's drawing is not a house. Values exist only after you build an object.

Building an object and using the dot

You build an object with new. According to the Java tutorial, new allocates memory for a new object and returns a reference to it. You will look at references properly in Lesson 4. For now, read this line as "make one account and call it a":

java
Account a = new Account();

The dot reaches into the object: a.owner = "Ana"; assigns that object's owner, and a.owner reads it. Notice what you write: a variable name, a dot, a field name. You never write Account.owner to reach an object's data, because the class is only the blueprint.

Each object has its own copy

Every object gets its own set of instance fields. If you build two accounts, there are two owner values, two number values, and two balance values, and changing one account does not touch the other. This is the difference between a class (one definition) and objects (many copies of the state), and it will come back in Lesson 5, when we meet the one kind of field that is not copied per object.

Default values

What happens if you build an object and never set a field? Java fills fields with a default value:

Field typeDefault value
int, long, short, byte0
double, float0.0
booleanfalse
charthe character with code 0 (it prints as an invisible character)
any object type (String, arrays, your own classes)null

null means "no object here". The Java tutorial adds that relying on these defaults is generally considered poor style, so in the next lesson we will write constructors that set every field deliberately.

Defaults apply to fields only. A local variable, one declared inside a method, never gets a default. Using one before assigning it is a compile-time error: "variable might not have been initialized". Do not mix up the two.

Examples

Example 1: a class with defaults (simple)

Account.java is the class from above. Main.java builds two accounts and sets only one owner:

java
public class Main {
    public static void main(String[] args) {
        Account a = new Account();
        a.owner = "Ana";
        Account b = new Account();
        System.out.println(a.owner + " " + a.number + " " + a.balance);
        System.out.println(b.owner + " " + b.number + " " + b.balance);
    }
}

Output (run on JDK 21):

text
Ana null 0.0
null null 0.0

Account a has an owner because we set it; its number is still null and its balance is 0.0. Account b is completely untouched. Setting a.owner did not change b.owner: each object has its own copy.

Example 2: every default at once (practical)

A class can have fields of any type. This Student has five, and none is set:

java
public class Student {
    String name;
    int age;
    boolean enrolled;
    char grade;
    int[] marks;
}
java
public class Defaults {
    public static void main(String[] args) {
        Student s = new Student();
        System.out.println(s.name + " " + s.age + " " + s.enrolled
                + " " + (int) s.grade + " " + s.marks);
    }
}

Output:

text
null 0 false 0 null

We cast the char to int so that the default is visible as 0. The array field marks is null: there is a slot for an array, but no array has been created. Calling s.marks.length here would fail, a mistake we will meet properly in Lesson 4.

Example 3: modelling a real thing (realistic)

Suppose a small shop wants software for its products. Reading the description, "a product has a name, a price, a stock count, and can be active or hidden", gives you the fields almost word for word:

java
public class Product {
    String name;
    double price;
    int stock;
    boolean active;
}
java
public class Main {
    public static void main(String[] args) {
        Product tea = new Product();
        tea.name = "Tea";
        tea.price = 2.5;
        tea.stock = 40;
        Product mug = new Product();
        mug.name = "Mug";
        System.out.println(tea.name + " " + tea.price + " " + tea.stock + " " + tea.active);
        System.out.println(mug.name + " " + mug.price + " " + mug.stock + " " + mug.active);
        tea.stock = 35;
        System.out.println(mug.stock);
    }
}

Output:

text
Tea 2.5 40 false
Mug 0.0 0 false
0

The last line proves the point: we changed the tea's stock to 35 and the mug's stock is still 0. Two products, two independent states, one class. The Product class will be our running example in the exercises of the next lessons.

Backend Insight

Backend code is mostly data shapes. An HTTP request is turned into an object, the object is handed to the business code, and the result is stored in a database row. That shape, the list of named, typed fields, is a class. Frameworks you will use later, such as Spring, create and fill objects like these for you, and database mapping tools turn each field into a column.

Two habits start here. First, design the fields from the problem: nouns in the description become classes, and their attributes become fields. Second, remember that null is the default for every object-typed field. Much of the real-world debugging in backend work is tracking down a field that was never set. Seeing null in an output should immediately make you ask "who was supposed to fill this in?"

Common Mistakes

Mistake 1: File name and class name do not match

  • Incorrect: public class Account saved as account.java or Acct.java.
  • Correct: public class Account saved as Account.java. Capitalization counts.

The compiler error quoted above tells you exactly what to do; read it.

Mistake 2: Declaring a field inside main or another method

A variable declared in a method is a local variable. It disappears when the method ends and does not belong to the object. If you want the object to remember something, declare it at class level, above or below the methods, never inside one.

Mistake 3: Reaching a field through the class name

  • Incorrect: Account.owner = "Ana";
  • Correct: Account a = new Account(); a.owner = "Ana";

An instance field belongs to an object, so you need an object to reach it. The class name only works for static members, which Lesson 5 explains.

Mistake 4: Trusting a default without noticing it

A balance of 0.0 looks harmless, but a number of null printed into a receipt, or a null that is later used in a method call, is a bug in waiting. If a field must always have a real value, make sure that the code sets it, which is what constructors are for.

Exercises

Try each exercise yourself before opening the solutions. Use your IDE or the command line, and write the files in an empty folder.

Level A: Foundation

A1. A class ShoppingCart should be saved in which file name? Would shoppingcart.java work?

Show solution A1

A1. ShoppingCart.java. A file named shoppingcart.java would not work for a public class, because file names are compared with the class name including capitalization.

A2. What are the default values of these fields in a new object: int quantity;, String label;, boolean paid;, double weight;?

Show solution A2

A2. quantity is 0, label is null, paid is false, weight is 0.0.

A3. In the following code, which variables are fields and which are local variables?

java
public class Counter {
    int value;
    void show() {
        int copy = value;
        System.out.println(copy);
    }
}
Show solution A3

A3. value is a field (declared in the class, outside any method). copy is a local variable, declared inside show. A local variable has no default value and must be assigned before use; here it is assigned from value.

Level B: Application

B1. Write a class Book with a title, an author, and a number of pages, and a Main that creates one book, sets its title and author only, and prints all three fields. Predict the output before you run it.

Show solution B1

B1.

java
public class Book {
    String title;
    String author;
    int pages;
}
java
public class Main {
    public static void main(String[] args) {
        Book b = new Book();
        b.title = "Java Basics";
        b.author = "Sam Lee";
        System.out.println(b.title + " / " + b.author + " / " + b.pages);
    }
}

The output is Java Basics / Sam Lee / 0, because pages was never set and an int field defaults to 0.

B2. The following file is called Item.java. Explain the compile error without compiling it, and give two different fixes.

java
public class Product {
    String name;
}
Show solution B2

B2. The class is public and called Product, but the file is Item.java, so the compiler reports that class Product is public and should be declared in a file named Product.java. Fix 1: rename the file to Product.java. Fix 2: rename the class to Item (and keep the file name). Removing public would also compile, but it is not the normal fix for a class you want to use from other files.

B3. Given the Book class from B1, what does this print, and why?

java
Book x = new Book();
Book y = new Book();
x.pages = 200;
y.pages = x.pages + 50;
x.pages = 10;
System.out.println(x.pages + " " + y.pages);
Show solution B3

B3. It prints 10 250. First x.pages is 200, so y.pages becomes 250. Then x.pages becomes 10. The two books are separate objects, so changing x afterwards does not change y. (A number copied into another variable is just a copy.)

Level C: Challenge

C1. A library wants software that records members. Read the description and list the class name and fields (with types) you would write: "A member has a name, a membership number such as M-102, an age, and whether the membership is currently active. The library also wants to know how many books the member has borrowed."

Show solution C1

C1. Class Member with: String name, String number, int age, boolean active, and int borrowedCount. The nouns in the description become the fields. A count of books is a whole number, so int fits better than double.

C2. Write the Member class from C1 and a Main that builds two members, changes the age of one of them, and prints both ages. Explain in one sentence why the second member's age did not change.

Show solution C2

C2.

java
public class Member {
    String name;
    String number;
    int age;
    boolean active;
    int borrowedCount;
}
java
public class Main {
    public static void main(String[] args) {
        Member m1 = new Member();
        Member m2 = new Member();
        m1.age = 30;
        m2.age = 25;
        m1.age = 31;
        System.out.println(m1.age + " " + m2.age);
    }
}

This prints 31 25. The second member's age did not change because each object keeps its own copy of every instance field.

Mini Challenge

Choose a thing from your own life: a phone, a recipe, a course, a pet. Do the following:

  1. Write the class with at least four fields of at least three different types. Choose a proper name and file name.
  2. Write a Main that creates two objects from it and sets some, but not all, of the fields of each.
  3. Print every field of both objects, and compare the output with your prediction before running.

Check your work: the file name matches the class name; every field is outside every method; at least one printed value is a default (0, 0.0, false, or null) that you predicted correctly.

Summary & Next Lesson

Key takeaways

  • A class is written in a file named after it: Account lives in Account.java. Class names use UpperCamelCase.
  • Fields are variables declared inside the class and outside every method. They describe what each object remembers.
  • Each object has its own copy of every instance field.
  • Unset fields get defaults: 0, 0.0, false, or null. Local variables get no default.
  • You reach an object's fields with the dot on a variable, not on the class name.

Next lesson

Setting fields one by one after new Account() is easy to forget and leaves objects half-built. The next lesson, "Constructors", shows how to create every object in a valid starting state.

Self-check

  1. In which file must public class Invoice be saved?
  2. What is the default value of an int field? Of a String field?
  3. What is the difference between a field and a local variable?
  4. If two Account objects exist and you change owner on one, what happens to the other?
  5. Why is Account.owner = "Ana"; wrong for an instance field?
Show answers
  1. In Invoice.java, with exactly that capitalization.
  2. 0 and null.
  3. A field is declared in the class, outside methods, belongs to an object, and gets a default value. A local variable is declared inside a method, lives only while the method runs, and gets no default.
  4. Nothing. Each object has its own copy.
  5. An instance field belongs to a particular object, so you need an object variable (a.owner). The class name is only the blueprint.

References

  • Oracle, The Java Tutorials, Variables. Supports the default values for fields (0, 0.0, false, null), the note that relying on them is poor style, and the rule that local variables get no default.
  • Oracle, The Java Tutorials, Creating Objects. Supports the statement that new allocates memory for a new object and returns a reference, and that declaring a variable alone does not create an object.
  • The file-name rule, the compile error text, and all program output above were produced by compiling and running the code on JDK 21 (javac 21.0.10). The UpperCamelCase convention is described in general in the Java tutorial's naming conventions; this lesson did not separately fetch that page.

Practice

Apply this lesson with the module's lab, exercises and quiz.

Lab and exercises Quiz

Marking a lesson complete is optional and you can undo it any time. Your progress stays in this browser.

Continue to next lesson

Type to search levels, phases, modules and lessons.