blob: cbcec5f21a697c0848c5ac84ecf84f1504956453 [file] [log] [blame] [view]
Andrew Grieve8d9e40f2023-03-15 21:04:421# Chromium Java Style Guide
nyquist9d61f982017-02-10 00:29:082
3_For other languages, please see the [Chromium style
John Palmerbe051302021-05-19 11:48:354guides](https://chromium.googlesource.com/chromium/src/+/main/styleguide/styleguide.md)._
nyquist9d61f982017-02-10 00:29:085
6Chromium follows the [Android Open Source style
7guide](http://source.android.com/source/code-style.html) unless an exception
8is listed below.
9
nyquistaae4c7c2017-02-15 20:41:4210You can propose changes to this style guide by sending an email to
11`[email protected]`. Ideally, the list will arrive at some consensus and you can
12request review for a change to this file. If there's no consensus,
John Palmerbe051302021-05-19 11:48:3513[`//styleguide/java/OWNERS`](https://chromium.googlesource.com/chromium/src/+/main/styleguide/java/OWNERS)
nyquistaae4c7c2017-02-15 20:41:4214get to decide.
15
agrieve0e6bdf22018-08-03 14:25:2416[TOC]
17
Andrew Grieve8282bf22023-01-13 17:29:1718## Java 10 Language Features
Nate Fischer03308e92022-11-07 18:14:5919
Andrew Grieve8d9e40f2023-03-15 21:04:4220### Type Deduction using `var`
Nate Fischer03308e92022-11-07 18:14:5921
22A variable declaration can use the `var` keyword in place of the type (similar
23to the `auto` keyword in C++). In line with the [guidance for
24C++](https://google.github.io/styleguide/cppguide.html#Type_deduction), the
25`var` keyword may be used when it aids readability and the type of the value is
26already clear (ex. `var bundle = new Bundle()` is OK, but `var something =
27returnValueIsNotObvious()` may be unclear to readers who are new to this part of
28the code).
29
30The `var` keyword may also be used in try-with-resources when the resource is
31not directly accessed (or when it falls under the previous guidance), such as:
32
33```java
34try (var ignored = StrictModeContext.allowDiskWrites()) {
35 // 'var' is permitted so long as the 'ignored' variable is not used directly
36 // in the code.
37}
38```
39
agrieve0e6bdf22018-08-03 14:25:2440## Java 8 Language Features
Andrew Grieve8d9e40f2023-03-15 21:04:4241
Andrew Grieve8282bf22023-01-13 17:29:1742[D8] is used to rewrite some Java 7 & 8 language constructs in a way that is
43compatible with Java 6 (and thus all Android versions). Use of [these features]
44is encouraged.
agrieve0e6bdf22018-08-03 14:25:2445
Andrew Grieve8282bf22023-01-13 17:29:1746[D8]: https://developer.android.com/studio/command-line/d8
47[these features]: https://developer.android.com/studio/write/java8-support
agrieve0e6bdf22018-08-03 14:25:2448
Andrew Grieve8282bf22023-01-13 17:29:1749## Java Library APIs
agrieve0e6bdf22018-08-03 14:25:2450
Andrew Grieve8282bf22023-01-13 17:29:1751Android provides the ability to bundle copies of `java.` APIs alongside
52application code, known as [Java Library Desugaring]. However, since this
53bundling comes with a performance cost, Chrome does not use it. Treat `java.`
54APIs the same as you would `android.` ones and guard them with
55`Build.VERSION.SDK_INT` checks [when necessary]. The one exception is if the
56method is [directly backported by D8] (these are okay to use, since they are
57lightweight). Android Lint will fail if you try to use an API without a
58corresponding `Build.VERSION.SDK_INT` guard or `@RequiresApi` annotation.
59
60[Java Library Desugaring]: https://developer.android.com/studio/write/java8-support-table
61[when necessary]: https://developer.android.com/reference/packages
62[directly backported by D8]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/r8/backported_methods.txt
agrieve0e6bdf22018-08-03 14:25:2463
agrieve398286b2018-08-15 01:44:4564## Other Language Features & APIs
65
66### Exceptions
Andrew Grieve318b35322023-01-13 16:03:2367We discourage overly broad catches via `Throwable`, `Exception`, or
68`RuntimeException`, except when dealing with `RemoteException` or similar
69system APIs.
70 * There have been many cases of crashes caused by `IllegalStateException` /
71 `IllegalArgumentException` / `SecurityException` being thrown where only
72 `RemoteException` was being caught. In these cases, use
73 `catch (RemoteException | RuntimeException e)`.
74 * For all broad catch expressions, add a comment to explain why.
agrieve398286b2018-08-15 01:44:4575
Andrew Grieve318b35322023-01-13 16:03:2376Avoid adding messages to exceptions that do not aid in debugging. For example:
agrieve398286b2018-08-15 01:44:4577
agrieve50430de2018-08-15 17:49:1678```java
79try {
80 somethingThatThrowsIOException();
81} catch (IOException e) {
82 // Bad - message does not tell you more than the stack trace does:
83 throw new RuntimeException("Failed to parse a file.", e);
84 // Good - conveys that this block failed along with the "caused by" exception.
85 throw new RuntimeException(e);
86 // Good - adds useful information.
87 throw new RuntimeException(String.format("Failed to parse %s", fileName), e);
88}
89```
90
agrieve398286b2018-08-15 01:44:4591### Logging
Andrew Grieve8d9e40f2023-03-15 21:04:4292
agrieve398286b2018-08-15 01:44:4593* Use `org.chromium.base.Log` instead of `android.util.Log`.
94 * It provides `%s` support, and ensures log stripping works correctly.
95* Minimize the use of `Log.w()` and `Log.e()`.
96 * Debug and Info log levels are stripped by ProGuard in release builds, and
97 so have no performance impact for shipping builds. However, Warning and
98 Error log levels are not stripped.
99* Function calls in log parameters are *not* stripped by ProGuard.
100
101```java
102Log.d(TAG, "There are %d cats", countCats()); // countCats() not stripped.
103```
104
105### Asserts
Andrew Grieve8d9e40f2023-03-15 21:04:42106
agrieve398286b2018-08-15 01:44:45107The Chromium build system strips asserts in release builds (via ProGuard) and
108enables them in debug builds (or when `dcheck_always_on=true`) (via a [build
109step](https://codereview.chromium.org/2517203002)). You should use asserts in
110the [same
John Palmerbe051302021-05-19 11:48:35111scenarios](https://chromium.googlesource.com/chromium/src/+/main/styleguide/c++/c++.md#CHECK_DCHECK_and-NOTREACHED)
agrieve398286b2018-08-15 01:44:45112where C++ DCHECK()s make sense. For multi-statement asserts, use
Nate Fischer4570ebc32021-06-04 00:44:45113`org.chromium.build.BuildConfig.ENABLE_ASSERTS` to guard your code (similar to
114`#if DCHECK_IS_ON()` in C++).
agrieve398286b2018-08-15 01:44:45115
116Example assert:
117
118```java
119assert someCallWithoutSideEffects() : "assert description";
120```
121
Nate Fischer4570ebc32021-06-04 00:44:45122Example use of `BuildConfig.ENABLE_ASSERTS`:
agrieve398286b2018-08-15 01:44:45123
124```java
Nate Fischer4570ebc32021-06-04 00:44:45125import org.chromium.build.BuildConfig;
126
127...
128
129if (BuildConfig.ENABLE_ASSERTS) {
agrieve398286b2018-08-15 01:44:45130 // Any code here will be stripped in Release by ProGuard.
131 ...
132}
133```
134
Andrew Grieve8d9e40f2023-03-15 21:04:42135### Streams
136
137Most uses of [Java 8 streams] are discouraged. If you can write your code as an
138explicit loop, then do so. The primary reason for this guidance is because the
139lambdas (and method references) needed for streams almost always result in
140larger binary size ([example](https://chromium-review.googlesource.com/c/chromium/src/+/4329952).
141
142The `parallel()` and `parallelStream()` APIs are simpler than their loop
143equivalents, but are are currently banned due to a lack of a compelling use case
144in Chrome. If you find one, please discuss on `[email protected]`.
145
146[Java 8 streams]: https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html
147
agrieve16c6fe82018-11-27 17:47:49148### Finalizers
Andrew Grieve8d9e40f2023-03-15 21:04:42149
agrieve16c6fe82018-11-27 17:47:49150In line with [Google's Java style guide](https://google.github.io/styleguide/javaguide.html#s6.4-finalizers),
151never override `Object.finalize()`.
152
153Custom finalizers:
154* are called on a background thread, and at an unpredicatble point in time,
155* swallow all exceptions (asserts won't work),
156* causes additional garbage collector jank.
157
158Classes that need destructor logic should provide an explicit `destroy()`
John Palmerbe051302021-05-19 11:48:35159method. Use [LifetimeAssert](https://chromium.googlesource.com/chromium/src/+/main/base/android/java/src/org/chromium/base/LifetimeAssert.java)
Bo Liu9bb53ca2020-09-22 00:48:10160to ensure in debug builds and tests that `destroy()` is called.
agrieve16c6fe82018-11-27 17:47:49161
Nate Fischer74cd25c2020-12-16 16:17:03162### AndroidX Annotations
Andrew Grieve8d9e40f2023-03-15 21:04:42163
agrieve398286b2018-08-15 01:44:45164* Use them! They are [documented here](https://developer.android.com/studio/write/annotations).
165 * They generally improve readability.
166 * Some make lint more useful.
Nate Fischer74cd25c2020-12-16 16:17:03167* `javax.annotation.Nullable` vs `androidx.annotation.Nullable`
168 * Always prefer `androidx.annotation.Nullable`.
agrieve398286b2018-08-15 01:44:45169 * It uses `@Retention(SOURCE)` rather than `@Retention(RUNTIME)`.
170
Carlos Knippschildf2e58c12021-06-03 01:43:37171### IntDef Instead of Enum
172
173Java enums generate far more bytecode than integer constants. When integers are
174sufficient, prefer using an [@IntDef annotation], which will have usage checked
175by [Android lint].
176
177Values can be declared outside or inside the `@interface`. We recommend the
178latter, with constants nested within it as follows:
179
180```java
181@IntDef({ContactsPickerAction.CANCEL, ContactsPickerAction.CONTACTS_SELECTED,
182 ContactsPickerAction.SELECT_ALL, ContactsPickerAction.UNDO_SELECT_ALL})
183@Retention(RetentionPolicy.SOURCE)
184public @interface ContactsPickerAction {
185 int CANCEL = 0;
186 int CONTACTS_SELECTED = 1;
187 int SELECT_ALL = 2;
188 int UNDO_SELECT_ALL = 3;
189 int NUM_ENTRIES = 4;
190}
191// ...
192void onContactsPickerUserAction(@ContactsPickerAction int action, ...);
193```
194
195Values of `Integer` type are also supported, which allows using a sentinel
196`null` if needed.
197
198[@IntDef annotation]: https://developer.android.com/studio/write/annotations#enum-annotations
199[Android lint]: https://chromium.googlesource.com/chromium/src/+/HEAD/build/android/docs/lint.md
200
agrieve398286b2018-08-15 01:44:45201## Style / Formatting
nyquistaae4c7c2017-02-15 20:41:42202
agrieve398286b2018-08-15 01:44:45203### File Headers
John Palmerbe051302021-05-19 11:48:35204* Use the same format as in the [C++ style guide](https://chromium.googlesource.com/chromium/src/+/main/styleguide/c++/c++.md#File-headers).
nyquistaae4c7c2017-02-15 20:41:42205
agrieve398286b2018-08-15 01:44:45206### TODOs
Andrew Grieve8d9e40f2023-03-15 21:04:42207
agrieve398286b2018-08-15 01:44:45208* TODO should follow chromium convention. Examples:
209 * `TODO(username): Some sentence here.`
210 * `TODO(crbug.com/123456): Even better to use a bug for context.`
nyquistaae4c7c2017-02-15 20:41:42211
Andrew Grieve8d9e40f2023-03-15 21:04:42212### Code Formatting
213
nyquist9d61f982017-02-10 00:29:08214* Fields should not be explicitly initialized to default values (see
215 [here](https://groups.google.com/a/chromium.org/d/topic/chromium-dev/ylbLOvLs0bs/discussion)).
nyquistaae4c7c2017-02-15 20:41:42216
Andrew Grieve8d9e40f2023-03-15 21:04:42217### Curly Braces
218
nyquistaae4c7c2017-02-15 20:41:42219Conditional braces should be used, but are optional if the conditional and the
220statement can be on a single line.
221
222Do:
223
224```java
225if (someConditional) return false;
226for (int i = 0; i < 10; ++i) callThing(i);
227```
228
229or
230
231```java
232if (someConditional) {
233 return false;
234}
235```
236
237Do NOT do:
238
239```java
240if (someConditional)
241 return false;
242```
243
nyquist2d192c4c2017-03-06 21:36:51244### Import Order
Andrew Grieve8d9e40f2023-03-15 21:04:42245
nyquist2d192c4c2017-03-06 21:36:51246* Static imports go before other imports.
247* Each import group must be separated by an empty line.
248
249This is the order of the import groups:
250
2511. android
Yun Liuf40227d92019-04-04 17:37:462521. androidx
nyquist2d192c4c2017-03-06 21:36:512531. com (except com.google.android.apps.chrome)
2541. dalvik
2551. junit
2561. org
2571. com.google.android.apps.chrome
2581. org.chromium
2591. java
2601. javax
261
Caitlin Fischer210cfab2020-05-07 20:04:30262## Test-only Code
Andrew Grieve8d9e40f2023-03-15 21:04:42263
Andrew Grieve0872aad2023-06-26 14:16:31264Functions and fields used only for testing should have `ForTesting` as a
265suffix so that:
Caitlin Fischer210cfab2020-05-07 20:04:30266
Andrew Grieve0872aad2023-06-26 14:16:312671. The `android-binary-size` trybot can [ensure they are removed] in
268 non-test optimized builds (by R8).
2692. [`PRESUMBIT.py`] can ensure no calls are made to such methods outside of
270 tests, and
271
272`ForTesting` methods that are `@CalledByNative` should use
273`@CalledByNativeForTesting` instead.
274
275Symbols that are made public (or package-private) for the sake of tests
276should be annotated with [`@VisibleForTesting`]. Android Lint will check
277that calls from non-test code respect the "otherwise" visibility.
278
279Symbols with a `ForTesting` suffix should **not** be annotated with
280`@VisibleForTesting`. While `otherwise=VisibleForTesting.NONE` exists, it
281is redundant given the "ForTesting" suffix and the associated lint check
282is redundant given our trybot check.
283
284[ensure they are removed]: /docs/speed/binary_size/android_binary_size_trybot.md#Added-Symbols-named-ForTest
285[`PRESUMBIT.py`]: https://chromium.googlesource.com/chromium/src/+/main/PRESUBMIT.py
286[`@VisibleForTesting`]: https://developer.android.com/reference/androidx/annotation/VisibleForTesting
Sam Maier7452a0d2022-07-20 18:24:35287
nyquist9d61f982017-02-10 00:29:08288## Location
Andrew Grieve8d9e40f2023-03-15 21:04:42289
nyquist9d61f982017-02-10 00:29:08290"Top level directories" are defined as directories with a GN file, such as
John Palmerbe051302021-05-19 11:48:35291[//base](https://chromium.googlesource.com/chromium/src/+/main/base/)
nyquist9d61f982017-02-10 00:29:08292and
John Palmerbe051302021-05-19 11:48:35293[//content](https://chromium.googlesource.com/chromium/src/+/main/content/),
nyquist9d61f982017-02-10 00:29:08294Chromium Java should live in a directory named
295`<top level directory>/android/java`, with a package name
296`org.chromium.<top level directory>`. Each top level directory's Java should
297build into a distinct JAR that honors the abstraction specified in a native
John Palmerbe051302021-05-19 11:48:35298[checkdeps](https://chromium.googlesource.com/chromium/buildtools/+/main/checkdeps/checkdeps.py)
nyquist9d61f982017-02-10 00:29:08299(e.g. `org.chromium.base` does not import `org.chromium.content`). The full
300path of any java file should contain the complete package name.
301
302For example, top level directory `//base` might contain a file named
303`base/android/java/org/chromium/base/Class.java`. This would get compiled into a
304`chromium_base.jar` (final JAR name TBD).
305
306`org.chromium.chrome.browser.foo.Class` would live in
307`chrome/android/java/org/chromium/chrome/browser/foo/Class.java`.
308
309New `<top level directory>/android` directories should have an `OWNERS` file
310much like
John Palmerbe051302021-05-19 11:48:35311[//base/android/OWNERS](https://chromium.googlesource.com/chromium/src/+/main/base/android/OWNERS).
nyquist9d61f982017-02-10 00:29:08312
Andrew Grieve0872aad2023-06-26 14:16:31313## Tools
314
315### Automatically Formatting Edited Files
316
317A checkout should give you clang-format to automatically format Java code.
318It is suggested that Clang's formatting of code should be accepted in code
319reviews.
320
321You can run `git cl format` to apply the automatic formatting.
322
323### IDE Setup
324
325For automatically using the correct style, follow the guide to set up your
326favorite IDE:
327
328* [Android Studio](https://chromium.googlesource.com/chromium/src/+/main/docs/android_studio.md)
329* [Eclipse](https://chromium.googlesource.com/chromium/src/+/main/docs/eclipse.md)
330
331### Checkstyle
332
333Checkstyle is automatically run by the build bots, and to ensure you do not have
334any surprises, you can also set up checkstyle locally using [this
335guide](https://sites.google.com/a/chromium.org/dev/developers/checkstyle).
336
337### Lint
338
339Lint is run as part of the build. For more information, see
340[here](https://chromium.googlesource.com/chromium/src/+/main/build/android/docs/lint.md).
341
nyquistaae4c7c2017-02-15 20:41:42342## Miscellany
Andrew Grieve8d9e40f2023-03-15 21:04:42343
nyquistaae4c7c2017-02-15 20:41:42344* Use UTF-8 file encodings and LF line endings.