Java Jdk Mac Os X



The abstract class java.lang.Record is the common superclass of all record classes. Every Java source file implicitly imports the java.lang.Record class, as well as all other types in the java.lang package, regardless of whether you enable or disable preview features. JDK 16 is the open-source reference implementation of version 16 of the Java SE Platform, as specified by by JSR 390 in the Java Community Process. JDK 16 reached General Availability on 16 March 2021. Production-ready binaries under the GPL are available from Oracle; binaries from other vendors will follow shortly.

Summary

Enhance the Java programming language with records, which are classesthat act as transparent carriers for immutable data. Records can be thought ofas nominal tuples.

History

Records were proposed by JEP 359and delivered in JDK 14 as apreview feature.

In response to feedback, the design was refined byJEP 384 and delivered inJDK 15 as apreview feature for a second time. The refinements for the second preview were as follows:

  • In the first preview, canonical constructors were required to be public.In the second preview, if the canonical constructor isimplicitly declared then its access modifier is the same as the record class; ifthe canonical constructor is explicitly declared then its access modifier must provideat least as much access as the record class.

  • The meaning of the @Override annotation was extended to includethe case where the annotated method is an explicitly declared accessor method fora record component.

  • To enforce the intended use of compact constructors, it became a compile-timeerror to assign to any of the instance fields in the constructor body.

  • The ability to declare local record classes, local enum classes, and local interfaceswas introduced.

This JEP proposes to finalize the feature in JDK 16, with the following refinement:

  • Relax the longstanding restriction whereby an inner classcannot declare a member that is explicitly or implicitly static. This will become legaland, in particular, will allow an inner class to declare a member that is a record class.

Additional refinements may be incorporated based on further feedback.

Goals

  • Devise an object-oriented construct that expresses a simple aggregation ofvalues.

  • Help developers to focus on modeling immutable data rather than extensiblebehavior.

  • Automatically implement. In particular, it is not agoal to address the problems of mutable classes which use the JavaBeans namingconventions.

  • It is not a goal to add features such as properties or annotation-driven codegeneration, which are often proposed to streamline the declaration of classesfor 'Plain Old Java Objects'.

Motivation

It is a common complaint that 'Java is too verbose' or has 'too much ceremony'.Some of the worst offenders are classes that are nothing more than immutabledata carriers for a handful of values. Properly writing such a and they don't want to declare yet another class.

IDEs help us to write most of the code in a from the dozens of lines of boilerplate. Writing Java codethat models a handful of values should be easier to write, to read, and toverify as correct.

Java

While it is superficially tempting to treat records as primarily being aboutboilerplate reduction, we instead choose a more semantic goal: modeling data asdata. (If the semantics are right, the boilerplate will take care of itself.)It should be easy and concise to declare adjust the state of a recordinstance, and the invariant above is not satisfied:

In addition, for all record classes the implicitly declared equals method is implemented so that it isreflexive and that it behaves consistently with hashCode for record classesthat have floating point components. Again, explicitly declared equals andhashCode methods should behave similarly.

Rules for record classes

There are numerous restrictions on the declaration of a record class incomparison to a normal class:

  • A record class declaration does not have an extends clause. The superclassof a record class is always java.lang.Record, similar to how the superclass ofan enum class is always java.lang.Enum. Even though a normal class can explicitlyextend its implicit superclass Object, a record cannot explicitly extend anyclass, even its implicit superclass Record.

  • A record class is implicitly final, and cannot be abstract. Theserestrictions emphasize that the API of a record class is defined solely by itsstate description, and cannot be enhanced later by another class.

  • The fields derived from the record components are final. This restrictionembodies an immutable by default policy that is widely applicable fordata-carrier classes.

  • A record class cannot explicitly declare instance fields, and cannot containinstance initializers. These restrictions ensure that the record header alonedefines the state of a record value.

  • Any explicit declarations of a member that would otherwise be automaticallyderived must match the type of the automatically derived member exactly,disregarding any annotations on the explicit declaration. Any explicitimplementation of accessors or the equals or hashCode methods should becareful to preserve the semantic invariants of the record class.

  • A record class cannot declare native methods. If a record class coulddeclare a native method then the behavior of the record class would bydefinition depend on external state rather than the record class's explicitstate. No class with native methods is likely to be a good candidate formigration to a record.

