Introduce `getMessageExtensionOrNull` for extendable messages to avoid the code pattern of `hasExtension() ? getExtension : null` which takes an extra extension lookup. PiperOrigin-RevId: 926787242
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 4e955b0..45e69f0 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 @@ /** Get the value of an extension. */ <T> T getExtension(ExtensionLite<? extends MessageT, T> extension); + /** Get the value of a message-typed extension, or null if it is not set. */ + <T extends MessageLite> T getMessageTypedExtensionOrNull( + ExtensionLite<? extends MessageT, T> extension); + /** Overload to maintain ABI compatibility. See {@link #getExtension(ExtensionLite)}. */ default <T> T getExtension(Extension<? extends MessageT, T> extension) { return getExtension((ExtensionLite<? extends MessageT, T>) extension); @@ -1098,6 +1102,21 @@ return (T) extension.fromReflectionType(value); } + @Override + @SuppressWarnings("unchecked") // Safe as fromReflectionType will always match the type of T. + public final <T extends MessageLite> T getMessageTypedExtensionOrNull( + final ExtensionLite<? extends MessageT, T> extensionLite) { + Extension<MessageT, T> 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 @@ return (T) extension.fromReflectionType(value); } + @Override + @SuppressWarnings("unchecked") // Safe as fromReflectionType will always match the type of T. + public final <T extends MessageLite> T getMessageTypedExtensionOrNull( + final ExtensionLite<? extends MessageT, T> extensionLite) { + Extension<MessageT, T> 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> T getExtension(