Skip Top Navigation Bar

Educator Briefings

Included in this document are some of the updates and features that have been made in Java from Java 8 through the most current version of Java. This document has been designed to help educators and organizations that educate students at the high school and college level to become aware of new features that should be considered as part of an introduction to Java experience. The benefits of helping educators and organizations get current and stay current come in the form of keeping pace with the evolution of Java, ensuring students are being taught the expected industry standard for how code should be written, and to increase engagement of programming students using Java.

Updates to the core Java language are being released every 6 months, in September and March.

The features included in this brief are organized by release and separated into three categories: Features of Data Oriented Programming, Features to Increase Engagement, and Features to Support Instruction. For each feature, we have included a link to the corresponding JEP page, description of the feature, and some examples for how to use the feature.

The following is a summary chart of what can be found below:

Features for Data Oriented Programming

Release Status Feature
Java 25 Finalized JEP 513: Flexible Constructor Bodies
Java 22 Finalized JEP 456: Unnamed Variables & Patterns
Java 21 Finalized JEP 441: Pattern Matching for switch
Java 21 Finalized JEP 440: Record Patterns
Java 17 Finalized JEP 409: Sealed Classes
Java 16 Finalized JEP 395: Records
Java 14 Finalized JEP 361: Switch Expressions
Java 10 Finalized JEP 286: Local-Variable Type Inference

Features to Increase Engagement

Release Status Feature
Java 25 Preview JEP 488: Primitive Types in Patterns, instanceof, and switch
Java 21 Finalized JEP 431: Sequenced Collections
Java 16 Finalized JEP 394: Pattern Matching for instanceof
Java 15 Finalized JEP 378: Text Blocks
Java 11 Finalized JEP 323: Local-Variable Syntax for Lambda Parameters
Java 9 Finalized JEP 269: Convenience Factory Methods for Collections
Java 8 Finalized JEP 126: Lambda Expressions & Virtual Extension Methods

Features to Support Instruction

Release Status Feature
Java 25 Finalized JEP 512: Compact Source Files and Instance Main Methods
Java 23 Finalized JEP 467: Markdown Documentation Comments
Java 22 Finalized JEP 458: Launch Multi-File Source-Code Programs
Java 14 Finalized JEP 358: Helpful NullPointerExceptions
Java 11 Finalized JEP 330: Launch Single-File Source-Code Programs
Java 9 Finalized JEP 222: jshell: The Java Shell (Read-Eval-Print Loop)

Which new features should be incorporated into Introductory Computer Science courses?

This article provides an overview of features that are recommended for intro to CS courses to include.

Recommended Features for Intro CS

Categories:

The features listed in this section are recommended for inclusion in introductory computer science courses and data structures courses (i.e., CS 1 or CS 2 courses) that include a focus on data-oriented programming. These features reflect current, more modern ways of introducing programming using Java, beyond just object-oriented programming.

Features:

Originally previewed in JEP 447, JEP 482, and 492.

Constructors will be allowed to include statements that do not reference the instance being created prior to an explicit constructor call such as super(…) and this(…).

An example of a good use of this feature would be as a check on parameters being passed in prior to using them.

Uses in Intro to CS

Recommended to be included once finalized.

Learn more: JEP 513: Flexible Constructor Bodies

When variable declarations or nested patterns are required but not used, an underscore (' _ ') can be used instead.

try..catch Example

try {
  //something
} catch (Exception ex) {
   //error message
} 

The variable ex isn’t being used, so we could re-write as:

try {
  //something
} catch (Exception _ ) {
   //error message
}

Record Example

Another example for when you want to grab a specific value in a record, but do not need the other data.

Your Turn

Try this in the Java Playground.

Uses in Intro to CS

This would be recommended for any courses that include data in their course. Data science courses would benefit from the use of records and record patterns. Incorporating real-world data has the potential to increase engagement for students.

Learn more: JEP 456: Unnamed Variables & Patterns

Resources

This feature has considerable interaction with Record Patterns JEP 440: Record Patterns, which is covered above.

Pattern Matching for Switch

Similar to what we saw in Record Patterns, the Pattern Matching for Switch includes:

  1. a type check in the form of case checks;
  2. creation and assignment of variable; and
  3. typecasting of the variable.

Your Turn

Try the code in the Java Playground!

Pattern Matching for Switch with Lambda Notation

Combine with Unnamed Patterns and Variables (JEP 456: Unnamed Variables & Patterns) and rule switching with Lambda notation.

Your Turn

Try it in the Java Playground.

Since we are using a sealed interfaces that only allows implementation with Dog and Cat, a default statement is not necessary.