Beyond the restrictions above, a record class behaves like a normal class:

Java Jdk Mac Os X

  • Instances of record classes are created using a new expression.

  • A record class can be declared top level or nested, and can be generic.

  • A record class can declare static methods, fields, and initializers.

  • A record class can declare instance methods.

  • A record class can implement interfaces. A record class cannot specify asuperclass since that would mean inherited state, beyond the state described inthe header. A record class can, however, freely specify superinterfaces anddeclare instance methods to implement them. Just as for classes, an interfacecan usefully characterize the behavior of many records. The behavior may bedomain-independent (e.g., Comparable) or domain-specific, in which caserecords can be part of a sealed hierarchy which captures the domain (seebelow).

  • A record class can declare nested types, including nested record classes. If arecord class is itself nested, then it is implicitly static; this avoids animmediately enclosing instance which would silently add state to the recordclass.

  • A record class, and the components in its header, may be decorated withannotations. Any annotations on the record components are propagated to theautomatically derived fields, methods, and constructor parameters, according tothe set of applicable targets for the annotation. Type annotations on the typesof record components are also propagated to the corresponding type uses in theautomatically derived members.

  • Instances of record classes can be serialized and deserialized. However, theprocess cannot be customized by providing writeObject, readObject,readObjectNoData, writeExternal, or readExternal methods. The componentsof a record class govern serialization, while the canonical constructor of arecord class governs deserialization.

Local record classes

A program that produces and consumes instances of a record class is likely todeal with many intermediate values that are themselves simple groups ofvariables. It will often be convenient to declare record classes to model thoseintermediate values. One option is to declare 'helper' record classes that are staticand nested, much as many programs declare helper classes today. A moreconvenient option would be to declare a record inside a method, close to thecode which manipulates the variables. Accordingly we define localrecord classes, akin to the existing construct oflocal classes.

In the following example, the aggregation of a merchant and a monthly salesfigure is modeled with a local record class, MerchantSales. Using this record classimproves the readability of the stream operations which follow:

Local record classes are a particular case of nested record classes. Like nestedrecord classes, local record classes are implicitly static. This means thattheir own methods cannot access any variables of the enclosing method; in turn,this avoids capturing an immediately enclosing instance which would silently addstate to the record class. The fact that local record classes are implicitlystatic is in contrast to local classes, which are not implicitly static. Infact, local classes are never static — implicitly or explicitly — and canalways access variables in the enclosing method.

Local enum classes and local interfaces

The addition of local record classes is an opportunity to add other kinds ofimplicitly-static local declarations.

Nested enum classes and nested interfaces are already implicitly static, sofor consistency we define local enum classes and local interfaces, which arealso implicitly static.

Static members of inner classes

It iscurrently specifiedto be a compile-time error if an inner class declares a member that is explicitlyor implicitly static, unless the member is a constant variable. This means that,for example, an inner class cannot declare a record class member, since nestedrecord classes are implicitly static.

We relax this restriction in order to allow an inner classto declare members that are either explicitly or implicitly static. Inparticular, this allows an inner class to declare a static member that is arecord class.

Annotations on record components

Record components have multiple roles in record declarations. A recordcomponent is a first-class concept, but each component also corresponds to afield of the same name and type, an accessor method of the same name and returntype, and a formal parameter of the canonical constructor of the same name andtype.

This raises the question: When a component is annotated, what actually is beingannotated? The answer is, 'all of the elements to which this particularannotation is applicable.' This enables classes that use annotations on theirfields, constructor parameters, or accessor methods to be migrated to recordswithout having to redundantly declare these members. For example, a class suchas the following

can be migrated to the equivalent, and considerably more readable, record declaration:

The applicability of an annotation is declared using a @Target meta-annotation.Consider the following:

This declares the annotation @I1 that it is applicable to fielddeclarations. We can declare that an annotation is applicable to more than onedeclaration; for example:

This declares an annotation @I2 that it is applicable to both fielddeclarations and method declarations.

