Skip to main content

Java Keywords (Part XXIV): native

Java keyword list abstract continue for new switch assert default goto * package synchronized boolean do if private this break double implements protected throw byte else import public throws case enum instanceof return transient catch extends int short try char final interface static void class finally long strictfp volatile const * float native super while Keyword marked with an asterisk (*) are keywords that, although valid, are not used by programmers. This is the last chapter of the Java Keyword series. This is probably the keyword I have used the least. In my 20 year career as a software developer, I have used this keyword once, and that was to make some addition to legacy code. The keyword native is a method modifier . Basically, it is a keyword that can only be applied to methods. According to the Java Language Specification (JLS), A method that is native is implemented i...

Java Keywords Addendum: The Java Record

Since originally my Java series was based on Java 8, it did not include a new keyword introduced later on. For that reason, I decided to post an addition to the Java Keyword series to include the Java record keyword. Introduced in Java 14, the purpose of this keyword is to eliminate all the boilerplate code when creating a Java POJO. For example,

public class Student {
  private String name;
  private int id;
  
  public Student(String name, int id) {
    this.name = name;
    this.id = id;
  }
  
  public String getName() {
    return name;
  }
  
  public int getId() {
    return id;
  }
  
  public void setName(String name) {
    this.name = name;
  }
  
  public void setId(int id) {
    this.id = id;
  }
}
can be replaced simply with a record that looks like this:

public record Student(String name, int id){ }
And not only it replaces the boilerplate code I showed you, it also automatically overrides Object#equals(Object), Object#hashCode(), and Object#toString().

Usage

Here is a simpe example of a record declaration as a .java file.

Student.java


public record Student(String name, int id){ }
Main.java

public class Main {
  public static void main(String[] args) {
    Student s1 = new Student("John", 1);
    Student s2 = new Student("Mary", 2);
    Student s3 = new Student("Hector", 3);
    Student s4 = s2;
    
    System.out.println("Student 1's name: " + s1.name());
    System.out.println("Student 2's id: " + s2.id());
    System.out.println("Student 3: " + s3);
    System.out.println("Student 2 is equal to 4: " + s2.equals(s4));
  }
}
The first thing you would notice is that, using a record object is basically the same as using a class object. A Java record is a class. It is a class without boilerplate code. A much more simplified form of a class. It does have caveats, which are outlined in the "Restrictions" section below.

Another thing you should notice is that the getter methods do not have the prefix "get" in them. It is a direct derivation of the variable name. Is this a good thing or a bad thing? I am somewhat neutral, but leaning towards this convention. I am an old developer who is quite used to the getter/setter naming convention. But even I know this can get somewhat confusing when it comes to boolean fields. It seems to me that the developer community is almost split in the middle when it comes to the prepending boolean getter methods with "is" versus "get". To me, not prepending seems more sensible. Simpler. If you want to know the getter method name for a particular field, simply look for that field in the constructor.

The output of this example is as shown below:


Student 1's name: John
Student 2's id: 2
Student 3: Student[name=Hector, id=3]
Student 2 is equal to 4: true
The first two print out statements illustrate the use of the getter methods for the two fields in the class. The third print out illustrates the use of the default overridden Object#toString() method. The fourth print out statement illustrate the use of the implementation of Object#equals(Object) and Object#hashCode(). All of that packaged in this simple record declaration

public record Student(String name, int id){ }
This looks trivial when you look at a simple POJO with a two fields. But just think for a second how much time (compounded) it saves you over the life of a project. Not long ago, I was workinng alone in a project where I needed to create, initially, about 4 to 5 POJOs. It would have taken me maybe close to an hour to write all these by hand. Even with IDEs like IntelliJ or Eclipse, it would have taken me many minutes to create the classes and declared the fields, then go to the IDE menu to create getters and setters, override Object#equals(Object) and Object#hashCode(), and then override Object#toString(). It took me seconds to create the records.

Restrictions

There are some caveats that you must be aware when using records.
  1. Java records cannot be extended. They are implicitly final. For this reason, they cannot be abstract.
  2. Java records are immutable. Therefore, their inner values cannot be changed after instantiation.
  3. Because records are immutable, they contain no setter methods. Values must be passed through the constructor
For me, these constraints are more of a benefit than a constraint. Consider the immutable nature of a record. This means that they are inherently thread-safe. This benefit makes it easier to share this object across mulitple threads without worrying about changing internal values, proper ways to synchronize, slowing down the application when applying locks, etc. However, with every benefit, there are some drawbacks. For example, if the data being held by the object changes frequently, this means you will need to create a new record each and every time the data changes which can present challenges when garbage collecting. As a developer, it is up to you to decide what is the best approach for your application. In some cases, using records will greatly improve your application. In other cases, it might be of a hinderance to use them. Arm yourself with what you learn here and decide for yourself.

I hope this short article was of some benefit to you. For my next topic, I will get into customizing Java records and implementing interfaces with records. Good luck and stay tuned!

Comments

Popular posts from this blog

Implementing Interfaces with Java Records

If you have not read my article on Java records and do not know about this topic, please read my blog titled " Customizing Java Records " first and then come back to this one. Now that you know how to customize Java records, implementing an interface using Java records should be very easy to understand. If you don't know about interfaces in Java, you can read more on my article about interfaces. The recipe for implementing an interface is simply an expansion of what you learned in my previous blog on how to customize a Java record. Following our Rectangle example, let's create an interface with the same two methods we used before. public interface Shape { double area(); double perimeter(); } Now, let's further customize the previous example by doing two things: Add implements Shape at the end of the record declaration (after the record constructor), and Add @Override to the existing methods to ensure these methods com...

Customizing Java Records

If you have not read my article on Java records and do not know about this topic, please read my blog titled " Java Keywords Addendum: The Java Record " first and then come back to this one. What is a customization of a record? A customization of a record is simply the addition of code inside the body of the class. Before proceeding further, let's recap important aspects of a Java Record: Java records are immutable Because of item 1 above, you cannot add new fields unless defined in the record constructor Java records already override: Object#equals(Object) and Object#hashCode() , and then override Object#toString() You could redefine overridden methods as part of your customization if you would like. For example, if you want a fancier implementation of the Object#toString() method, you could do so. Let's look at our first customization example. Using the example from my previous blog, public record Student(...

Object-Oriented Programming Basics: What is in a Class?

EDITORIAL NOTE : This article was published briefly back in 2016 and quickly set back to draft because I wasn't happy with its contents. It is a shame that it was taking me three years to revisit this topic and work on a new and improved version. At least, I'm hoping it will be to the liking you the reader. Keep in mind that the opening paragraph will still read as if I just wrote it for my (former) students at Texas Wesleyan. I started working on lecture on the topic of Object-Oriented (OO) Programming by gathering some material, old and new, when I realized this might be good and simple post for my second attempt at blogging. To be completely honest, in the 8 hours I spent collecting information and preparing material for this week's lecture, I realized I still made some of the mistakes I am about to blog about. I am actually hoping I can write a series of postings regarding Object-Oriented Programming (OOP). But to do so, I must start from the very beginning. ...