Java Generated Code Guide
Any differences between proto2, proto3, and Editions generated code are highlighted—note that these differences are in the generated code as described in this document, not the base message classes/interfaces, which are the same in all versions. You should read the proto2 language guide, proto3 language guide, and/or Editions language guide before reading this document.
Note that no Java Protobuf methods accept or return nulls unless otherwise specified.
Compiler Invocation
The Protobuf compiler produces Java output when invoked with the --java_out=
command-line flag. The parameter to the --java_out= option is the directory
where you want the compiler to write your Java output. For each .proto file
input, the compiler creates a wrapper .java file containing a Java class that
represents the .proto file itself.
If the .proto file contains a line like the following:
option java_multiple_files = true;
Then the compiler will also create separate .java files for each of the
classes/enums which it will generate for each top-level message, enumeration,
and service declared in the .proto file.
Otherwise (when the java_multiple_files option is disabled, which is the
default), the aforementioned wrapper class will also be used as an outer class,
and the generated classes/enums for each top-level message, enumeration, and
service declared in the .proto file will all be nested within the outer
wrapper class. Thus the compiler will only generate a single .java file for
the entire .proto file, and it will have an extra layer in the package
The wrapper class’s name is chosen as follows: If the .proto file contains a
line like the following:
option java_outer_classname = "Foo";
Then the wrapper class name will be Foo. Otherwise, the wrapper class name is
determined by converting the .proto file base name to camel case. For example,
foo_bar.proto will generate a class name of FooBar. If there’s a service,
enum, or message (including nested types) in the file with the same name,
“OuterClass” will be appended to the wrapper class’s name. Examples:
- If
foo_bar.protocontains a message calledFooBar, the wrapper class will generate a class name ofFooBarOuterClass. - If
foo_bar.protocontains a service calledFooService, andjava_outer_classnameis also set to the stringFooService, then the wrapper class will generate a class name ofFooServiceOuterClass.
Note
If you are using the deprecated v1 of the Protobuf API,OuterClass is added regardless of
any collisions with message names.In addition to any nested classes, the wrapper class itself will have the
following API (assuming the wrapper class is named Foo and was generated from
foo.proto):
public final class Foo {
private Foo() {} // Not instantiable.
/** Returns a FileDescriptor message describing the contents of {@code foo.proto}. */
public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor();
/** Adds all extensions defined in {@code foo.proto} to the given registry. */
public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry registry);
public static void registerAllExtensions(com.google.protobuf.ExtensionRegistryLite registry);
// (Nested classes omitted)
}
The Java package name is chosen as described under Packages, below.
The output file is chosen by concatenating the parameter to --java_out=, the
package name (with .s replaced with /s), and the .java file name.
So, for example, let’s say you invoke the compiler as follows:
protoc --proto_path=src --java_out=build/gen src/foo.proto
If foo.proto’s Java package is com.example and it doesn’t enable
java_multiple_files and its outer classname is FooProtos, then the Protobuf
compiler will generate the file build/gen/com/example/FooProtos.java. The
Protobuf compiler will automatically create the build/gen/com and
build/gen/com/example directories if needed. However, it will not create
build/gen or build; they must already exist. You can specify multiple
.proto files in a single invocation; all output files will be generated at
once.
When outputting Java code, the Protobuf compiler’s ability to output directly to
JAR archives is particularly convenient, as many Java tools are able to read
source code directly from JAR files. To output to a JAR file, simply provide an
output location ending in .jar. Note that only the Java source code is placed
in the archive; you must still compile it separately to produce Java class
files.
Packages
The generated class is placed in a Java package based on the java_package
option. If the option is omitted, the package declaration is used
instead.
For example, if the .proto file contains:
package foo.bar;
Then the resulting Java class will be placed in Java
package foo.bar. However, if
the .proto file also contains a java_package option, like so:
package foo.bar;
option java_package = "com.example.foo.bar";
Then the class is placed in the com.example.foo.bar package instead. The
java_package option is provided because normal .proto package declarations
are not expected to start with a backwards domain name.
Messages
If you are designing a new Protobuf schema, see the recommendations for Java proto names.
Given a simple message declaration:
message Foo {}
The Protobuf compiler generates a class called Foo, which implements the
Message interface. The class is declared final; no further subclassing is
allowed. Foo extends GeneratedMessage, but this should be considered an
implementation detail. By default, Foo overrides many methods of
GeneratedMessage with specialized versions for maximum speed. However, if the
.proto file contains the line:
option optimize_for = CODE_SIZE;
then Foo will override only the minimum set of methods necessary to function
and rely on GeneratedMessage’s reflection-based implementations of the rest.
This significantly reduces the size of the generated code, but also reduces
performance. Alternatively, if the .proto file contains:
option optimize_for = LITE_RUNTIME;
then Foo will include fast implementations of all methods, but will implement
the MessageLite interface, which contains a subset of the methods of
Message. In particular, it does not support descriptors, nested builders, or
reflection. However, in this mode, the generated code only needs to link against
libprotobuf-lite.jar instead of libprotobuf.jar. The “lite” library is much
smaller than the full library, and is more appropriate for resource-constrained
systems such as mobile phones.
The Message interface defines methods that let you check, manipulate, read, or
write the entire message. In addition to these methods, the Foo class defines
the following static methods:
static Foo getDefaultInstance(): Returns the singleton instance ofFoo. This instance’s contents are identical to what you’d get if you calledFoo.newBuilder().build()(so all singular fields are unset and all repeated fields are empty). Note that the default instance of a message can be used as a factory by calling itsnewBuilderForType()method.static Descriptor getDescriptor(): Returns the type’s descriptor. This contains information about the type, including what fields it has and what their types are. This can be used with the reflection methods of theMessage, such asgetField().static Foo parseFrom(...): Parses a message of typeFoofrom the given source and returns it. There is oneparseFrommethod corresponding to each variant ofmergeFrom()in theMessage.Builderinterface. Note thatparseFrom()never throwsUninitializedMessageException; it throwsInvalidProtocolBufferExceptionif the parsed message is missing required fields. This makes it subtly different from callingFoo.newBuilder().mergeFrom(...).build().static Parser parser(): Returns an instance of theParser, which implements variousparseFrom()methods.Foo.Builder newBuilder(): Creates a new builder (described below).Foo.Builder newBuilder(Foo prototype): Creates a new builder with all fields initialized to the same values that they have inprototype. Since embedded message and string objects are immutable, they are shared between the original and the copy.
Builders
Message objects—such as instances of the Foo class described
above—are immutable, just like a Java String. To construct a message
object, you need to use a builder. Each message class has its own builder
class—so in our Foo example, the Protobuf compiler generates a nested
class Foo.Builder which can be used to build a Foo. Foo.Builder implements
the Message.Builder interface. It extends the GeneratedMessage.Builder
class, but, again, this should be considered an implementation detail. Like
Foo, Foo.Builder may rely on generic method implementations in
GeneratedMessage.Builder or, when the optimize_for option is used, generated
custom code that is much faster. You can get a Foo.Builder by calling the
static method Foo.newBuilder().
Foo.Builder does not define any static methods. Its interface is exactly as
defined by the Message.Builder interface, with the exception that return types
are more specific: methods of Foo.Builder that modify the builder return type
Foo.Builder, and build() returns type Foo.
Methods that modify the contents of a builder—including field
setters—always return a reference to the builder (i.e. they “return this;”). This allows multiple method calls to be chained together in one line.
For example: builder.mergeFrom(obj).setFoo(1).setBar("abc").clearBaz();
Note that builders are not thread-safe, so Java synchronization should be used whenever it is necessary for multiple different threads to be modifying the contents of a single builder.
Sub-Builders
For messages containing sub-messages, the compiler also generates sub-builders. This allows you to repeatedly modify deep-nested sub-messages without rebuilding them. For example:
message Foo {
int32 val = 1;
// some other fields.
}
message Bar {
Foo foo = 1;
// some other fields.
}
message Baz {
Bar bar = 1;
// some other fields.
}
If you have a Baz message already, and want to change the deeply nested val
in Foo. Instead of:
baz = baz.toBuilder().setBar(
baz.getBar().toBuilder().setFoo(