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 nie java.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 i V dla kluczy i wartości w mapach lub R dla typu zwracanego przez funkcję), użyj tego, w przeciwnym razie użyj T
  • 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 jak package-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:

  1. Pola (w kolejności publicznej, chronionej i prywatnej)
  2. Konstruktory
  3. Metody fabryczne
  4. 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
  • Modyfikatory nie powinny być zapisywane, gdy są niejawne. Na przykład metody interfejsu nie powinny być deklarowane jako public ani abstract , 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ć sufiks long litery L
  • 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 kluczowe else , catch i while in do…while pętle do…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.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow