Wednesday, February 17, 2021

More restrictions with using record classes

Instance Variables not allowed

A record class cannot have instance variables defined in its body. 

The components in the record header gets converted to instance variables in its generated class. But we cannot declare an instance variable explicitly - either matching the one defined in the header or a completely new one. 

The below code will not compile

record Cat(String color) {
    
    // Not allowed - Declaring the instance variable for a record component explicitly
    private final String color; 

    // Not allowed - Declaring an instance variable not listed in the record header
    private final String breed; 

}

This code throws a compilation error stating "field declaration must be static" and a message "(consider replacing field with record component)"

So, the only set of instance variables that we can have in a record class is the components included in its header definition.

Instance initialization blocks not allowed

Also not allowed are instance initialization blocks inside the record body

record Cat(String color) {

    // Not allowed - Having instance initialization block
    {
        System.out.println("Creating an instance");
    }
}

Above code throws an error stating "instance initializers not allowed in records" during compilation.

Native methods not allowed

One more restriction that applies for record classes is that it cannot have any native methods defined in it

record Cat(String color) {
    
    // Not allowed - implementing a native method inside a record
    native void iAmNative();
}

This throws a compilation error "modifier native not allowed here"

Usage of APIs or Classes named "Record"

This is more of a convention to be taken care of when using any API or Class with the name as Record

This stems from the fact that Java language imports all classes in java.lang package using 

import java.lang.*;

With the introduction of java.lang.Record which is the base class of all record classes, the name Record conflicts with the Record class imported from java.lang

For example, lets say we have a our custom class named "Record" defined inside "test" package

package test;

public class Record {

}

If we want to import and use this class, as in the below code

import test.*;

class Main {
    public static void main(String args[]) {
        Record rec = new Record();
    }
}

This would give a compilation error stating "reference to Record is ambiguous"

Import with fully qualified name to get around this problem. The below code makes right reference to the Record class 

import test.Record;

class Main {
    public static void main(String args[]) {
        Record rec = new Record();
    }
}

We will get into exploring some more features of record classes in the next post.


Sample code used in this post can be downloaded from https://github.com/ashokkumarta/awesomely-java/tree/main/2021/02/Language-Features/Record/More-restrictions

No comments:

Post a Comment