<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Serialization on SoftwareGarden.dev</title><link>https://softwaregarden.dev/en/tags/serialization/</link><description>Recent content in Serialization on SoftwareGarden.dev</description><generator>Hugo -- gohugo.io</generator><language>en_GB</language><copyright>© Piotr Przybył SoftwareGarden.dev CC BY-NC-SA 4.0</copyright><lastBuildDate>Fri, 15 May 2020 10:30:00 +0200</lastBuildDate><atom:link href="https://softwaregarden.dev/en/tags/serialization/index.xml" rel="self" type="application/rss+xml"/><item><title>Records in Java - reflection</title><link>https://softwaregarden.dev/en/posts/new-java/records/reflection/</link><pubDate>Fri, 15 May 2020 10:30:00 +0200</pubDate><guid>https://softwaregarden.dev/en/posts/new-java/records/reflection/</guid><description>&lt;h3 id="things-get-interesting"&gt;Things get interesting&lt;/h3&gt;
&lt;p&gt;When Java 14 was (about to be) released I saw a few discussions following more or less this schema:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Oh, records in Java, cool, finally we have automatically generated setters and getters!&lt;/li&gt;
&lt;li&gt;No, records in Java are POJOs without any setters&amp;hellip;&lt;/li&gt;
&lt;li&gt;Oh, I see&amp;hellip; Cool, finally in Java we have generated Beans, without any setters though!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now it&amp;rsquo;s time for me to write two most important things about records in Java.
The first:&lt;/p&gt;
&lt;h2 id="records-are-not-javabeans"&gt;Records are not JavaBeans&lt;/h2&gt;
&lt;p&gt;and the second:&lt;/p&gt;
&lt;h2 id="records-are-not-javabeans-1"&gt;Records are not JavaBeans&lt;/h2&gt;
&lt;p&gt;People shaken and stirred will find the explanation this below.&lt;/p&gt;
&lt;h3 id="new-kids-in-the-class"&gt;New kids in the class&lt;/h3&gt;
&lt;p&gt;In the &lt;a href="https://softwaregarden.dev/en/posts/new-java/records/can-and-cannot/"&gt;previous entry on records&lt;/a&gt; it was shown, that the records look a bit like enumeration types introduced in Java 5. Just like an &lt;code&gt;enum&lt;/code&gt; inherits directly from &lt;code&gt;java.lang.Enum&lt;/code&gt; and nothing can inherit from it, a &lt;code&gt;record&lt;/code&gt; inherits directly from &lt;code&gt;java.lang.Record&lt;/code&gt; and nothing can inherit from it as well.&lt;/p&gt;
&lt;p&gt;One of the differences is that &lt;code&gt;enum&lt;/code&gt; is a keyword, whereas &lt;code&gt;record&lt;/code&gt; (just like &lt;code&gt;var&lt;/code&gt;) is not. (Don&amp;rsquo;t focus on the syntax colouring in the browser, please. The JS plugin doesn&amp;rsquo;t support records now ;-))
.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//this won&amp;#39;t work&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; enum &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;//this works&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;var&lt;/span&gt; record &lt;span style="color:#f92672"&gt;=&lt;/span&gt; ...&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Introduction of records brought us two new methods in the &lt;code&gt;Class&lt;/code&gt; class.&lt;/p&gt;
&lt;p&gt;Just as we can check if an object is an &lt;code&gt;enum&lt;/code&gt; by using &lt;a href="https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Class.html#isEnum()"&gt;&lt;code&gt;Class.isEnum()&lt;/code&gt;&lt;/a&gt;, we can now check if an object is a record by calling &lt;a href="https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Class.html#isRecord()"&gt;&lt;code&gt;Class.isRecord()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And when the result of the &lt;code&gt;isRecord()&lt;/code&gt; tells us &amp;lsquo;it&amp;rsquo;s a record&amp;rsquo;, then we may wish to check what are the components of the record. We can get them in the form of an array calling &lt;a href="https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/Class.html#getRecordComponents()"&gt;&lt;code&gt;public RecordComponent[] Class.getRecordComponents()&lt;/code&gt;&lt;/a&gt;. This works just as getting the list of fields, methods, etc. Of course, having a &lt;code&gt;RecordComponent&lt;/code&gt;, we can try to get deeper to evaluate the possibilities. Probably the most intriguing one is &lt;a href="https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/lang/reflect/RecordComponent.html#getAccessor()"&gt;&lt;code&gt;getAccessor()&lt;/code&gt;&lt;/a&gt;, which allows us to get the value of the component.&lt;/p&gt;
&lt;p&gt;Please pay some attention to the name of this method. It&amp;rsquo;s not a &lt;em&gt;getter&lt;/em&gt;, it&amp;rsquo;s an &lt;em&gt;accessor&lt;/em&gt;. So called &lt;em&gt;gettery&lt;/em&gt; by convention have their names starting with &lt;code&gt;get&lt;/code&gt; (or &lt;code&gt;is&lt;/code&gt;).&lt;/p&gt;
&lt;h3 id="description-of-the-bean"&gt;Description of the bean&lt;/h3&gt;
&lt;p&gt;Let me follow this path. In this journey our companions will be two classes. A &amp;ldquo;typical&amp;rdquo; bean &lt;code&gt;BeanWithSetters&lt;/code&gt; and a record &lt;code&gt;ReflectionCheck&lt;/code&gt;. They look the following way (the entire code available on &lt;a href="https://github.com/pioorg/DeepDiveJava14/blob/master/src/main/java/org/przybyl/ddj14/records/s2_reflection/Reflection.java"&gt;GitHub&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;record&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;ReflectionCheck&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;int&lt;/span&gt; a, String b) {}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;class&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;BeanWithSetters&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;final&lt;/span&gt; UUID id;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; String stringField;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;BeanWithSetters&lt;/span&gt;(UUID id, String stringField) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;id&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; id;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;stringField&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; stringField;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; UUID &lt;span style="color:#a6e22e"&gt;getId&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; id;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; String &lt;span style="color:#a6e22e"&gt;getStringField&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; stringField;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;setStringField&lt;/span&gt;(String stringField) {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;this&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;stringField&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; stringField;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;What results can we expect when we make them go through the following machine?&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;BeanInfo beanInfo &lt;span style="color:#f92672"&gt;=&lt;/span&gt; Introspector.&lt;span style="color:#a6e22e"&gt;getBeanInfo&lt;/span&gt;(object.&lt;span style="color:#a6e22e"&gt;getClass&lt;/span&gt;());
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;Stream.&lt;span style="color:#a6e22e"&gt;of&lt;/span&gt;(beanInfo.&lt;span style="color:#a6e22e"&gt;getPropertyDescriptors&lt;/span&gt;()).&lt;span style="color:#a6e22e"&gt;forEach&lt;/span&gt;(System.&lt;span style="color:#a6e22e"&gt;out&lt;/span&gt;::println);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;For &lt;em&gt;JavaBean&lt;/em&gt; we get what we expect. The bean has two properties (except the class), one of which has only a &lt;em&gt;getter&lt;/em&gt; (read method), the other one has a &lt;em&gt;setter&lt;/em&gt; (write method) and a &lt;em&gt;getter&lt;/em&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;java.beans.PropertyDescriptor[name=class; values={expert=false; visualUpdate=false; hidden=false; enumerationValues=[Ljava.lang.Object;@5ce65a89; required=false}; propertyType=class java.lang.Class; readMethod=public final native java.lang.Class java.lang.Object.getClass()]
java.beans.PropertyDescriptor[name=id; values={expert=false; visualUpdate=false; hidden=false; enumerationValues=[Ljava.lang.Object;@51521cc1; required=false}; propertyType=class java.util.UUID; readMethod=public java.util.UUID BeanWithSetters.getId()]
java.beans.PropertyDescriptor[name=stringField; values={expert=false; visualUpdate=false; hidden=false; enumerationValues=[Ljava.lang.Object;@1b4fb997; required=false}; propertyType=class java.lang.String; readMethod=public java.lang.String BeanWithSetters.getStringField(); writeMethod=public void BeanWithSetters.setStringField(java.lang.String)]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What happens when we perform a similar analysis of a record?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;java.beans.PropertyDescriptor[name=class; values={expert=false; visualUpdate=false; hidden=false; enumerationValues=[Ljava.lang.Object;@5ce65a89; required=false}; propertyType=class java.lang.Class; readMethod=public final native java.lang.Class java.lang.Object.getClass()]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The only thing working like in a &lt;em&gt;JavaBean&lt;/em&gt; is getting the class of the record. The components from the record&amp;rsquo;s declaration don&amp;rsquo;t generate any getters. A &lt;em&gt;record&lt;/em&gt; is not a &lt;em&gt;JavaBean&lt;/em&gt;, Q.E.D.&lt;/p&gt;
&lt;h3 id="implications"&gt;Implications&lt;/h3&gt;
&lt;p&gt;The fact that the records are not &lt;em&gt;JavaBeans&lt;/em&gt; has some implications. Java 14 didn&amp;rsquo;t emerge in the void. There are more than 25 years of development, creating the ecosystem, tons libraries and frameworks, many developers use it every day. Summarising: it&amp;rsquo;s a mass with some momentum, which inherited an assumption that (almost) everything is a &lt;em&gt;JavaBean&lt;/em&gt; if there&amp;rsquo;s some data inside.&lt;/p&gt;
&lt;p&gt;Suddenly the records show up, being perfect for keeping data, and they don&amp;rsquo;t have any _getter_s. You know, a &lt;em&gt;VO&lt;/em&gt;, a &lt;em&gt;DTO&lt;/em&gt;, but no _getter_s. Cool, isn&amp;rsquo;t it?&lt;/p&gt;
&lt;p&gt;That&amp;rsquo;s why some libraries may &lt;em&gt;for time being&lt;/em&gt; not support them in the ideal way. (That&amp;rsquo;s why I think the concept of &lt;em&gt;preview features&lt;/em&gt; is great for everyone to recover from the shock and make needed changes.)&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s examine Jackson in version 2.10.3 (whole code on &lt;a href="https://github.com/pioorg/DeepDiveJava14/blob/master/src/main/java/org/przybyl/ddj14/records/s3_serialization/JSONifocation.java"&gt;GitHub&lt;/a&gt;). Having a record (for example this one):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;record&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SerializationRecordCheck&lt;/span&gt;(String justOneField) {}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;if we wish to turn this record into JSON using Jackson:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; ObjectMapper().&lt;span style="color:#a6e22e"&gt;writeValueAsString&lt;/span&gt;(&lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; SerializationBeanCheck(&lt;span style="color:#e6db74"&gt;&amp;#34;Bean&amp;#34;&lt;/span&gt;))&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;we have to face such a beautiful exception:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Exception in thread &amp;quot;main&amp;quot; com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
No serializer found for class SerializationRecordCheck and
no properties discovered to create BeanSerializer
(to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These four lines can explain that &amp;lsquo;records are not Java Beans&amp;rsquo; perhaps even better than &lt;code&gt;BeanInfo&lt;/code&gt;. Jackson expects that it&amp;rsquo;ll be given for serialization a JavaBean, that is: an object having some methods starting with &lt;code&gt;get&lt;/code&gt;/&lt;code&gt;is&lt;/code&gt; (except &lt;code&gt;getClass()&lt;/code&gt;). However, there are no such methods in the record!&lt;/p&gt;
&lt;p&gt;I guess the most probable scenario in the future is that Jackson (and other libraries as well) will check the result of the &lt;code&gt;isRecord()&lt;/code&gt; and will (de)serialize records differently than JavaBeans. Just as they handle enums already.&lt;/p&gt;
&lt;p&gt;Okay, but what shall be done if we badly want to use records now and they appear at the edges of our hexagon?&lt;/p&gt;
&lt;p&gt;Most probably we don&amp;rsquo;t want to set the &lt;code&gt;SerializationFeature.FAIL_ON_EMPTY_BEANS&lt;/code&gt; flag, because we&amp;rsquo;re trying to serialize the record, so we do care about the data.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;We can add the getters by hand, so they are calling accessors inside. I don&amp;rsquo;t recommend that.&lt;/li&gt;
&lt;li&gt;We can create our own serializer. It makes sense if we don&amp;rsquo;t want to keep our domain code pure, free from any annotations.&lt;/li&gt;
&lt;li&gt;We can also annotate all record&amp;rsquo;s components with&lt;code&gt;@JsonProperty&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is how the last solution looks in the code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;record&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;SerializationRecordCheck&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;@JsonProperty&lt;/span&gt; String justOneField) {}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Annotations we use for the components &amp;ldquo;are copied&amp;rdquo; for the accessors and fields in the records. So we can image the record looking the following way after being compiled:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@JsonProperty&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;private&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;final&lt;/span&gt; String justOneField;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;@JsonProperty&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;public&lt;/span&gt; String &lt;span style="color:#a6e22e"&gt;justOneField&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;return&lt;/span&gt; justOneField;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&amp;ldquo;Oh, you saw it, you saw it! They didn&amp;rsquo;t implement thre records as they should, because this librarys doesn&amp;rsquo;t work!!1one&amp;rdquo;.
Two questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Were enums or the generic types working in all the libraries right away after being introduced?&lt;/li&gt;
&lt;li&gt;Is the tail supposed to wag the dog?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A similar issue was faced in Scala when some &lt;code&gt;case class&lt;/code&gt;es were used by some Java libraries expecting getter. In Scala, to make the getter appear in the class as well, the components have to be annotated with &lt;code&gt;@BeanProperty&lt;/code&gt;. For me, it&amp;rsquo;s hard to say if that was better or worse approach. It was better, because it makes things work &amp;ldquo;right away&amp;rdquo; with the ecosystem. It was worse, because the rotting leg wasn&amp;rsquo;t chopped off. Let&amp;rsquo;s be honest: Scala doesn&amp;rsquo;t have such coverage and such reach as Java does, so Scala had to fit into Java. Does Java itself need to fit into Java?&lt;/p&gt;
&lt;p&gt;I think the subject of &amp;rsquo;lack of getters&amp;rsquo; was summarised in the best way by the records JEPs&amp;rsquo; author, Mr. B. Goetz himself: &lt;a href="http://mail.openjdk.java.net/pipermail/amber-dev/2020-May/006009.html"&gt;link&lt;/a&gt; to his e-mail.&lt;/p&gt;
&lt;h3 id="what-do-you-think"&gt;What do you think?&lt;/h3&gt;
&lt;p&gt;I think I kind of like this &amp;ldquo;no getters approach&amp;rdquo;, but I develop not only in Java, so I got used to this concept long ago. Actually I could only sigh &amp;lsquo;well, finally&amp;hellip;&amp;rsquo; Besides very accurate judgement of the Java architects I see additional benefit: the accessors simplify our lives even more. Naming is one of the two most difficults contepts in IT. Theoretically the _getter_s, as the name implies, were supposed to start with &lt;em&gt;get&lt;/em&gt; prefix. However, for a &lt;code&gt;boolean&lt;/code&gt; there could also be &lt;code&gt;is&lt;/code&gt;. That made the less thought-out solution crash already (because of the &amp;ldquo;regex diarrhea&amp;rdquo;). What if that was a &lt;code&gt;Boolean&lt;/code&gt;? Then shall we stick to &lt;code&gt;get&lt;/code&gt; or was it more like &lt;code&gt;is&lt;/code&gt;. What about field &lt;code&gt;Boolean wasDelivered&lt;/code&gt;: &lt;code&gt;getWas...&lt;/code&gt;, &lt;code&gt;isWas...&lt;/code&gt;, just &lt;code&gt;was...&lt;/code&gt; alone? With the accessors the rule is trivial.&lt;/p&gt;
&lt;h3 id="more-on-serialization"&gt;More on serialization&lt;/h3&gt;
&lt;p&gt;Some say we could have some new features in Java sooner if not &amp;lsquo;oh crap, this *** serialization&amp;rsquo;. Records can be serialized just like other objects, all we need is to implement the &lt;code&gt;Serializable&lt;/code&gt; interface. The binary format is a bit different, but the JVM handles that, we don&amp;rsquo;t have to. For the intrigued souls &lt;a href="https://github.com/pioorg/DeepDiveJava14/blob/master/src/main/java/org/przybyl/ddj14/records/s3_serialization/Serialization.java"&gt;some code to run&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;However, there is a huge change when it comes to DEserialization. Records are deserialized using the canonical constructor, we one could risk stating that Java is returning to the OOP track.&lt;/p&gt;</description></item></channel></rss>