Skip to content

Commit cc05530

Browse files
author
Roger Riggs
committed
8371732: [redo] Change java.time month/day field types to 'byte'
Reviewed-by: darcy, alanb
1 parent 91b97a4 commit cc05530

File tree

7 files changed

+124
-24
lines changed

7 files changed

+124
-24
lines changed

src/java.base/share/classes/java/time/LocalDate.java

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,8 @@
7979
import java.io.IOException;
8080
import java.io.InvalidObjectException;
8181
import java.io.ObjectInputStream;
82+
import java.io.ObjectStreamField;
83+
import java.io.Serial;
8284
import java.io.Serializable;
8385
import java.time.chrono.ChronoLocalDate;
8486
import java.time.chrono.IsoEra;
@@ -142,6 +144,22 @@
142144
public final class LocalDate
143145
implements Temporal, TemporalAdjuster, ChronoLocalDate, Serializable {
144146

147+
/**
148+
* For backward compatibility of the serialized {@code LocalDate.class} object,
149+
* explicitly declare the types of the serialized fields as defined in Java SE 8.
150+
* Instances of {@code LocalDate} are serialized using the dedicated
151+
* serialized form by {@code writeReplace}.
152+
* @serialField year int The year.
153+
* @serialField month short The month-of-year.
154+
* @serialField day short The day-of-month.
155+
*/
156+
@Serial
157+
private static final ObjectStreamField[] serialPersistentFields = {
158+
new ObjectStreamField("year", int.class),
159+
new ObjectStreamField("month", short.class),
160+
new ObjectStreamField("day", short.class)
161+
};
162+
145163
/**
146164
* The minimum supported {@code LocalDate}, '-999999999-01-01'.
147165
* This could be used by an application as a "far past" date.
@@ -178,15 +196,15 @@ public final class LocalDate
178196
/**
179197
* @serial The year.
180198
*/
181-
private final int year;
199+
private final transient int year;
182200
/**
183201
* @serial The month-of-year.
184202
*/
185-
private final short month;
203+
private final transient byte month;
186204
/**
187205
* @serial The day-of-month.
188206
*/
189-
private final short day;
207+
private final transient byte day;
190208

191209
//-----------------------------------------------------------------------
192210
/**
@@ -490,8 +508,8 @@ private static LocalDate resolvePreviousValid(int year, int month, int day) {
490508
*/
491509
private LocalDate(int year, int month, int dayOfMonth) {
492510
this.year = year;
493-
this.month = (short) month;
494-
this.day = (short) dayOfMonth;
511+
this.month = (byte) month;
512+
this.day = (byte) dayOfMonth;
495513
}
496514

497515
//-----------------------------------------------------------------------

src/java.base/share/classes/java/time/MonthDay.java

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@
6969
import java.io.IOException;
7070
import java.io.InvalidObjectException;
7171
import java.io.ObjectInputStream;
72+
import java.io.ObjectStreamField;
73+
import java.io.Serial;
7274
import java.io.Serializable;
7375
import java.time.chrono.Chronology;
7476
import java.time.chrono.IsoChronology;
@@ -133,6 +135,20 @@ public final class MonthDay
133135
*/
134136
@java.io.Serial
135137
private static final long serialVersionUID = -939150713474957432L;
138+
139+
/**
140+
* For backward compatibility of the serialized {@code MonthDay.class} object,
141+
* explicitly declare the types of the serialized fields as defined in Java SE 8.
142+
* Instances of {@code MonthDay} are serialized using the dedicated
143+
* serialized form by {@code writeReplace}.
144+
* @serialField month int The month-of-year.
145+
* @serialField day int The day-of-month.
146+
*/
147+
@Serial
148+
private static final ObjectStreamField[] serialPersistentFields = {
149+
new ObjectStreamField("month", int.class),
150+
new ObjectStreamField("day", int.class)
151+
};
136152
/**
137153
* Parser.
138154
*/
@@ -144,13 +160,13 @@ public final class MonthDay
144160
.toFormatter();
145161

146162
/**
147-
* @serial The month-of-year, not null.
163+
* @serial The month-of-year.
148164
*/
149-
private final int month;
165+
private final transient byte month;
150166
/**
151167
* @serial The day-of-month.
152168
*/
153-
private final int day;
169+
private final transient byte day;
154170

155171
//-----------------------------------------------------------------------
156172
/**
@@ -319,8 +335,8 @@ public static MonthDay parse(CharSequence text, DateTimeFormatter formatter) {
319335
* @param dayOfMonth the day-of-month to represent, validated from 1 to 29-31
320336
*/
321337
private MonthDay(int month, int dayOfMonth) {
322-
this.month = month;
323-
this.day = dayOfMonth;
338+
this.month = (byte) month;
339+
this.day = (byte) dayOfMonth;
324340
}
325341

326342
//-----------------------------------------------------------------------

src/java.base/share/classes/java/time/YearMonth.java

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@
7878
import java.io.IOException;
7979
import java.io.InvalidObjectException;
8080
import java.io.ObjectInputStream;
81+
import java.io.ObjectStreamField;
82+
import java.io.Serial;
8183
import java.io.Serializable;
8284
import java.time.chrono.Chronology;
8385
import java.time.chrono.IsoChronology;
@@ -137,6 +139,20 @@ public final class YearMonth
137139
*/
138140
@java.io.Serial
139141
private static final long serialVersionUID = 4183400860270640070L;
142+
143+
/**
144+
* For backward compatibility of the serialized {@code YearMonth.class} object,
145+
* explicitly declare the types of the serialized fields as defined in Java SE 8.
146+
* Instances of {@code YearMonth} are serialized using the dedicated
147+
* serialized form by {@code writeReplace}.
148+
* @serialField year int The year.
149+
* @serialField month int The month-of-year.
150+
*/
151+
@java.io.Serial
152+
private static final ObjectStreamField[] serialPersistentFields = {
153+
new ObjectStreamField("year", int.class),
154+
new ObjectStreamField("month", int.class),
155+
};
140156
/**
141157
* Parser.
142158
*/
@@ -149,11 +165,11 @@ public final class YearMonth
149165
/**
150166
* @serial The year.
151167
*/
152-
private final int year;
168+
private final transient int year;
153169
/**
154-
* @serial The month-of-year, not null.
170+
* @serial The month-of-year..
155171
*/
156-
private final int month;
172+
private final transient byte month;
157173

158174
//-----------------------------------------------------------------------
159175
/**
@@ -306,7 +322,7 @@ public static YearMonth parse(CharSequence text, DateTimeFormatter formatter) {
306322
*/
307323
private YearMonth(int year, int month) {
308324
this.year = year;
309-
this.month = month;
325+
this.month = (byte) month;
310326
}
311327

312328
/**

src/java.base/share/classes/java/time/chrono/HijrahDate.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -137,11 +137,11 @@ public final class HijrahDate
137137
/**
138138
* The month-of-year.
139139
*/
140-
private final transient int monthOfYear;
140+
private final transient byte monthOfYear;
141141
/**
142142
* The day-of-month.
143143
*/
144-
private final transient int dayOfMonth;
144+
private final transient byte dayOfMonth;
145145

146146
//-------------------------------------------------------------------------
147147
/**
@@ -273,8 +273,8 @@ private HijrahDate(HijrahChronology chrono, int prolepticYear, int monthOfYear,
273273

274274
this.chrono = chrono;
275275
this.prolepticYear = prolepticYear;
276-
this.monthOfYear = monthOfYear;
277-
this.dayOfMonth = dayOfMonth;
276+
this.monthOfYear = (byte) monthOfYear;
277+
this.dayOfMonth = (byte) dayOfMonth;
278278
}
279279

280280
/**
@@ -287,8 +287,8 @@ private HijrahDate(HijrahChronology chrono, long epochDay) {
287287

288288
this.chrono = chrono;
289289
this.prolepticYear = dateInfo[0];
290-
this.monthOfYear = dateInfo[1];
291-
this.dayOfMonth = dateInfo[2];
290+
this.monthOfYear = (byte) dateInfo[1];
291+
this.dayOfMonth = (byte) dateInfo[2];
292292
}
293293

294294
//-----------------------------------------------------------------------

test/jdk/java/time/test/java/time/TestLocalDate.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -65,6 +65,8 @@
6565
import static org.testng.Assert.assertTrue;
6666
import static org.testng.Assert.fail;
6767

68+
import java.io.ObjectStreamClass;
69+
import java.io.ObjectStreamField;
6870
import java.time.DateTimeException;
6971
import java.time.LocalDate;
7072
import java.time.Month;
@@ -515,4 +517,18 @@ public void test_minus_QuarterYears(long quarterYears) {
515517
.minus(quarterYears, ChronoUnit.MONTHS);
516518
assertEquals(t0, t1);
517519
}
520+
521+
// Verify serialized fields types are backward compatible
522+
@Test
523+
public void verifySerialFields() {
524+
var osc = ObjectStreamClass.lookup(LocalDate.class);
525+
for (ObjectStreamField f : osc.getFields()) {
526+
switch (f.getName()) {
527+
case "year" -> assertEquals(f.getType(), int.class, f.getName());
528+
case "month",
529+
"day" -> assertEquals(f.getType(), short.class);
530+
default -> fail("unknown field in LocalDate: " + f.getName());
531+
}
532+
}
533+
}
518534
}

test/jdk/java/time/test/java/time/TestMonthDay.java

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -62,7 +62,10 @@
6262
import static org.testng.Assert.assertEquals;
6363
import static org.testng.Assert.assertSame;
6464
import static org.testng.Assert.assertTrue;
65+
import static org.testng.Assert.fail;
6566

67+
import java.io.ObjectStreamClass;
68+
import java.io.ObjectStreamField;
6669
import java.time.LocalDate;
6770
import java.time.Month;
6871
import java.time.MonthDay;
@@ -144,4 +147,17 @@ void doTest_comparisons_MonthDay(MonthDay... localDates) {
144147
}
145148
}
146149

150+
151+
// Verify serialized fields types are backward compatible
152+
@Test
153+
public void verifySerialFields() {
154+
var osc = ObjectStreamClass.lookup(MonthDay.class);
155+
for (ObjectStreamField f : osc.getFields()) {
156+
switch (f.getName()) {
157+
case "month",
158+
"day" -> assertEquals(f.getType(), int.class, f.getName());
159+
default -> fail("unknown field in MonthDay: " + f.getName());
160+
}
161+
}
162+
}
147163
}

test/jdk/java/time/test/java/time/TestYearMonth.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -59,10 +59,16 @@
5959
*/
6060
package test.java.time;
6161

62+
import java.io.ObjectStreamClass;
63+
import java.io.ObjectStreamField;
64+
import java.time.LocalDate;
6265
import java.time.YearMonth;
6366

6467
import org.testng.annotations.Test;
6568

69+
import static org.testng.Assert.assertEquals;
70+
import static org.testng.Assert.fail;
71+
6672
/**
6773
* Test YearMonth.
6874
*/
@@ -75,4 +81,16 @@ public void test_immutable() {
7581
assertImmutable(YearMonth.class);
7682
}
7783

84+
// Verify serialized fields types are backward compatible
85+
@Test
86+
public void verifySerialFields() {
87+
var osc = ObjectStreamClass.lookup(YearMonth.class);
88+
for (ObjectStreamField f : osc.getFields()) {
89+
switch (f.getName()) {
90+
case "year" -> assertEquals(f.getType(), int.class, f.getName());
91+
case "month" -> assertEquals(f.getType(), int.class, f.getName());
92+
default -> fail("unknown field in YearMonth: " + f.getName());
93+
}
94+
}
95+
}
7896
}

0 commit comments

Comments
 (0)