Java Language
Oficjalny kod Oracle
Szukaj…
Wprowadzenie
Oficjalny przewodnik po stylu Oracle dla języka programowania Java jest standardem przestrzeganym przez programistów Oracle, a także zalecany przez innych programistów Java. Obejmuje nazwy plików, organizację plików, wcięcia, komentarze, deklaracje, instrukcje, białe znaki, konwencje nazewnictwa, praktyki programowania i zawiera przykład kodu.
Uwagi
Powyższe przykłady są ściśle zgodne z nowym oficjalnym przewodnikiem po stylu Oracle. Innymi słowy, nie są subiektywnie tworzone przez autorów tej strony.
Oficjalny przewodnik po stylach został starannie napisany, aby był kompatybilny z pierwotnym przewodnikiem po stylu i większością kodu na wolności.
Oficjalny przewodnik styl został wzajemnej przeglądowi przez m.in. Brian Goetz (języka Java Architect) i Mark Reinhold (Chief Architect Platformy Java).
Przykłady są nienormatywne; Chociaż zamierzają zilustrować prawidłowy sposób formatowania kodu, mogą istnieć inne sposoby prawidłowego formatowania kodu. Jest to ogólna zasada: może istnieć kilka sposobów formatowania kodu, wszystkie zgodne z oficjalnymi wytycznymi.
Konwencje nazewnictwa
Nazwy paczek
- Nazwy pakietów powinny być pisane małymi literami, bez podkreślników i innych znaków specjalnych.
- Nazwy pakietów zaczynają się od części adresu URL firmy dewelopera z odwróconymi uprawnieniami. Po tej części może następować podstruktura pakietu zależna od projektu / programu.
- Nie używaj liczby mnogiej. Postępuj zgodnie z konwencją standardowego interfejsu API, który wykorzystuje na przykład
java.lang.annotation
a niejava.lang.annotations
. - Przykłady:
com.yourcompany.widget.button
,com.yourcompany.core.api
Nazwy klas, interfejsów i enum
- Nazwy klas i wyliczeń powinny zazwyczaj być rzeczownikami.
- Nazwy interfejsów powinny zazwyczaj być rzeczownikami lub przymiotnikami kończącymi się na… zdolny.
- Użyj wielkiej litery z pierwszą literą w każdym słowie wielkimi literami (tj. CamelCase ).
- Dopasuj wyrażenie regularne
^[AZ][a-zA-Z0-9]*$
. - Używaj całych słów i unikaj używania skrótów, chyba że skrót jest częściej używany niż długa forma.
- Sformatuj skrót jako słowo, jeśli jest ono częścią dłuższej nazwy klasy.
- Przykłady:
ArrayList
,BigInteger
,ArrayIndexOutOfBoundsException
,Iterable
.
Nazwy metod
Nazwy metod powinny zazwyczaj być czasownikami lub innymi opisami działań
- Powinny pasować do wyrażenia regularnego
^[az][a-zA-Z0-9]*$
. - Używaj małych i wielkich liter z pierwszą literą.
- Przykłady:
toString
,hashCode
Zmienne
Nazwy zmiennych powinny być pisane wielkimi literami, a pierwsza litera małymi literami
- Dopasuj wyrażenie regularne
^[az][a-zA-Z0-9]*$
- Dalsze zalecenia: Zmienne
- Przykłady:
elements
,currentIndex
Zmienne typu
W prostych przypadkach, w których występuje niewiele zmiennych typu, użyj jednej dużej litery.
- Dopasuj wyrażenie regularne
^[AZ][0-9]?$
- Jeśli jedna litera jest bardziej opisowa niż inna (np.
K
iV
dla kluczy i wartości w mapach lubR
dla typu zwracanego przez funkcję), użyj tego, w przeciwnym razie użyjT
- W skomplikowanych przypadkach, w których zmienne typu jednoliterowego stają się mylące, użyj dłuższych nazw pisanych wielkimi literami i użyj podkreślenia (
_
), aby rozdzielić słowa. - Przykłady:
T
,V
,SRC_VERTEX
Stałe
Stałe ( static final
pola static final
których treść jest niezmienna, według reguł językowych lub konwencji) powinny być nazwane wszystkimi dużymi literami i podkreśleniem ( _
) w celu oddzielenia słów.
- Dopasuj wyrażenie regularne
^[AZ][A-Z0-9]*(_[A-Z0-9]+)*$
- Przykłady:
BUFFER_SIZE
,MAX_LEVEL
Inne wytyczne dotyczące nazewnictwa
- Unikaj metod ukrywania / cieniowania, zmiennych i zmiennych typu w zewnętrznych zakresach.
- Niech gadatliwość nazwy koreluje z rozmiarem zakresu. (Na przykład, użyj opisowych nazw dla pól dużych klas i krótkich nazw dla lokalnych zmiennych krótkotrwałych.)
- Podczas nazywania publicznych elementów statycznych, pozwól, aby identyfikator był opisowy, jeśli uważasz, że zostaną one zaimportowane statycznie.
- Dalsza lektura: Sekcja nazewnictwa (w oficjalnym przewodniku po stylach Java)
Źródło: Java Style Guidelines od Oracle
Pliki źródłowe Java
Wszystkie linie muszą być zakończone znakiem przesunięcia linii (LF, wartość ASCII 10), a nie na przykład CR lub CR + LF.
Na końcu linii może nie być końcowych białych znaków.
Nazwa pliku źródłowego musi być równa nazwie zawartej w nim klasy, po której następuje rozszerzenie
.java
, nawet w przypadku plików zawierających tylko prywatną klasę pakietu. Nie dotyczy to plików, które nie zawierają deklaracji klas, takich jakpackage-info.java
.
Znaki specjalne
Oprócz LF jedynym dozwolonym znakiem białych znaków jest Spacja (wartość ASCII 32). Zauważ, że oznacza to, że inne znaki spacji (na przykład w literaturze łańcuchowej i znakowej) muszą być zapisane w postaci znaku zmiany znaczenia.
\'
,\"
,\\
,\t
,\b
,\r
,\f
i\n
powinny być preferowane w stosunku do odpowiadających im znaków ósemkowych (np.\047
) lub Unicode (np.\u0027
).Jeśli zachodzi potrzeba sprzeczności z powyższymi zasadami w celu przeprowadzenia testów, test powinien wygenerować wymagane dane programowo.
Deklaracja paczki
package com.example.my.package;
Deklaracja pakietu nie powinna być zawijana w linie, niezależnie od tego, czy przekracza ona zalecaną maksymalną długość linii.
Zaimportuj wyciągi
// First java/javax packages
import java.util.ArrayList;
import javax.tools.JavaCompiler;
// Then third party libraries
import com.fasterxml.jackson.annotation.JsonProperty;
// Then project imports
import com.example.my.package.ClassA;
import com.example.my.package.ClassB;
// Then static imports (in the same order as above)
import static java.util.stream.Collectors.toList;
Instrukcje importu należy posortować…
- … Głównie przez niestatyczny / statyczny z importem niestatycznym w pierwszej kolejności.
- … Po drugie według pochodzenia paczki zgodnie z następującą kolejnością
- pakiety java
- pakiety javax
- pakiety zewnętrzne (np. org.xml)
- pakiety wewnętrzne (np. com.sun)
- … Trzeciorzędny według paczki i identyfikatora klasy w porządku leksykograficznym
Instrukcje importu nie powinny być zawijane w wiersze, niezależnie od tego, czy przekraczają zalecaną maksymalną długość linii.
Niewykorzystany przywóz nie powinien być obecny.
Importowanie symboli wieloznacznych
- Ogólnie rzecz biorąc, nie należy używać importu symboli zastępczych.
- Podczas importowania dużej liczby blisko spokrewnionych klas (takich jak implementacja gościa nad drzewem z dziesiątkami różnych klas „węzłów”) można użyć importu symboli zastępczych.
- W każdym przypadku nie należy używać więcej niż jednego importu symboli wieloznacznych na plik.
Struktura klasy
Zakon członków klasy
Członków klasy należy uporządkować w następujący sposób:
- Pola (w kolejności publicznej, chronionej i prywatnej)
- Konstruktory
- Metody fabryczne
- Inne metody (w porządku publicznym, chronionym i prywatnym)
Zamawianie pól i metod przede wszystkim według ich modyfikatorów dostępu lub identyfikatora nie jest wymagane.
Oto przykład tego zamówienia:
class Example {
private int i;
Example(int i) {
this.i = i;
}
static Example getExample(int i) {
return new Example(i);
}
@Override
public String toString() {
return "An example [" + i + "]";
}
}
Grupowanie członków klasy
- Powiązane pola powinny być zgrupowane razem.
- Typ zagnieżdżony można zadeklarować tuż przed pierwszym użyciem; w przeciwnym razie należy zadeklarować przed polami.
- Konstruktory i przeciążone metody powinny być pogrupowane według funkcjonalności i uporządkowane ze wzrostem arsenacji. Oznacza to, że delegacja między tymi konstrukcjami płynie w dół w kodzie.
- Konstruktorzy powinni być zgrupowani razem, bez innych członków między.
- Przeciążone warianty metody powinny być grupowane razem, bez innych elementów między nimi.
Modyfikatory
class ExampleClass {
// Access modifiers first (don't do for instance "static public")
public static void main(String[] args) {
System.out.println("Hello World");
}
}
interface ExampleInterface {
// Avoid 'public' and 'abstract' since they are implicit
void sayHello();
}
Modyfikatory powinny iść w następującej kolejności
- Modyfikator dostępu (
public
/private
/protected
) -
abstract
-
static
-
final
-
transient
-
volatile
-
default
-
synchronized
-
native
-
strictfp
- Modyfikator dostępu (
Modyfikatory nie powinny być zapisywane, gdy są niejawne. Na przykład metody interfejsu nie powinny być deklarowane jako
public
aniabstract
, a zagnieżdżone wyliczenia i interfejsy nie powinny być deklarowane jako statyczne.Parametry metody i zmienne lokalne nie powinny być deklarowane jako
final
chyba że poprawi to czytelność lub udokumentuje faktyczną decyzję projektową.Pola powinny zostać uznane za
final
chyba że istnieje ważny powód, aby je modyfikować.
Wcięcie
- Poziom wcięcia to cztery spacje .
- Do wcięcia można stosować tylko znaki spacji. Brak kart.
- Puste linie nie mogą być wcięte. (Jest to implikowane przez zasadę, że nie ma końca białych znaków).
- wiersze
case
powinny być wcięte czterema spacjami, a instrukcje w sprawie powinny być wcięte kolejnymi czterema spacjami.
switch (var) {
case TWO:
setChoice("two");
break;
case THREE:
setChoice("three");
break;
default:
throw new IllegalArgumentException();
}
Wskazówki dotyczące sposobu wcięcia linii kontynuacji znajdują się w Zawijanie .
Zawijanie instrukcji
Kod źródłowy i komentarze na ogół nie powinny przekraczać 80 znaków w wierszu, a rzadko, jeśli w ogóle, przekraczać 100 znaków w wierszu, w tym wcięcia.
Limit znaków należy oceniać indywidualnie dla każdego przypadku. To, co naprawdę się liczy, to semantyczna „gęstość” i czytelność linii. Długie tworzenie linii sprawia, że są trudne do odczytania; podobnie podejmowanie „heroicznych prób” zmieszczenia ich w 80 kolumnach może również utrudnić ich odczytanie. Przedstawiona tutaj elastyczność ma na celu umożliwienie programistom uniknięcia tych ekstremów, a nie maksymalizację wykorzystania monitorowanych nieruchomości.
Adresy URL lub przykładowe polecenia nie powinny być opakowane.
// Ok even though it might exceed max line width when indented.
Error e = isTypeParam
? Errors.InvalidRepeatableAnnotationNotApplicable(targetContainerType, on)
: Errors.InvalidRepeatableAnnotationNotApplicableInContext(targetContainerType));
// Wrapping preferable
String pretty = Stream.of(args)
.map(Argument::prettyPrint)
.collectors(joining(", "));
// Too strict interpretation of max line width. Readability suffers.
Error e = isTypeParam
? Errors.InvalidRepeatableAnnotationNotApplicable(
targetContainerType, on)
: Errors.InvalidRepeatableAnnotationNotApplicableInContext(
targetContainerType);
// Should be wrapped even though it fits within the character limit
String pretty = Stream.of(args).map(Argument::prettyPrint).collectors(joining(", "));
Owijanie na wyższym poziomie syntaktycznym jest lepsze niż owijanie na niższym poziomie syntaktycznym.
W wierszu powinno być maksymalnie 1 instrukcja.
Linia kontynuacji powinna być wcięta na jeden z czterech poniższych sposobów
- Wariant 1 : 8 dodatkowych spacji w stosunku do wcięcia poprzedniej linii.
- Wariant 2 : Z 8 dodatkowymi spacjami względem kolumny początkowej zawiniętego wyrażenia.
- Wariant 3 : Wyrównany z poprzednim wyrażeniem rodzeństwa (o ile jest jasne, że jest to linia kontynuacji)
- Wariant 4 : Wyrównany z poprzednim wywołaniem metody w łańcuchowym wyrażeniu.
Deklaracja metody pakowania
int someMethod(String aString,
List<Integer> aList,
Map<String, String> aMap,
int anInt,
long aLong,
Set<Number> aSet,
double aDouble) {
…
}
int someMethod(String aString, List<Integer> aList,
Map<String, String> aMap, int anInt, long aLong,
double aDouble, long aLong) {
…
}
int someMethod(String aString,
List<Map<Integer, StringBuffer>> aListOfMaps,
Map<String, String> aMap)
throws IllegalArgumentException {
…
}
int someMethod(String aString, List<Integer> aList,
Map<String, String> aMap, int anInt)
throws IllegalArgumentException {
…
}
- Deklaracje metod można sformatować, wymieniając argumenty w pionie lub nową linię i +8 dodatkowych spacji
- Jeśli klauzula throws wymaga zawinięcia, umieść znak podziału wiersza przed klauzulą throws i upewnij się, że wyróżnia się na liście argumentów, albo przez wcięcie +8 w stosunku do deklaracji funkcji, albo +8 w stosunku do poprzedniej linii.
Zawijanie wyrażeń
- Jeśli linia zbliża się do maksymalnego limitu znaków, zawsze należy rozważyć podzielenie go na wiele instrukcji / wyrażeń zamiast zawijania linii.
- Przerwa przed operatorami.
- Przerwa przed. w połączonych wywołaniach metod.
popupMsg("Inbox notification: You have "
+ newMsgs + " new messages");
// Don't! Looks like two arguments
popupMsg("Inbox notification: You have " +
newMsgs + " new messages");
Biała przestrzeń
Pionowe białe znaki
Pojedynczej pustej linii należy użyć do oddzielenia…
- Deklaracja paczki
- Deklaracje klasowe
- Konstruktory
- Metody
- Inicjatory statyczne
- Inicjatory instancji
… I mogą być użyte do oddzielenia logicznych grup
- instrukcje importu
- pola
- sprawozdania
Wiele kolejnych pustych wierszy powinno być używanych tylko do oddzielania grup powiązanych elementów, a nie jako standardowe odstępy między elementami.
Pozioma biała spacja
Należy użyć jednej spacji…
- Aby oddzielić słowa kluczowe od sąsiednich nawiasów otwierających lub zamykających i nawiasów klamrowych
- Przed i po wszystkich operatorach binarnych i symbolach podobnych do operatorów, takich jak strzałki w wyrażeniach lambda i dwukropek w rozszerzonych pętlach (ale nie przed dwukropkiem etykiety)
- Po
//
zaczyna komentarz. - Po przecinkach oddzielanie argumentów i średników oddzielających części pętli for.
- Po zamykającym nawiasie obsady.
W deklaracjach zmiennych nie zaleca się wyrównywania typów i zmiennych.
Deklaracje zmienne
- Jedna zmienna na deklarację (i maksymalnie jedna deklaracja na linię)
- Nawiasy kwadratowe tablic powinny być typu (
String[] args
), a nie zmiennej (String args[]
). - Zadeklaruj zmienną lokalną tuż przed jej pierwszym użyciem i zainicjuj ją jak najbliżej deklaracji.
Adnotacje
Adnotacje do deklaracji należy umieszczać w osobnym wierszu niż adnotacje do deklaracji.
@SuppressWarnings("unchecked")
public T[] toArray(T[] typeHolder) {
...
}
Jednak kilka lub krótkie adnotacje opisujące metodę jednowierszową można umieścić w tym samym wierszu co metoda, jeśli poprawia to czytelność. Na przykład można napisać:
@Nullable String getName() { return name; }
Ze względu na spójność i czytelność wszystkie adnotacje należy umieścić w tym samym wierszu lub każdą adnotację należy umieścić w osobnej linii.
// Bad.
@Deprecated @SafeVarargs
@CustomAnnotation
public final Tuple<T> extend(T... elements) {
...
}
// Even worse.
@Deprecated @SafeVarargs
@CustomAnnotation public final Tuple<T> extend(T... elements) {
...
}
// Good.
@Deprecated
@SafeVarargs
@CustomAnnotation
public final Tuple<T> extend(T... elements) {
...
}
// Good.
@Deprecated @SafeVarargs @CustomAnnotation
public final Tuple<T> extend(T... elements) {
...
}
Wyrażenia lambda
Runnable r = () -> System.out.println("Hello World");
Supplier<String> c = () -> "Hello World";
// Collection::contains is a simple unary method and its behavior is
// clear from the context. A method reference is preferred here.
appendFilter(goodStrings::contains);
// A lambda expression is easier to understand than just tempMap::put in this case
trackTemperature((time, temp) -> tempMap.put(time, temp));
- Baranki ekspresyjne są bardziej preferowane niż lambdy blokowe jednowierszowe.
- Odniesienia do metod powinny być na ogół lepsze niż wyrażenia lambda.
- W przypadku odwołań do metod z powiązanymi instancjami lub metod z arancją większą niż jeden, wyrażenie lambda może być łatwiejsze do zrozumienia, a zatem preferowane. Zwłaszcza jeśli zachowanie metody nie jest jasne z kontekstu.
- Typy parametrów należy pominąć, chyba że poprawią czytelność.
- Jeśli wyrażenie lambda rozciąga się na więcej niż kilka wierszy, rozważ utworzenie metody.
Nadmiarowe nawiasy
return flag ? "yes" : "no";
String cmp = (flag1 != flag2) ? "not equal" : "equal";
// Don't do this
return (flag ? "yes" : "no");
- Nadmiarowe grupowanie nawiasów (tj. Nawiasów, które nie wpływają na ocenę) można zastosować, jeśli poprawią one czytelność.
- Nadmiarowe nawiasy grupujące powinny być zwykle pomijane w krótszych wyrażeniach obejmujących wspólne operatory, ale włączane do dłuższych wyrażeń lub wyrażeń obejmujących operatory, których pierwszeństwo i powiązanie są niejasne bez nawiasów. Wyrażenia trójskładnikowe z nietrywialnymi warunkami należą do tych ostatnich.
- Całe wyrażenie po słowie kluczowym
return
nie może być otoczone nawiasami.
Literały
long l = 5432L;
int i = 0x123 + 0xABC;
byte b = 0b1010;
float f1 = 1 / 5432f;
float f2 = 0.123e4f;
double d1 = 1 / 5432d; // or 1 / 5432.0
double d2 = 0x1.3p2;
-
long
literały powinny zawierać sufikslong
literyL
- Literały szesnastkowe powinny używać wielkich liter
A
-F
- Wszystkie inne przedrostki numeryczne, przyrostki i przyrostki powinny zawierać małe litery.
Aparat ortodontyczny
class Example {
void method(boolean error) {
if (error) {
Log.error("Error occurred!");
System.out.println("Error!");
} else { // Use braces since the other block uses braces.
System.out.println("No error");
}
}
}
Nawiasy otwierające powinny być umieszczone na końcu bieżącej linii, a nie na linii samodzielnie.
Powinna być nowa linia przed zamykającą klamrą, chyba że blok jest pusty (patrz krótkie formularze poniżej)
Nawiasy klamrowe są zalecane, nawet jeśli język czyni je opcjonalnymi, na przykład jednowierszowe elementy if i loop.
- Jeśli blok obejmuje więcej niż jedną linię (łącznie z komentarzami), musi mieć nawiasy klamrowe.
- Jeśli jeden z bloków instrukcji
if
/else
ma nawiasy klamrowe, drugi blok również musi. - Jeśli blok znajduje się na końcu w bloku otaczającym, musi mieć nawiasy klamrowe.
else
kluczoweelse
,catch
iwhile
indo…while
pętledo…while
idą w tym samym wierszu co nawias zamykający poprzedniego bloku.
Krótkie formy
enum Response { YES, NO, MAYBE }
public boolean isReference() { return true; }
Powyższe zalecenia mają na celu poprawę jednolitości (a tym samym zwiększenie znajomości / czytelności). W niektórych przypadkach „krótkie formularze”, które odbiegają od powyższych wytycznych, są tak samo czytelne i mogą być używane zamiast tego. Przypadki te obejmują na przykład proste deklaracje wyliczeniowe i trywialne metody oraz wyrażenia lambda.