Returning to annotations on a record component, these annotations appear at thecorresponding program points where they are applicable. In other words, thepropagation is under the control of the developer using the @Targetmeta-annotation. The propagation rules are systematic and intuitive, and allthat apply are followed:

  • If an annotation on a record component is applicable to a field declaration,then the annotation appears on the corresponding private field.

  • If an annotation on a record component is applicable to a method declaration,then the annotation appears on the corresponding accessor method.

  • If an annotation on a record component is applicable to a formal parameter,then the annotation appears on the corresponding formal parameter of the canonicalconstructor if one is not declared explicitly, or else to the corresponding formalparameter of the compact constructor if one is declared explicitly.

  • If an annotation on a record component is applicable to a type, the annotationwill be propagated to all of the following:

    • the type of the corresponding field
    • the return type of the corresponding accessor method
    • the type of the corresponding formal parameter of the canonical constructor
    • the type of the record component (which is accessible at runtime via reflection)

Jdk Mac Download

If a public accessor method or (non-compact) canonical constructor is declaredexplicitly, then it only has the annotations which appear on it directly;nothing is propagated from the corresponding record component to these members.

A declaration annotation on a record component will not be amongst those associatedwith the record component at run time via thereflection API unless the annotation is meta-annotated with@Target(RECORD_COMPONENT).

Compatibility and migration

The abstract class java.lang.Record is the common superclass of all recordclasses. Every Java source file implicitly imports the java.lang.Record class,as well as all other types in the java.lang package, regardless of whether youenable or disable preview features. However, if your application importsanother class named Record from a different package, you might get a compilererror.

Consider the following class declaration of com.myapp.Record:

The following example, org.example.MyappPackageExample, importscom.myapp.Record with a wildcard but doesn't compile:

The compiler generates an error message similar to the following:

Both Record in the com.myapp package and Record in the java.lang packageare imported with wildcards. Consequently, neither class takes precedence, andthe compiler generates an error message when it encounters the use of the simplename Record.

To enable this example to compile, the import statement can be changed so thatit imports the fully qualified name of Record:

The introduction of classes in the java.lang package is rare but sometimesnecessary. Previous examples are Enum in Java 5, Module inJava 9, and Record in Java 14.

Java grammar

Class-file representation

The class file of a record uses a Record attribute to store informationabout the record's components:

If the record component has a generic signature that is different from theerased descriptor then there must be a Signature attribute in therecord_component_info structure.

Reflection API

We add two public methods to java.lang.Class:

  • RecordComponent[] getRecordComponents() — Returns an array ofjava.lang.reflect.RecordComponent objects. The elements of this arraycorrespond to the record's components, in the same order as they appear in therecord declaration. Additional information can be extracted from each element ofthe array, including its name, annotations, and accessor method.

  • boolean isRecord() — Returns true if the given class was declared as arecord. (Compare with isEnum.)

Alternatives

Record classes can be considered a nominal form of tuples. Instead of recordclasses, we could implement structural tuples. However, while tuples might offera lightweight means of expressing some aggregates, the result is often inferioraggregates:

  • A central aspect of Java's design philosophy is that names matter. Classesand their members have meaningful names, while tuples and tuple components donot. That is, a Person record class with components firstName and lastName isclearer and safer than an anonymous tuple of two strings.

  • Classes allow for state validation through their constructors; tuples typicallydo not. Some data aggregates (such as numeric ranges) have invariants that, ifenforced by the constructor, can thereafter be relied upon. Tuples do not offerthis ability.

  • Classes can have behavior that is based on their state; co-locating the stateand behavior makes the behavior more discoverable and easier to access. Tuples,being raw data, offer no such facility.

Dependencies

Record classes work well with another feature currently in preview, namely sealedclasses (JEP 360). For example, a familyof record classes can be explicitly declared to implement the same sealedinterface:

The combination of record classes and sealed classes is sometimes referred to asalgebraic data types.Record classes allow us to express products, and sealed classes allow us toexpress sums.

In addition to the combination of record classes and sealed classes, recordclasses lend themselves naturally to pattern matching. Becauserecord classes couple their API to their state description, we will eventuallybe able to derive deconstruction patterns for record classes as well, and usesealed type information to determine exhaustiveness in switch expressions withtype patterns or deconstruction patterns.