Repository navigation
Tiny typos in Date Time articles ( https://dev.java/learn/date-time/ ) and Reflection articles ( https://dev.java/learn/reflection ) #191
Description
Thanks for the excellent content!
Just sharing a few small typos I found in case the team wants to clean them up in the next version.
- https://dev.java/learn/date-time/zoneid-zone-offset/ (archived at https://web.archive.org/web/20260208003013/https://dev.java/learn/date-time/zoneid-zone-offset/ ) has at least one typo:
The following code, **efines** the departure time for a flight from San Francisco to Tokyo as a [ZonedDateTime](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/time/ZonedDateTime.html) in the America/Los Angeles time zone.
efines should be defines .
- https://dev.java/learn/date-time/temporal/ (archived: https://web.archive.org/web/20260208020314/https://dev.java/learn/date-time/temporal/ ) has at least one typo:
The nest example is the PaydayAdjuster custom adjuster
nest should be next .
- https://dev.java/learn/reflection/names/#array (archived: https://web.archive.org/web/20260208021909/https://dev.java/learn/reflection/names/#array )
has a typo, "refence" instead of "reference."
- For https://dev.java/learn/reflection/fields/ (archived https://web.archive.org/web/20260206042334/https://dev.java/learn/reflection/fields/ )
there are a few issues.
First, a small typo in:
Note that there are restrictions on the members you can make accessible, if there are in other modules. You can check the page [Reflective Access with Open Modules and Open Packages](https://dev.java/learn/modules/opening-for-reflection/) for more information.
That is, "if there are in other modules", "there" should be "they." (see screenshot below, shared with one more example).
Then for: "This codes makes the field nameField accessible, despite being private."
It seems it should be "This code makes" instead of "This codes makes" (with an extra "s" on "codes") (see screenshot above).
Finally, in two code snippets, the "toString()" method for the User class is overridden, and both of them have a typo in the String returned.
That is, in two places:
public String toString() {
return "User[name='" + name + "]"; // missing single quote before square bracket on right side of name
}
should be:
public String toString() {
return "User[name='" + name + "']"; // single quote added before square bracket on right side of name
}
A side note, in the example, it is not mentioned that,
for
Field nameField = userClass.getDeclaredField("name");
NoSuchFieldException must be caught or declared to be thrown,
and
nameField.set(maria, "Mary");
IllegalAccessException must be caught or declared to be thrown, which might also be worth mentioning.
- For https://dev.java/learn/reflection/methods/ (archived: https://web.archive.org/web/20260206041438/https://dev.java/learn/reflection/methods/ )
In
You can still get access to such a method and invoke it, by first calling [method.setAccessible(true)](https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/reflect/Method.html#setAccessible(boolean)) on it.
This call may fail in case you are trying to invoke a method from a class in another module,
due to the restrictions on the class members a module. You can check the page [Reflective Access with Open Modules and Open Packages](https://dev.java/learn/modules/opening-for-reflection/) for more information.
Not sure what wording exactly was intended to be written for "due to the restrictions on the class members a module," which is not grammatically correct. It may be missing a preposition before "a module" or might be a leftover fragment that should simply be removed. Perhaps the rest of the sentence prior is fine by itself, e.g. "This call may fail in case you are trying to invoke a method from a class in another module," because the package containing the class of interest may not be opened or exported by the other module, which is already explained by the link given in the next sentence.
Also "But by doing so you loose the type safety of calling the method directly."
"loose" should be "lose" in this case.
Thanks so much for the all the content!
Bit hesitant to bother you with the reports of the typos and other little issues, but if I were hosting this I would want these reported (and they are very easy to clean up), so letting you know.
Activity
JosePaumard commentedon Feb 8, 2026
Hello, and thank you for taking the time to report all this! I just pushed the fixes.
is "This call may fail in case you are trying to invoke a method from a class in another module, due to the access restrictions on class members that a module may declare." correct, and is it clear enough?
Again, thank you!
willy-b commentedon Feb 8, 2026
Thanks for the updates!
All typos I had reported in the Date Time articles have been resolved.
(As of https://web.archive.org/web/20260208223138/https://dev.java/learn/date-time/zoneid-zone-offset/ and https://web.archive.org/web/20260208223211/https://dev.java/learn/date-time/temporal/ .)
For the Reflection article on Fields ( https://dev.java/learn/reflection , section https://dev.java/learn/reflection/fields/ ; archived at https://web.archive.org/web/20260208223622/https://dev.java/learn/reflection/fields/ ) , there are a couple of items remaining:
nameField.set(maria, "Mary");, you might consider to write something like "Note that Field.set(Object, Object) declares that it can throw the checked Exception IllegalAccessException, so the method call must be wrapped in an appropriate try-catch block or the calling method must also declare that it throws IllegalAccessException for the code to compile successfully. Such exception handling has been omitted from these code snippets for brevity but must be included by those following along at home."Field nameField = userClass.getDeclaredField("name");, you might instead consider to write something like "Note that getDeclaredField() declares that it can throw the checked Exception NoSuchFieldException, so exception handling, not shown here, will be required for this example to compile." (The explanation could also be more verbose like what I suggested for IllegalAccessException above.)Re: your question on how you should finish the sentence
on https://dev.java/learn/reflection/methods/ (current version with your proposed edit archived at https://web.archive.org/web/20260208223938/https://dev.java/learn/reflection/methods/ ):
I think "due to the access restrictions of class members that a module may declare"
is a little confusing to be honest because, as I understand it (see the spec quote below):
Per JLS 25:
https://docs.oracle.com/javase/specs/jls/se25/jls25.pdf
Or e.g. also per https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/reflect/AccessibleObject.html
Thanks very much!
JosePaumard commentedon Feb 9, 2026
Thank you for your review and reports! I just pushed some fixes.
As for the exception handling part: I prefer to keep things simple in this section, by not deep-diving into to many details. This part is about Reflection, and there is a section dedicated to Exceptions. BTW I changed the wording to "can throw an Exception".
As for the modules: thanks for your comment. I rewrote this part. And, same as for the Exception, since there is a section specifically on this topic, I don't want to go too deep neither.
willy-b commentedon Feb 10, 2026
Great! The discussion of the Exceptions is clear and agreed makes sense to leave out any additional detail on that.
Re: https://dev.java/learn/reflection/methods/
and replacing what you had written in the 2nd version ( https://web.archive.org/web/20260206041438/https://dev.java/learn/reflection/methods/ )
(which I said in #191 (comment) was confusing since package level control is the finest level of export/opening control available for modules, not classes or class members, and defined modules hide packages by default from reflection from other modules)
with the new ( https://web.archive.org/web/20260210144803/https://dev.java/learn/reflection/methods/ ):
Agreed on the change to the last half of the second sentence:
"module does not declare itself or the package that contains the element you want to access as being opened to reflection" is great and addresses my concern about other explicitly defined modules being closed for reflection by default, and that opening contents of a module for reflection is at its finest level controlled at the package, not class or class member level, though "element" might be better replaced with "method" as this article is specific to methods.
Re: replacing
with
maybe instead of "the element you want to make accessible belongs to a named module", "you are trying to invoke a method from a class in another named module" would be clearest,
as this is from https://dev.java/learn/reflection/methods/ and per the previous sentence is referring to
method.setAccessible(true)and methods from classes in the same named module are still open to reflection.Thanks for also specifying "named module", as I agree it is worth mentioning explicitly that if one does not define a module at all, despite the fact that an unnamed module is created automatically, the classes without a declared module are treated the same for reflection by other modules that can import them as if they were in the same module rather than another module (open to reflection; as used to be the case in Java generally for all packages before reflection was restricted by modules, which first landed in a long-term supported java release in 2018-09 with Java 11, first out in 2017-09 in Java 9).
E.g. from the JLS 25 spec:
https://docs.oracle.com/javase/specs/jls/se25/jls25.pdf
The last thing would then be to consider to make the detail enhancement you made above also in https://dev.java/learn/reflection/fields/ (archived: https://web.archive.org/web/20260210044513/https://dev.java/learn/reflection/fields/ ), which currently reads:
"Note that there are restrictions on the members you can make accessible, if they are in other modules."
Where you could also expand what your team had written there, "if they are in other modules", to "if they are in other named modules" as we discussed here.
Otherwise, for https://dev.java/learn/reflection/fields/ (archived: https://web.archive.org/web/20260210044513/https://dev.java/learn/reflection/fields/ ), issues reported were all resolved:
Nit: On https://dev.java/learn/reflection/fields/ , the sentence "You can read more on access flags in this section" , [was] missing a period at the end. (archived: https://web.archive.org/web/20260208223622/https://dev.java/learn/reflection/fields/ ).The print output for instances of User in the examples for https://dev.java/learn/reflection/fields/ [needed] to be updated to match the fixed toString .IllegalAccessException and NoSuchFieldException notes were potentially unclearThanks so much!
JosePaumard commentedon Feb 10, 2026
What I see is that this subject of getting access to non-visible fields is a little clumsy. So I did some reorganization.
I added a section on accessing private members on the Field page, and a similar section on the Method and Constructor pages, that point to the Field page. I also changed the explanation a little about the reflective access.
willy-b commentedon Feb 11, 2026
Thanks so much for the changes!
For the latest version, reviewing all sections so far discussed,
I see the following issues:
In the latest https://dev.java/learn/reflection/methods/ (archived: https://web.archive.org/web/20260210180629/https://dev.java/learn/reflection/methods/ ):
For the sentence:
"The type parameter of a method is erased at compile time, meaning that you cannot use it with the Reflection API."
I think "type parameter" should be plural, so this sentence should instead be written:
"The type parameters of a method are erased at compile time, meaning that you cannot use them with the Reflection API."
An example of a method with multiple type parameters would be an implementation of Map#put(K,V):
https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/util/Map.html#put(K,V) .
E.g. one replacing the current single type example with a two type example as follows:
For the updated discussion of limitations on
setAccessiblein the methods reflection article:Thanks, this is clear. The detail we were discussing in #191 (comment) has been moved to the new article section "Making a Field, a Method or a Constructor Accessible" of the https://dev.java/learn/reflection/fields/ article, discussed later in this comment (see below), and I think consolidating the explanation and expanding it there was a smart move.
For https://dev.java/learn/reflection/fields/ (archived: https://web.archive.org/web/20260210181106/https://dev.java/learn/reflection/fields/ )
In the first example of the section "Locating Field" the line
boolean isPublic = field.accessFlags().contains(AccessFlag.PUBLIC);defines a variable which is not used (does not actually get printed in the print statement on the subsequent line)This is safe as far as what is mentioned here in this section.
Thank you, this is so much clearer than the earlier versions,
e.g. "Note that there are restrictions on the members you can make accessible, if they are in other modules." from https://web.archive.org/web/20260210044513/https://dev.java/learn/reflection/fields/ or "This call may fail in case you are trying to invoke a method from a class in another module, due to the restrictions on the class members a module." from https://web.archive.org/web/20260206041438/https://dev.java/learn/reflection/methods/ .
My last remaining thoughts on this is are:
Why not link here also to your team's article on "the unnamed module" at https://dev.java/learn/modules/unnamed-module/ (archived: https://web.archive.org/web/20260211015421/https://dev.java/learn/modules/unnamed-module/ )?
I can't comment on whether not using the Java Module System is a bad practice or not (I am not familiar with the latest recommendations on that yet) and whether it is safe for everything to be in the unnamed automatically generated module which is entirely open for reflection in that case, but it is how the entire Java language worked prior to Java 9 in 2017; modules and restrictions on reflective access only first even became long-term supported in 2018 with Java 11, and are still not required to be used. I do agree though that in a project not using the Java Module System the setAccessible call is safe in that it will not fail due to reflective access restrictions, and I agree that this paragraph is consistent with what your team wrote in https://dev.java/learn/modules/unnamed-module/ .
It may be appropriate to say "automatically generated unnamed modules" instead of "the unnamed module," and to note that all declared modules are named modules, see https://docs.oracle.com/javase/specs/jls/se25/jls25.pdf section 7.7 (see also 7.7.5). Note that in the original planning for the module system there was described a single "unnamed module" referred to as "the unnamed module" e.g. in https://openjdk.org/projects/jigsaw/spec/sotms/#the-unnamed-module , but in the JLS 25 and more recent documents, unnamed modules are described in the plural and e.g. https://docs.oracle.com/en/java/javase/25/docs/api//java.base/java/lang/Module.html says "There is an unnamed module for each ClassLoader, obtained by invoking its getUnnamedModule method. All types that are not in a named module [(all declared modules are named)] are members of their defining class loader's unnamed module."
Under the heading "Dealing with Primitive Types", in the sentence, "Is your field has a primitive type or a wrapper type," "Is" should be "If"
For the latest "Opening for Reflection" article, https://dev.java/learn/modules/opening-for-reflection/ (archived: https://web.archive.org/web/20260210193234/https://dev.java/learn/modules/opening-for-reflection/ ):
In the sentence, "communicates the intend to use the package with a reflection-based framework", "intend" should be "intent."
In the sentence, "Consequently, it doesn't make sense to manually open further packages, which is why opens directives in an open module and lead to compile errors." should probably end with "which is why additional "opens" directives in an open module lead to compilation errors." ("opens" rather than "open" intentional in this case.)
In the latest https://dev.java/learn/reflection/constructors/ (archived: https://web.archive.org/web/20260210222645/https://dev.java/learn/reflection/constructors/),
"constructor" should be "constructors", and "invoke" should be "invoking."
"exception:" should be "exceptions:".
On the latest https://dev.java/learn/reflection/names/ (archived: https://web.archive.org/web/20260211003456/https://dev.java/learn/reflection/names/ ):
On the latest https://dev.java/learn/reflection/modifiers/ (archived at https://web.archive.org/web/20260211002358/https://dev.java/learn/reflection/modifiers/ ):
Thanks again!
I will continue reviewing later pages in the tutorials for typos and other issues and once you let me know the ones I have reported so far are fixed, I will post the next batch that I find (if any). Looking forward to helping your team get these nits and typos completely cleared out.
JosePaumard commentedon Feb 11, 2026
Thank you for your review and reports! I just pushed the fixes.
As for the unnamed module: there is a section dedicated to this topic, so I prefer to keep it simple in the Reflection part.
NamLe029 commentedon Feb 11, 2026
There is also a typo in https://dev.java/learn/reflection/classes/#get-class, at the end of the subsection
Getting a Runtime Class:JosePaumard commentedon Feb 11, 2026
Thank you for your report! I just pushed a fix.
willy-b commentedon Feb 23, 2026
Thanks! The specific issues I previously reported have been addressed (except where you disagreed explicitly with justification).
Here are some additional typos and small errors I have found in these articles as I continue to review them:
For the latest https://dev.java/learn/reflection/annotations/ (archived at https://web.archive.org/web/20260222211141/https://dev.java/learn/reflection/annotations/ )
In "allows you to check is a given annotation is present on this element", the first "is" should probably be "if".
"getAnnotation(Class) and getDeclaredAnnotation(Class): returns an annotation for the specific type passed as an argument." , I think "returns" should be "return" to match the plural subject
"getAnnotationsByType(Class has been added in Java SE 8" is missing a closing ")"
In "First, you can check if the Person class has any annotation, and discover them.", "annotation" should be plural.
"Note that this annotation can be used where the types are used, not the types themselves."
might be clearer as "Note that this annotation can be used where the types are used, not applied to the types themselves."
In "You can the use this annotation in this way", "the" should be "then"
In the "Getting Inherited Annotations" and subsequent sections, there seem to be a few accidental replacements of "User" with "Employee"
e.g.
and in the first example of the "Getting Annotations on Types" section:
(which also has typos, see above, in "You can the use this annotation" ("the" should be "then"), and "gives you access to this annotation in ths way" ("ths" should be "this"))
In the latest version of the "Creating an Interceptor with Annotations" article, https://dev.java/learn/reflection/interceptor/ (archived at https://web.archive.org/web/20260222211217/https://dev.java/learn/reflection/interceptor/ ), there are a few possible issues:
is written one extra time before ,
"Now that you have all the elements, you can run the following code,"
in a way that makes it look like the flow was interrupted by the "Let us add another class, to show that the interception mechanism is working correctly." section and then resumed.
It may be clearer if the first occurrence is dropped.
but after writing
"Let us add another class, to show that the interception mechanism is working correctly. This SomeNonInterceptedService class is the same as the SomeInterceptedService class.
The only difference is that its service method does not declare the interceptor",
another unnecessary difference is introduced:
SomeInterceptedService is declared static (actually "public static class" which is an error, see above, but it should be corrected to "public class" not non-public static), which is inconsistent and maybe distracting and looks unintentional though it is harmless.
re: ServiceFactory.invoke, do we need to be able to invoke non-public methods on a service class using the ServiceFactory? If not, we can replace getDeclaredMethod with getMethod?
It should probably be mentioned that the approach used in ServiceFactory.invoke is not safe for many method parameter types, e.g. interface or superclass types of those used at runtime (ignoring generics which would also be problematic).
It may be necessary instead to iterate through
getDeclaredMethods()(or if only public methods are needed,getMethods()) to find a possible match,taking into account argument superclass and superinterface relationships, using e.g.
Class::isAssignableFrom(i.e. requiringmethodParameterTypes[i].isAssignableFrom(parameterClasses[i])for all i) (see https://web.archive.org/web/20251204003020/https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/Class.html#isAssignableFrom(java.lang.Class) ).In more detail,
for
ServiceFactory.invoke:Using
getDeclaredMethodto look for the applicable method using the runtime type of the argument makes this fail for any case where the runtime type does not match exactly, e.g.when the method parameter type is an interface or superclass (also problematic for primitives).
For a specific example, one can try the following almost identical variant of the intercepted service method, changing the parameter type to the CharSequence interface (String is an implementation of CharSequence and can be passed as such a parameter):
Then the ServiceFactory can no longer invoke that method with a String argument, throwing a
NoSuchMethodException, as getDeclaredMethod cannot use the runtime type of the argument, a String, an implementation of CharSequence, to look up a method with a CharSequence parameter:
If one replaces
Method method = serviceClass.getDeclaredMethod(methodName, parameterClasses);with
Method method = findMatchingMethod(serviceClass, methodName, parameterClasses);for an appropriately defined static method findMatchingMethod
which iterates through
serviceClass.getDeclaredMethods()for one with a matchingmethodName, the same number of parameters, and which satisfiesmethodParameterTypes[i].isAssignableFrom(parameterClasses[i]for all indicesiwhenmethodParameterTypes = method.getParameterTypes(), it resolves at least this issue and this example (one will also have to disambiguate the cases with multiple matching signatures by following the Java rule of most specific parameter types winning) (I have written code to handle the single matching method case and can confirm the NoSuchMethodException above is resolved for e.g. a parameter type of CharSequence with runtime type of String).In the latest version of the Dependency Injection using Reflection article, https://dev.java/learn/reflection/dependency-injection/ (archived at https://web.archive.org/web/20260222211245/https://dev.java/learn/reflection/dependency-injection/ ):
(Very cool tutorial!)
I think the
@Targetfor the@Injectannotation might be mistaken, it is given asElementType.TYPE,when it appears to be a case calling for a
ElementType.FIELDannotation:Trying to use an
ElementType.TYPEon a field declaration will give anannotation interface not applicable to this kind of declarationerror, I think.Aside from that, there are also similar issues here as reported above for the Interceptor article
with using reflection to find a method (in this case a constructor) that is an exact match by argument runtime type rather than a compatible match.
E.g.
BeanFactory.getInstanceOfuseswhich won't find a constructor that has any parameters of interface types or superclass types to the types passed at runtime .
For example, this will not be able find a constructor with CharSequence parameters if a String is passed at runtime, e.g., if Message uses CharSequence:
The current
BeanFactory.getInstanceOfwould not be able to construct a Message with a CharSequence component type with a String despiteCharSequence.class.isAssignableFrom(String.class) == true.That is not to say this approach cannot be used, but a simple call to
getConstructorwith the argument classes will not yield matching constructors if interface or superclass types are used, not to mention generics (e.g. suppose the constructor takes a Collection, or Map, or List - it will fail).It may be necessary to iterate through
getDeclaredConstructors()instead to find a possible match,taking into account argument superclass and superinterface relationships, using Class::isAssignableFrom (i.e. requiring
methodParameterTypes[i].isAssignableFrom(parameterClasses[i])for all i) (see https://web.archive.org/web/20251204003020/https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/lang/Class.html#isAssignableFrom(java.lang.Class) ).In the latest version of the Enums Reflection article, https://dev.java/learn/reflection/enums/ (archived at https://web.archive.org/web/20260222211043/https://dev.java/learn/reflection/enums/ ):
In "Note that this enum as a defined constructor, a field, and a method, which is an accessor to this field", "this enum as a" should be "this enum has a".
In "It also has a factory method, to get one of the constant from a label.", the word "constant" should be plural, "constants".
In the latest version of the Records Reflection article, https://dev.java/learn/reflection/records/ (archived at https://web.archive.org/web/20260222211125/https://dev.java/learn/reflection/records/ ):
Re: "Records are a particular type of class, that strongly enforce non-modifiability. It also introduces the notion of record component." Maybe "it also introduces" should be "they also introduce" due to plural subject ? (see previous sentence, "Records are")
Re: "When were introduced in Java SE 16, several new methods and classes were added to the Reflection API." Should this start "When Records were introduced"?
In the latest version of the Date Time APIs TOC page, https://dev.java/learn/date-time/ (archived: https://web.archive.org/web/20260210102410/https://dev.java/learn/date-time/ ), a few typos:
"The Instant class represent an instantaneous moment on the timeline.": "represent" -> "represents"
Re: "The Period and Duration classes, as well as the ChronoUnit.between method() are used to calculate an amount of time."
Should the "()" be on "between" instead of "method" or not present at all?
Re: "tips on how to convert older java.util.Date and java.util.Calendar code to the Date-Time API." This section description sentence does not begin with a capital letter, unlike the others on this page.
In the latest version of the Methods Reflection article, https://dev.java/learn/reflection/methods/ , (archived at https://web.archive.org/web/20260222204250/https://dev.java/learn/reflection/methods/ ):
In the sentence "The method Method.getModifiers() returns an int in which each bit represent a single modifier", the word "represent" should be "represents". (If this sounds like a repeat, it is because I reported the same typo in the text for Field.getModifiers in the Fields reflection article earlier.)
Re: "On the other hand, if the method you are invoking takes two parameters, then you invocation of the invoke() method needs three arguments". It seems "you invocation" should be "your invocation".
Re: "The String.length() does not take any parameter, which make the invocation of this method easier." Can drop the leading article "The" or write "The method String.length()" but as is, saying "The String.length()" seems wrong. Also, "does not take any parameter" might be made consistent with other descriptions which assume the possibility of multiple parameters by writing "does not take any parameters". "which make" should also probably be "which makes."
Re: "The Reflection API catches these exceptions for you, and wrap them in a InvocationTargetException that you can catch and analyze."
Here "wrap" should be "wraps."
Re: "Note that we are using the Files.newBufferedWriter() method, that declares a variable argument." It seems "that declares" should be "which declares".
On the latest Reflection articles Table of Contents , https://dev.java/learn/reflection/ (archived at https://web.archive.org/web/20260222211626/https://dev.java/learn/reflection/ ), there are a couple of small issues.
The "Records" section description is the just the first 13 words of the "Reading Modifiers" section's description, suggesting some kind of copy-paste error.
Compare:
and
Then, for the "Retrieving Classes" section, in the description sentence "How to retrieve a class instance, from its name, or from and object, including arrays an primitive types":
Thanks again for the excellent content and for resolving issues as they are reported!
JosePaumard commentedon Feb 23, 2026
Thank you for all this! I just pusehd a fix.
As for the interceptor example. I agree that this example is fragile due to the difference between the types at compile time and the types at runtime, but I think this example is complex enough as it is. I just added a mention on this point, but showing how to fix it would be a whole new chapter, and I think it would go way outside the scope of this presentation on the Reflection API. Matching trees and graphs is not really the subject of this chapter ;)
willy-b commentedon Feb 28, 2026
Great! Most items reported (typos, class/variable name mismatches, etc) have been fixed. Thanks so much!
However, it does seem at least a couple of the issues reported in #191 (comment) are still actually NOT fixed yet, see below.
The following item reported earlier above remains in the latest https://dev.java/learn/reflection/annotations/ (archived at: https://web.archive.org/web/20260227183835/https://dev.java/learn/reflection/annotations/ , originally archived at https://web.archive.org/web/20260222211141/https://dev.java/learn/reflection/annotations/ ):
This has not changed in the most recent version, indeed it rethrows a RuntimeException, but it does so regardless of whether the new "ReThrowAsRuntimeException" annotation specifically is on the method (it could be another annotation for example, or even no annotations on the declared exception at all, as the boolean
annotationPresentis not checked).For the latest version of the Interceptor article, https://dev.java/learn/reflection/interceptor/ ( archived at https://web.archive.org/web/20260227184909/https://dev.java/learn/reflection/interceptor/ ),
I had raised a concern about reflective invoker (ServiceFactory::invoke) built in this tutorial not covering many cases, e.g. any method with interface parameter types (for which the runtime type of the parameter is not strictly equal to the parameter type of the method).
E.g. a method taking an argument of type CharSequence which can be called with a String ( CharSequence assignable from String) but the reflective invoker using the overly specific getDeclaredMethod with the runtime type of the argument would fail in the case because it would not retrieve a method with argument type CharSequence by searching for one with a String type argument despite
CharSequence.class.isAssignableFrom(String.class) == true(see Class::isAssignableFrom).Thanks for acknowledging this issue. I have a small question about the following text which has been added at the bottom to address that concern :
Re: what you have added above, "the type String extends the type CharSequence", this might be a bit confusing as String does not extend CharSequence (it is not a superclass), but rather it implements CharSequence as an interface.
It might be clearer to stick to the narrow requirement, which is that
CharSequence.class.isAssignableFrom(String.class) == true, rather than saying "String extends ... CharSequence".Thus, "(the type String extends the type CharSequence), then the getDeclaredMethod() call would not have returned this message() method." might be clearer as "If the parameter of the message() method was of type CharSequence instead of String, then despite
CharSequence.class.isAssignableFrom(String.class) == true, the getDeclaredMethod() call used would not have returned this message() method." You might consider to mention that though it is out of scope for this tutorial, it is possible to loop through declared methods and check matching signatures using isAssignableFrom to resolve this gap.re: the latest version of https://dev.java/learn/reflection/dependency-injection/ , https://web.archive.org/web/20260227192258/https://dev.java/learn/reflection/dependency-injection/
The reflective constructor invocation by getInstanceOf/instantiateBeanClass in this article was also reported above as not safe (will not cover any constructors which have interface parameter types for example), for the same reasons as discussed in the interceptor example above. No note has been added yet and it probably should be commented upon similar to what you did in the Interceptor article.
Thanks so much!
JosePaumard commentedon Mar 2, 2026
Thank you again WIlly, for all these report! I just pushed a fix.
As for the examples in the Reflection API part. Indeed the type String extends the type CharSequence. If may sound confusing, but this is the right way of saying it. Narrowing with isAssignableFrom() could solve this very simple problem, but if you add more parameters to the method you are looking for, then you will need much more complex code. Odds are that you will end up getting all the methods, and fitering this list on the name, and then on mutliple isAssignableFrom() on each parameter. And since methods can have overloads, you may have several results in the end, and need to choose which one to pick, probably by choosing the most precise one, or the closest to the real type you have, and then picking one randomly because you can still have ties.
So I prefer to keep things simple.
26 remaining items
JosePaumard commentedon May 25, 2026
Thank you again for your report! A fix is on its way.
willy-b commentedon May 30, 2026
Thanks, I can confirm all those items reported were fixed.
I observe the following remaining items:
In the latest version of https://dev.java/learn/reflection/classes/ (archived as is at https://web.archive.org/web/20260530043720/https://dev.java/learn/reflection/classes/ ),
For the example
the expected output provided is
when it should be:
without the "c:".
In the latest version of https://dev.java/learn/reflection/constructors/ (archived as is https://web.archive.org/web/20260530233259/https://dev.java/learn/reflection/constructors/ )
In the sentences
", wrapped in an InvocationTargetException. " should be removed,
as Class.newInstance() does NOT throw InvocationTargetException, but rather the underlying exceptions, which is the problem. Constructor.newInstance() on the other hand does throw Exceptions wrapped in InvocationTargetException, which you can then declare for compile-time exception checking.
See the deprecation notice on Class.newInstance() (quoted from https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/lang/Class.html#newInstance() ):
In the code snippet with the line:
" parameter" should be " parameter(s)".
That way the current output:
Would be updated to:
In the next code snippet also:
should have " parameter" updated to " parameter(s)" for the same reason.
Thanks very much!
JosePaumard commentedon Jun 1, 2026
Thank you again for your reports! A fix is on its way.
willy-b commentedon Jun 4, 2026
Excellent, thanks! Just the following tiny non-blocker issues to fix or ACK "won't fix" below and then I will close this.
In the latest https://dev.java/learn/reflection/intro/ (archived as is at https://web.archive.org/web/20260603221846/https://dev.java/learn/reflection/intro/ )
Not a blocker for closing, but I will note in passing that re: the sentences
that https://openjdk.org/jeps/504 removing the Applet API (planned to be removed for 10 years) has landed in Java 26, and the Security Manager itself has been deprecated since Java 17 and is permanently disabled since https://openjdk.org/jeps/486 which landed in Java 24.
Thus also on https://dev.java/learn/reflection/classes/ (archived as is at https://web.archive.org/web/20260603222215/https://dev.java/learn/reflection/classes/ ),
can be simplified to
(as ReflectPermission is deprecated.)
also
should be
class: class [[[I.In the latest version of https://dev.java/learn/reflection/interceptor/ (archived as is at: https://web.archive.org/web/20260604021307/https://dev.java/learn/reflection/interceptor/ )
Non-blocker nit:
In the sentences
"it relies" should be capitalized to "It relies."
In the latest version of https://dev.java/learn/reflection/dependency-injection/ (archived as is at https://web.archive.org/web/20260604031422/https://dev.java/learn/reflection/dependency-injection/ )
Non blocker nit:
In the sentence
"concept of singleton" should be "concept of a singleton".
Thanks very much!
JosePaumard commentedon Jun 4, 2026
Thank you again for your report! A fix is on its way.
willy-b commentedon Jun 4, 2026
The Reflection tutorial series part of this ticket ( https://dev.java/learn/reflection ) has everything fixed which had been reported, and I think that series is now in a good state overall, thanks so much!
However, I realize during the pre-close review that the separate Date-Time tutorial series ( https://dev.java/learn/date-time/ ) which has not been discussed much in this ticket due to the number of items found in the Reflection tutorial still has a couple of issues remaining which should probably be fixed or ACK'd "won't fix" as part of this ticket. Thus I begin listing remaining Date-Time tutorial issues below in case your team wants to fix them.
In the latest version of https://dev.java/learn/date-time/zoneid-zone-offset/ (archived as is at https://web.archive.org/web/20260604223645/https://dev.java/learn/date-time/zoneid-zone-offset/ ),
The first code snippet on the page will not compile due to multiple errors in the code, and has out of date TZDB entries leading to differences in the output vs recent versions of Java
First, the lines
will not compile, as List.sort must take a Comparator argument ( https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/util/List.html#sort(java.util.Comparator) )
AND sort returns void.
Thus one will get a message like (fixing this is not enough as sort also returns void):
The line above should be replaced with:
Then, two variables are given the same identifier "zone" and so the example would not compile also for this independent, second reason.
Thus,
should be updated to:
With those changes together, the example will compile and run and produce something close to what is given as the expected output.
However, I then still observe that there are differences in the timezones which are listed as having fractions of hours in their offset,
which appears to be due to changes in the offsets assigned to timezones since the author's version of Java to mine (Java 26), e.g.:
America/Caracas -04:00, but the example provided showsAmerica/Caracas -04:30Pacific/Norfolk +11:00, but the example provided showsPacific/Norfolk +11:30That is because the article is using an out of date TZDB, whereas I am running Java 26 released this year with the latest TZDB.
From the TZDB NEWS:
See also e.g. https://web.archive.org/web/20151113142441/http://www.norfolkisland.gov.nf/nia/MediaRelease/Media%20Release%20Norfolk%20Island%20Standard%20Time%20Change.pdf (document is no longer hosted by Norfolk gov but is in web.archive.org ).
Finally, there are also the differences in the output on recent versions of Java vs the tutorial author's version (unspecified) in the output for Tehran/Iran (I am seeing +03:30 instead of +04:30 , and I think Iran Daylight Savings Time is still discontinued since 2022; see https://en.wikipedia.org/w/index.php?title=Iran_Standard_Time&oldid=1349428906 ) and Asia/Rangoon has been renamed Asia/Yangon (but both entries have been kept by TZDB for backward compatibility).
In the latest version of https://dev.java/learn/date-time/standard-calendar/ (archived as is at https://web.archive.org/web/20260604210444/https://dev.java/learn/date-time/standard-calendar/ )
In the sentence
The text "Instant" is not a proper link,and links to
javadoc:instead of https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/Instant.html .In the latest https://dev.java/learn/date-time/dayofweek-month/ (archived as is at https://web.archive.org/web/20260604215431/https://dev.java/learn/date-time/dayofweek-month/ )
In the sentences
the links for DayOfWeek and Month are broken (link to
javadoc:which does nothing).Thanks so much!
JosePaumard commentedon Jun 5, 2026
Thank you again for your report! A fix is on its way.
willy-b commentedon Jun 11, 2026
Thanks so much! Here are some additional items found during further review of the Date Time tutorials.
In the latest version of https://dev.java/learn/date-time/dayofweek-month/ (archived as is at https://web.archive.org/web/20260609030620/https://dev.java/learn/date-time/dayofweek-month/ )
In the sentence
the link on "Month" has not been fixed yet (on the page it still links to "javadoc:" and does nothing). There is an occurrence in a preceding sentence that has the link correct which might be why this one remained unresolved (because it is not broken in the previous sentence).
In the latest version of https://dev.java/learn/date-time/zoneid-zone-offset/ (archived as is at https://web.archive.org/web/20260609214239/https://dev.java/learn/date-time/zoneid-zone-offset/ )
Thanks in advance for humoring this question: Why is TemporalAdjusters.lastInMonth() used to demonstrate OffsetDateTime? (It seems OffsetDateTime has no advantage over LocalDateTime for this)
The underlying question for me is: How can the time offset from UTC affect the answer to the question "what is the last Thursday in July 2013?" posed in this example. Indeed using -18:00 or +18:00 give the same answer (and those offsets span the maximum range of possible offsets for ZoneOffset , see the documentation at https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/ZoneOffset.html ).
I assume there is likely a good motivating reason for this example but if it is unclear to me when the others are clear, I figure it is worth asking and it may be useful to add a sentence to motivate it for other readers.
In the latest version of https://dev.java/learn/date-time/parsing-formatting/ (archived as is at https://web.archive.org/web/20260609222417/https://dev.java/learn/date-time/parsing-formatting/ )
In the sentence
"to specify the format [...] then you would have to always use" should be "if you specify the format [...] then you would have to always use" ("to specify" should be "if you specify").
In the expected output for the 2nd time
(same code was shown on the earlier page https://dev.java/learn/date-time/zoneid-zone-offset/#zonedatetime , as well; archived as is at https://web.archive.org/web/20260609224702/https://dev.java/learn/date-time/zoneid-zone-offset/#zonedatetime )
the flight from San Francisco to Tokyo example is used (now to demonstrate date-time formatting here in https://dev.java/learn/date-time/parsing-formatting/ (archived as is at https://web.archive.org/web/20260609222417/https://dev.java/learn/date-time/parsing-formatting/ ) )
the part of the output which prints whether daylight savings is in effect is this time omitted
(
(Asia/Tokyo standard time will be in effect.))the part of the output which prints whether daylight savings is in effect is this time omitted
(
(Asia/Tokyo standard time will be in effect.))Where the output omitted is that corresponding to the code in the snippet which is as follows:
In the latest version of https://dev.java/learn/date-time/non-iso-conversion/ (archived as is at https://web.archive.org/web/20260610033131/https://dev.java/learn/date-time/non-iso-conversion/ )
In the sentence
"JapaneseDate.from(TemporalAccessor)" is missing the fragment in its link URL to scroll to the appropriate method (missing "#from(java.time.temporal.TemporalAccessor)"),
it links to https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/chrono/JapaneseDate.html when it should link to https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/chrono/JapaneseDate.html#from(java.time.temporal.TemporalAccessor) .
Nit: the "StringConverter" class is not described in text or declared in provided code blocks but used for invoking toString/fromString static methods in examples.
One can determine implicitly that it is the unshown enclosing class but why not omit StringConverter and just call the methods as if the example blocks are in a static (e.g. main) method within the same class so they are in scope?
It may be worth noting explicitly that the expected input/output for toString/fromString are locale sensitive, e.g. the Buddhist Era era for ThaiBuddhist will be "BE" in one locale (Locale.US, TextStyle.SHORT) and "E. B." in another (Locale.FRENCH, TextStyle.SHORT), and apparently "B.E." for the dev.java author (unknown locale). This will cause exceptions if someone tries to test fromString in a different locale than the author.
Two possible problems with the
static String toString(LocalDate localDate, Chronology chrono)example (beyond the input/output examples):First, the "pattern" variable is not referenced (not used in the DateTimeFormatter), which is inconsistent with the later
fromStringexample.Second, Why does
static String toString(LocalDate localDate, Chronology chrono)convert the LocalDate to a ChronoLocalDate when formatting with a DateTimeFormatter with the target Chronology?Per the documentation ( https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/format/DateTimeFormatter.html#withChronology(java.time.chrono.Chronology) ),
thus, passing a ChronoLocalDate is unnecessary (and in fact the Chronology set in the ChronoLocalDate is ignored by the DateTimeFormatter which just uses its override Chronology, so it is misleading to set up a ChronoLocalDate in the code example).
Note also that the ChronoLocalDate documentation ( https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/chrono/ChronoLocalDate.html )
explains at length that using it should be generally avoided, preferring LocalDate:
Thus the existing code example could be simplified (marked up inline):
The simplified (and less error-prone due to removing code that appears to set the Chronology (on ChronoLocalDate) which actually has no effect on the output) version is then:
In the subsequent example of
LocalDate fromString(String text, Chronology chrono),aside from needing to fix the DateTimeFormatter to be consistent with toString not actually using the "pattern" variable,
there is also some potentially unnecessary code: (commented on inline)
so that it can be simplified to 1 line instead of 3, not using a ChronoLocalDate at all, just LocalDate.parse with the DateTimeFormatter which is Chronology aware:
In the latest version of https://dev.java/learn/date-time/legacy-code/ (archived as is at https://web.archive.org/web/20260610203727/https://dev.java/learn/date-time/legacy-code/ )
The first coding example has an extra closing parenthesis at the end on the following line:
In the sentence
The table linked above (archived as is at https://web.archive.org/web/20260611012755/https://dev.java/learn/date-time/intro/#methods ) actually gives method names, NOT classes, and classes from the java.time package are not even mentioned. The table link referenced above was probably intended by the dev.java author to be https://dev.java/learn/date-time/standard-calendar/#intro (archived as is at https://web.archive.org/web/20260611014552/https://dev.java/learn/date-time/standard-calendar/#intro ) instead of https://dev.java/learn/date-time/intro/#methods (archived as is at https://web.archive.org/web/20260611012755/https://dev.java/learn/date-time/intro/#methods ).
Thanks so much!
willy-b commentedon Jul 10, 2026
Also, in the latest version of https://dev.java/learn/date-time/parsing-formatting/ (archived as is at https://web.archive.org/web/20260710210105/https://dev.java/learn/date-time/parsing-formatting/?no_cache=true ) ,
In the sentence
"format(DateTimeFormatter)" links to https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/lang/String.html#format(java.lang.String,java.lang.Object...) ,
which is NOT the method described.
The code example shows us what the intended method may have been:
Showing the intended method may have been the specific ZonedDateTime.format(DateTimeFormatter) ( https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/ZonedDateTime.html#format(java.time.format.DateTimeFormatter) ) ,
or the upstream interface method specifying that ChronoZonedDateTime.format(DateTimeFormatter) ( https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/chrono/ChronoZonedDateTime.html#format(java.time.format.DateTimeFormatter) ) .
It seems many (but NOT ALL, e.g. NOT Instant) of the the classes implementing the Temporal interface at the present time do have a format(DateTimeFormatter) method but for some reason the Java API authors did not choose to put that method on some common interface or Temporal itself.
I don't see a common interface method for the Temporal class , but for the separate implementations:
(the format method here is also on the interface ChronoLocalDateTime https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/chrono/ChronoLocalDateTime.html , but there is no shared superinterface with the other bullets with this method signature)
(the format method here is also on the interface ChronoLocalDate https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/chrono/ChronoLocalDate.html , but there is no shared superinterface with the other bullets with this method signature)
(Note some other classes implementing Temporal do not have format(DateTimeFormatter) methods, like Instant https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/Instant.html , at least as of Java 26.)
Maybe besides fixing the link to the ZonedDateTime.format(DateTimeFormatter) used in the example (or ChronoZonedDateTime's equivalent method), it is worth specifically mentioning the other classes, e.g. LocalDateTime, LocalDate, LocalTime, OffsetDateTime, OffsetTime, that have this method since there appears to be no common interface that defines it, and since it is only some but not all Temporal classes that have the format(DateTimeFormatter) method signature?
Thanks very much!
JosePaumard commentedon Jul 11, 2026
Thank you again for your report! A fix is on its way.
As for the OffsetDateTime example: I don't have any answer to this question. The example is correct, and it is an example in the OffsetDateTime section, so it makes sense to use this class. I need to find the author of the page and ask that person about that. It may take a while though, because this page has probably beed written some years ago.
willy-b commentedon Jul 18, 2026
Thanks so much! However, some of the updates made were not quite as requested and comments were not updated along with the code, so I give some additional clarifications and instructions below.
In the latest version of https://dev.java/learn/date-time/parsing-formatting/ (archived as is at https://web.archive.org/web/20260718094137/https://dev.java/learn/date-time/parsing-formatting/?none=9 )
Re: the sentence
The update wasn't quite made as requested and seems to require a small additional update to be grammatical:
"However, if specify ..." should be "However, if you specify" (there are other ways too, like "However, if one specifies" or "However, if specifying", etc).
In the latest version of https://dev.java/learn/date-time/non-iso-conversion/ (arhived as is at https://web.archive.org/web/20260718094119/https://dev.java/learn/date-time/non-iso-conversion/?nonce=4 ),
toString/fromString code example comments mention code that was just removed by the dev.java team
Thanks for the updates just made by the dev.java team,
but it seems the comments in the code examples have not been updated, as they still mention using ChronoLocalDate(s).
That is, (1) the toString comments mention a ChronoLocalDate conversion step which was removed (should not mention this):
and (2) the fromString comments are also out of date (mention the ChronoLocalDate intermediate step that was removed):
Furthermore, the fromString code example still has unnecessary steps (see below) and uses a formatting pattern instead of relying only on builder parameters, inconsistent with toString
This should NOT convert from text to TemporalAccessor, then to LocalDate, using DateTimeFormatter 2x instead of 1x
(simpler would be just to use
return LocalDate.parse(text, df);).Also, the fromString example should not use a pattern string when the toString method does not use one, and should configure the DateTimeFormatter exactly the same for fromString as for toString.
(And as mentioned above separately, the comment above fromString is also out of date, mentioning ChronoLocalDate which is no longer used.)
In the latest version of https://dev.java/learn/date-time/legacy-code/ (archived as is at https://web.archive.org/web/20260718095302/https://dev.java/learn/date-time/legacy-code/?nonce=15 ),
(this was mentioned earlier but has not been fixed so I mention it again)
The sentence
is inconsistent. It mentions a table from https://dev.java/learn/date-time/intro/ as introduced on https://dev.java/learn/date-time/standard-calendar (how can this be so?).
Furthermore, the table linked above actually gives method names, NOT classes, and classes from the java.time package are not even mentioned. The table link referenced above was probably intended by the dev.java author to be https://dev.java/learn/date-time/standard-calendar/#intro (archived as is at https://web.archive.org/web/20260718101606/https://dev.java/learn/date-time/standard-calendar/?nonce=19 , scroll down to appropriate section) instead of https://dev.java/learn/date-time/intro/#methods (archived as is at https://web.archive.org/web/20260718101533/https://dev.java/learn/date-time/intro/?nonce=16 , scroll down to the appropriate section ).
Thanks!
JosePaumard commentedon Jul 20, 2026
Thank you again for your report! A fix is on its way.
willy-b commentedon Jul 30, 2026
Thanks for the updates, the items reported above have been resolved.
In the latest version of https://dev.java/learn/date-time/temporal/ (archived as is at https://web.archive.org/web/20260730074408/https://dev.java/learn/date-time/temporal/?nonce=1 )
In the code example
LocalDate = dateshould beLocalDate date.On a separate note, in the upstream Javadocs (not dev.java but maybe you can share this with the appropriate team), on https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/temporal/TemporalField.html#adjustInto(R,long)
for
TemporalField.adjustInto(R temporal, long newValue), there appears to be an error in their provided code example:The example uses a non-existent one-argument overload of TemporalField.adjustInto (there is only the two argument form
TemporalField.adjustInto(Temporal,long)( https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/temporal/TemporalField.html#adjustInto(R,long) ); the example seems confused with TemporalAdjuster which has a same name method with one argument, atTemporalAdjuster.adjustInto(java.time.temporal.Temporal)( https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/temporal/TemporalAdjuster.html#adjustInto(java.time.temporal.Temporal) ))The first line of the example should be
temporal = thisField.adjustInto(temporal, someLongValue);.for some longsomeLongValue.The second line of the example above also seems to confuse
Temporal.with(java.time.temporal.TemporalField,long)( https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/temporal/Temporal.html#with(java.time.temporal.TemporalField,long) )with a method accepting a TemporalAdjuster instead of a TemporalField,
Temporal.with(java.time.temporal.TemporalAdjuster)( https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/temporal/Temporal.html#with(java.time.temporal.TemporalAdjuster) ) .So the second line should be
temporal = temporal.with(thisField, someLongValue);(using https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/time/temporal/Temporal.html#with(java.time.temporal.TemporalField,long) ).Annotated image:

Thanks!
JosePaumard commentedon Jul 31, 2026
Thank you again for your report! A fix is on its way.
willy-b commentedon Aug 5, 2026
Thanks! Here are a few more items that came up during additional review of this material.
In the latest version of https://dev.java/learn/reflection/constructors/ (archived as is at https://web.archive.org/web/20260804200244/https://dev.java/learn/reflection/constructors/?nonce=2 )
In the sentence
"to create instance of" should be either "to create an instance of" (with singular "an object" or "a class") or "to create instances of" (with plural "objects").
In the sentence (this one is trivial, but may be of interest to fix)
it may be clearer to replace "no-arg constructor" with "constructor" because Constructor.newInstance(Object... initargs) can throw an IllegalAccessException regardless of whether the constructor invoked is no-arg,
even though the particular code example here happens to invoke a no-arg constructor (and of String.)
In the latest version of https://dev.java/learn/reflection/arrays/ (archived as is at https://web.archive.org/web/20260805044605/https://dev.java/learn/reflection/arrays/ )
In the sentence
"of 10 int" should be "of 10 ints".
In the latest version of https://dev.java/learn/date-time/non-iso-conversion/ (archived as is at https://web.archive.org/web/20260801202426/https://dev.java/learn/date-time/non-iso-conversion/?nonce=10 )
In the fromString code example
the ending curly brace is on the same line when it should be on a new line to be consistent with the rest of the code example.
In the latest version of https://dev.java/learn/date-time/legacy-code/ (archived as is at https://web.archive.org/web/20260801204511/https://dev.java/learn/date-time/legacy-code/?nonce=11 )
In the sentence
"to the rules used each time zone" should be "to the rules used by each time zone" (missing "by").
Thanks!