From 94de7ab2b34c8b52a90db5cfd77729f40e20686a Mon Sep 17 00:00:00 2001 From: Protobuf Team Bot Date: Thu, 4 Jun 2026 11:14:48 -0700 Subject: [PATCH] Introduce `getMessageExtensionOrNull` for extendable messages to avoid the code pattern of `hasExtension() ? getExtension : null` which takes an extra extension lookup. PiperOrigin-RevId: 926787242 --- .../com/google/protobuf/GeneratedMessage.java | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java index 4e955b0689..45e69f0c19 100644 --- a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java +++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java @@ -961,6 +961,10 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial /** Get the value of an extension. */ T getExtension(ExtensionLite extension); + /** Get the value of a message-typed extension, or null if it is not set. */ + T getMessageTypedExtensionOrNull( + ExtensionLite extension); + /** Overload to maintain ABI compatibility. See {@link #getExtension(ExtensionLite)}. */ default T getExtension(Extension extension) { return getExtension((ExtensionLite) extension); @@ -1098,6 +1102,21 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial return (T) extension.fromReflectionType(value); } + @Override + @SuppressWarnings("unchecked") // Safe as fromReflectionType will always match the type of T. + public final T getMessageTypedExtensionOrNull( + final ExtensionLite extensionLite) { + Extension extension = checkNotLite(extensionLite); + + final FieldDescriptor descriptor = extension.getDescriptor(); + verifyExtensionContainingType(descriptor); + final Object value = extensions.getField(descriptor); + if (value == null) { + return null; + } + return (T) extension.fromReflectionType(value); + } + /** Get one element of a repeated extension. */ @Override @SuppressWarnings("unchecked") @@ -1484,6 +1503,22 @@ public abstract class GeneratedMessage extends AbstractMessage implements Serial return (T) extension.fromReflectionType(value); } + @Override + @SuppressWarnings("unchecked") // Safe as fromReflectionType will always match the type of T. + public final T getMessageTypedExtensionOrNull( + final ExtensionLite extensionLite) { + Extension extension = checkNotLite(extensionLite); + verifyExtensionContainingType(extension); + if (extensions == null) { + return null; + } + final Object value = extensions.getField(extension.getDescriptor()); + if (value == null) { + return null; + } + return (T) extension.fromReflectionType(value); + } + /** Get one element of a repeated extension. */ @Override public final T getExtension(