Sealed Classes were finalized in the JDK 17 (JEP 409: Sealed Classes).

Uses in Intro to CS

This would be recommended for any courses that include data in their course. Data science courses would benefit from the use of records and record patterns. Incorporating real-world data has the potential to increase engagement for students.

Learn more: JEP 441: Pattern Matching for switch

Resources

Record Patterns and instanceof

This is an extension of JEP 394: Pattern Matching for instanceof, which allowed the instanceof operator to take a type pattern and perform pattern matching.

A pattern consists of a test and a set of local variables, known as pattern variables.

A type pattern consists of a test for the type of variable and a pattern variable.

In the new way, a instanceof Dog dog completes the following:

  1. the type check;
  2. the creation and assignment of variable dog; and
  3. casts a to type Dog.

Your Turn

Try it in the Java Playground.

Pattern Matching to Access Instance Values

Rather than creating a new Dog dog, we can create variables for the instances variables of Dog we are actually going to use.

NOTE: The Animal interface is a sealed interface. Sealed Classes were finalized in the JDK 17 (JEP 409: Sealed Classes).

Your Turn

Try it in the Java Playground.

Uses in Intro to CS

This would be recommended for any courses that include data in their course. Data science courses would benefit from the use of records and record patterns. Incorporating real-world data has the potential to increase engagement for students.

Learn more: JEP 440: Record Patterns

Resources

Sealed classes and interfaces restrict which other classes or interfaces can extend or implement them. This allows the originator to control which code has the responsibility for implementing it.

Using sealed classes and interfaces, support pattern matching for switch (JEP 441: Pattern Matching for switch) made final in the JDK 21 by allowing switch cases to be exhaustive without the need for a default clause.

For example, the Animal interface below allows for only Dog and Cat to implement it:

sealed interface Animal permits Dog, Cat {
}

Uses in Intro to CS

This would be recommended for any courses that include data in their course. Data science courses would benefit from the use of records and record patterns. Incorporating real-world data has the potential to increase engagement for students.

Learn more: JEP 409: Sealed Classes

Resources

In data-oriented programming, records allow us to treat data as non-modifiable, which is generally not the case for objects. Records are simply the right tool for dealing with non-modifiable data.

Records are simple to create and are meant to be used with non-modifiable data. The way in which they are designed protects the data from being altered making it the safer and right solution.

Consider a common CS 1 Project to write a Point class:

public class Point {
    private int x; 
    private int y;

    public Point() {
        x = 0; 
        y = 0;
    }

    public Point(int myX, int myY) {
        x = myX;
        y = myY;
    }

    public int getX() { 
        return x; 
    }

    public int getY() { 
        return y; 
    }
}

This class can be rewritten using a record as follows:

record PointRecord(int x, int y) {
}

Parts of a Record

  • A constructor:

    PointRecord(int x, int y)
    
  • Accessor methods:

    x()
    y()
    
  • Records also include the following automatically:

    toString()
    hashCode()
    equals()
    

Additional methods can be included in Records as well.

Your Turn

Try it in the Java Playground.

Uses in Intro to CS

This would be recommended for any courses that include data in their course. Data science courses would benefit from the use of records and record patterns. Incorporating real-world data has the potential to increase engagement for students.

Learn more: JEP 395: Records

Resources

Switch Expressions with yield

Extends the switch semantics. Now a switch can be an expression.

For switch expressions, yield is used to return the value of the expression. There is no fall through in switch expressions.

Your Turn

Try it in the Java Playground.

Switch Expressions with Lambda-Style Arrow Notation

The lambda-style arrow notation ( -> ) specifies the return the value of the expression. As it is an expression, there is no fall through.

Your Turn

Try it in the Java Playground.

Uses in Intro to CS

This would be recommended for any courses that include data in their course. Data science courses would benefit from the use of records and record patterns. Incorporating real-world data has the potential to increase engagement for students.

Learn more: JEP 361: Switch Expressions

Resources

In cases where the type of the variable can be inferred, the keyword var can be used instead of the type. These cases include local variables being declared with initializers, enhanced for-loops indexes, and index variables declared in traditional for loops. You can also use var for arguments in lambda expressions and for pattern variables in record patterns.

Some examples of variable declarations are as follows:

var brady = new Dog();
var wordlist = new ArrayList<String> ();

An example of an enhanced for-loop is as follows:

for (var word : wordlist) { ...

Uses in Intro to CS

The use of var could be incorporated in the earliest introductory computer science course.

Some examples of improper uses of var are as follows:

  • var wordlist;

Without an initialization, the compiler is unable to infer the type of wordlist.

  • var brady = null;

Since null can be assigned to objects of any type, the compiler is unable to infer the type of brady.

Learn more: JEP 286: Local-Variable Type Inference

Resources

The following features might be useful in creating more engaging lab experiences for students and foster an increased engagement.

Originally previewed in JEP 455: Primitive Types in Patterns, instanceof, and switch (Preview) and JEP 488: Primitive Types in Patterns, instanceof, and switch (Second Preview).

This preview features is an enhancement to pattern matching to extend the instanceof (JEP 394: Pattern Matching for instanceof) and switch (JEP 441: Pattern Matching for switch) to work with primitive variables.

Primitive Patterns and instanceof

Previously, you could only use instanceof on reference types, to answer the question of whether an object was of a specific type. With primitive patterns you can use instanceof with primitive types, to answer the question of whether the variable can be represented by a specific type without any loss of precision or data.

Your Turn

Try it in the Java Playground.

Primitive Patterns and switch

We can now switch over all primitive types. If we are using a switch expression, then we will need to be sure that all cases are being covered. We do this by including cases with additional guards.

Your Turn

Try it in the Java Playground.

  • update the value of x to try a negative value and 0.

Some important things to note here. The reserved word when is being used as a condition for the second case statement. We cannot use when again in the third case as it would cause the compiler to detect that the switch statement is not exhaustive. We use the last case statement as an option for all cases that aren’t the first two cases. This makes the switch exhaustive as required.

Also, note that since we are not using the variable in the third case, we can simply use an unnamed variable (_) as a placeholder. Please see JEP 456: Unnamed Variables & Patterns for more information on unnamed variables.

Switch Expression instead of Other Methods

We can also use switch expression instead of the ternary conditional operator (?:) or equivalent if..else statement.

Your Turn

Try it in the Java Playground.

  • Three ways to determine if a value is even or odd are presented.
  • update the value of x to test for even values.

Using Primitive Types in Switch Statement

If we would rather report out on this information, we could write a switch statement.

A ternary conditional operator would not allow for a statement, since it uses expressions only.

We could use an if..else statement to report the inforamtion as well.

Your Turn

Try it in the Java Playground.

  • Update the value of x to test for even values.

Uses in Intro to CS

Switch statements and switch expressions in general may help increase students understanding of conditionals and in some cases are better than using a long series of if..else statements. Students who learn ternary conditional operators, may choose to write their solutions using switch expressions instead. This feature has the potential to increase engagement for students.

Learn more: JEP 488: Primitive Types in Patterns, instanceof, and switch (Second Preview)

Resources

In addition to the Collection class, the ArrayList class now also implements the SequencedCollection. The SequencedCollection, contains the following new methods which would be considered legal Java during the AP Computer Science A exam:

  • addFirst(E e) – adds an element as the first element of this collection
  • addLast(E e) – adds an element as the last element of this collection
  • getFirst() – Gets the first element of this collection
  • getLast() – Gets the last element of this list
  • removeFirst() – Removes and returns the first element of this collection
  • removeLast() – Removes and returns the last element of this collection
  • reversed() – Returns a reverse-order view of this collection

Uses in Intro to CS

This new content could impact course work where students are asked to access or move specific elements or to add element to an ArrayList by adding each element to the front of the list. This feature could have an impact on specific sorting algorithms.

Learn more: JEP 431: Sequenced Collections

Resources

A pattern consists of a test and a set of local variables, known as pattern variables.

A type pattern consists of a test for the type of variable and a pattern variable.

sealed interface Animal permits Dog, Cat {
}

ArrayList<Animal> animList = new ArrayList<>();   

for (Animal a: animList) {
   //Old way 
   if (a instanceof Dog) {
      Dog dog = (Dog)a;
      //do something with dog
   }
   //New way
   if (a instanceof Dog dog) {
         //do something with dog
   }
}

Uses in Intro to CS

This would be recommended for any courses that include data in their course. Data science courses would benefit from the use of records and record patterns. Incorporating real-world data has the potential to increase engagement for students.

Learn more: JEP 394: Pattern Matching for instanceof

Resources

A text block is a multi-line string literal that avoids the needs for most escape sequences, automatically formats the string in a predictable way, and gives the developer control over the format when desired.

The opening delimiter is a sequence of three double quote characters (""") followed by zero or more white spaces followed by a line terminator.

The content begins at the first character after the line terminator of the opening delimiter and ends at the last character before the first double quote for the closing delimiter.

The closing delimiter is a sequence of three double quote characters (""").

Your Turn

Try it in the Java Playground.

  • The following all print the same result.

While a line terminator is required after the opening delimiter, it is not required before a closing delimiter.

The following will cause an error since there is no line terminator before the word first.

System.out.println("""first
second
third
""");

Uses in Intro to CS

Could impact how students respond to coursework and questions that require them to create strings using a particular spacing.

Learn more: JEP 378: Text Blocks

Resources

Relates to JEP 286: Local-Variable Type Inference.

This feature allows the use of var when establishing the parameters in lambda expressions.

For example, consider the following Computations interface:

public interface Computations {
   public double operation(double first, double second);
}

We can define the functionality of operation as follows:

Computations subt = (f, s) -> f - s;
System.out.println(subt.operation(3, 2));

We can also define the functionality of operation using var as follows:

Computations subt = (var f, var s) -> f - s;
System.out.println(subt.operation(3, 2));

This aligns the syntax of the formal parameters in lambda expressions with the syntax of a local variable declaration.

Uses in Intro to CS

For courses that are currently incorporating lambda, this feature should be included in the course of study.

Learn more: JEP 323: Local-Variable Syntax for Lambda Parameters

This feature allows for small non-modifiable sets of data to be set to Lists, Maps, and Sets, using the of method.

For example, instead of adding the following names to a student roster by calling the add method repeated, such as:

List<String> roster = new ArrayList<>();
roster.add("Mark");
roster.add("Liam");
roster.add("Aidan");
roster.add("Emelia");

If the roster is non-modifiable, meaning we won’t need to add, remove, or change any of the elements, we can create the list using the of method. This is similar to using an initializer list with arrays. For example:

List<String> names = List.of("Mark", "Liam", "Aidan", "Emelia");

Note that you cannot add any null values to list created with the List.of() factory method.

Uses in Intro to CS

This would be recommended for any courses that include data in their course. Data science courses would benefit from the use of records and record patterns. Incorporating real-world data has the potential to increase engagement for students.

Learn more: JEP 269: Convenience Factory Methods for Collections

Full details on Project Lambda can be found here: OpenJDK: Project Lambda

Lambda’s allow programmers to implement an interface that contains one method, without having to write the full class. They consist of a parameter list, the arrow token, and a return value based on the body of the code statements.

For example, consider the following Computations interface:

public interface Computations {
    public double operation(double first, double second);
}

We could create classes AdditionComputation and MultiplyComputation as well as several others, such as:

public class AdditionComputation implements Computations {
   @Override
   public double operation(double first, double second) {
      return first + second;
   }
}

public class MultiplyComputation implements Computations {
   @Override
   public double operation(double first, double second) {
      return first * second;
   }
}

To use these classes, we might write the following:

public class LambdaTester {
   public static void main(String[] args) {
      AdditionComputation add = new AdditionComputation();
      MultiplyComputation mult = new MultiplyComputation();
      System.out.println(add.operation(5.3, 2.3));
      System.out.println(mult.operation(5, 3));
   }
}

This would mean that every time we wanted to provide unique functionality for the operation method in Computations and use it, we would need to first create a class that implements Computations, then create an instance of this class, and finally call operation.

If we use lambda, we can create an instance of Computations that can be used to call the operation method and provide the functionality as part of declaring and creating that instance.

For example:

Computations subt = (f, s) -> f - s;
System.out.println(subt.operation(3,2));

Uses in Intro to CS

The use of lambda would be appropriate in a course where interfaces are being used. Additionally, it could easily be incorporated into any course that uses data and ArrayList. Some examples of the ArrayList forEach method are as follows.

The forEach method of the Collection interface takes a Consumer object as a parameter. Consumer is an interface that has an accept method that needs to be implemented. The accept method performs an operation on the given argument.

The following examples pass the implementation of the method accept as an argument to the forEach method. The accept method is void, so we have included the output statement as part of the implementation.

The following prints out all of the values of the list:

names.forEach((n) -> System.out.println(n));`

The following prints out all of the values that have a length greater than 4:

names.forEach((n) -> {
  if (n.length() > 4) {
      System.out.println(n);
  }
});

The following prints out the values that start with the letter "A":

names.forEach((n) -> {
   String first = n.substring(0,1);
   if (first.equals ("A")) {
      System.out.println(n);
   }
});

The implementation of a lambda expression can use variable defined outside of itself, as long as they are final, or at least not modified. In that case, the compiler can make this variable final for you. These non-final variable that can be made final by the compiler are called effectively final variables. The following code wouldn’t work because it requires the use of a local variable, and tries to modify it. So this local variable is not final, and cannot be made final.

int sum = 0; 
names.forEach((n) -> {
   sum += n.length();
});
System.out.println(sum/names.size());

Learn more: JEP 126: Lambda Expressions & Virtual Extension Methods

Resources

The following features could impact the way the course is taught. Many of these features make introducing new topics easier for students. This section will also include deprecated APIs that will no longer be supported in the future, yet we know that some teachers might still be using these materials.

Features:

Originally previewed in JEP 445: Unnamed Classes and Instance Main Methods (Preview), second preview in JEP 463: Implicitly Declared Classes and Instance Main Methods (Second Preview), third preview in JEP 477: Implicitly Declared Classes and Instance Main Methods (Third Preview), and final preview in JEP 495: Simple Source Files and Instance Main Methods (Fourth Preview).

Smaller Programs Written Succinctly

Great for beginners just learning Java, Compact Source Files and Instance Main Methods allows new and experienced programmers to write smaller programs succinctly, without the need for constructs intended for programming in the large. This is great for beginners and those who want to rapidly prototype or try code snippets.

This preview feature includes a new class IO that is part of the java.lang package and is implicitly made available for input and output. The static methods in this class are based on System.out and System.in.

Instead of:

public class MyClass {
   public static void main(String [] args) {
       System.out.println ("Java Rocks!");
   }
}

We can write the following:

void main() {
   IO.println ("Java Rocks!");
}

Automatically Imports java.base

It also automatically imports the top-level classes in the java.base module. This includes java.util which will allow for the use of ArrayList without import statements. Other useful classes that are included and could be incorporated in an introductory CS course to raise engagement are: java.time, java.text, java.io, and java.math.

Uses in Intro to CS

This content is shared as an instructional tool to help get students into the core Java content more quickly. It is similar to products that include an interactions pane with the added benefit of the code being in a .java file so it can be saved, tweaked, and run multiple times without having to re-type.

Learn more: JEP 495: Simple Source Files and Instance Main Methods (Fourth Preview)

In addition to being able to write documentation comments in JavaDoc and HTML, you can now use Markdown. Markdown is typically much easier to write and read within the code and translates to HTML.

Uses in Intro to CS

Comments written in markdown are easier to read and write within the code than HTML. If you would like to include more formatting in comments for starter code, using markdown would be the right tool to use.

Learn more: JEP 467: Markdown Documentation Comments

Expands prior JEP 330: Launch Single-File Source-Code Programs by allowing multiple files to be compiled and run at the same time, rather than needing to compile the files first and then run them.

Uses in Intro to CS

Multi-file and single-file source-code launcher provides instructors and students with more options in terms of tools that can be used and how they approach introducing concepts to students.

Single-file and multi-file source-code works well in jShell or IDEs that leverage jShell.

Learn more: JEP 458: Launch Multi-File Source-Code Programs

A helpful upgrade to NullPointerException errors. At the point in a program where code tries to access a null reference, an exception message will be displayed that names which variable was null.

Uses in Intro to CS

A helpful instructional tool that gives a little more information and can help identify the source of the exception better.

Learn more: JEP 358: Helpful NullPointerExceptions

This new feature allows multiple classes to be saved in the same .java file.

For example, saved in the DogTester.java file:

class Dog {
   private String name; 
   private String breed;
   private double weight; 

   public Dog(String n, String b, double w) {
      // body  
   }
}
public class DogTester {
   public static void main(String[] args) {
      Dog d = new Dog("Brady", "Whippet", 42); 
      ...
   }
}

The name of the file should be the same as the class that contains the main method.

You can add multiple classes or records. For example:

public class DogTester {
   public static void main(String [] args) {
       Dog d = new Dog(new LicName("Brady the Blue Brindle", 
              "Brady"), "Whippet", 46.7);
       System.out.println(d);
   }
}

record Dog(LicName name, String Breed, double weight) {
}

record LicName(String fullName, String nickname) {
}

Uses in Intro to CS

Single-file source-code launcher provides instructors with more options in terms of tools that can be used and how they approach introducing concepts to students.

Single-file source-code works well in jShell, IDEs that leverage jShell, and the Java Playground.

Learn more: JEP 330: Launch Single-File Source-Code Programs

JShell allows for rapid prototyping of lines of code, or snippets.

Requires the use of the command prompt to run the program code.

Uses in Intro to CS

This feature could be used in the earliest introductory computer science course as a way to introduce new topics and quickly demonstrate the functionality associated with particular snippets of code.

Learn more: JEP 222: jshell: The Java Shell (Read-Eval-Print Loop)