Java Language
Porównanie C ++
Szukaj…
Wprowadzenie
Java i C ++ są podobnymi językami. Ten temat służy jako szybki przewodnik dla inżynierów Java i C ++.
Uwagi
Klasy zdefiniowane w innych konstrukcjach #
Zdefiniowany w innej klasie
C ++
Klasa zagnieżdżona [ref] (wymaga odniesienia do otaczającej klasy)
class Outer {
class Inner {
public:
Inner(Outer* o) :outer(o) {}
private:
Outer* outer;
};
};
Jawa
[niestatyczna] Klasa zagnieżdżona (znana również jako klasa wewnętrzna lub klasa członka)
class OuterClass {
...
class InnerClass {
...
}
}
Zdefiniowane statycznie w innej klasie
C ++
Statycznie zagnieżdżona klasa
class Outer {
class Inner {
...
};
};
Jawa
Static Nested Class (vel Static Member Class) [ref]
class OuterClass {
...
static class StaticNestedClass {
...
}
}
Zdefiniowane w ramach metody
(np. obsługa zdarzeń)
C ++
Klasa lokalna [ref]
void fun() {
class Test {
/* members of Test class */
};
}
Zobacz także wyrażenia Lambda
Jawa
Klasa lokalna [ref]
class Test {
void f() {
new Thread(new Runnable() {
public void run() {
doSomethingBackgroundish();
}
}).start();
}
}
Przesłonięcie a przeciążenie
Następujące punkty zastąpienia i przeciążenia dotyczą zarówno C ++, jak i Java:
- Przesłonięta metoda ma taką samą nazwę i argumenty jak metoda podstawowa.
- Przeciążona metoda ma tę samą nazwę, ale różne argumenty i nie polega na dziedziczeniu.
- Dwie metody o tej samej nazwie i argumentach, ale o innym typie zwrotu są nielegalne. Zobacz podobne pytania Stackoverflow dotyczące „przeciążenia innym rodzajem zwrotu w Javie” - Pytanie 1 ; pytanie 2
Wielopostaciowość
Polimorfizm to zdolność obiektów różnych klas powiązanych przez dziedziczenie do różnej reakcji na to samo wywołanie metody. Oto przykład:
- klasa podstawowa Kształt z obszarem jako metoda abstrakcyjna
- dwie klasy pochodne, Kwadrat i Okrąg, wdrażają metody obszarowe
- Odwołaj się do punktów odniesienia kształtu do kwadratu i obszaru
W C ++ polimorfizm jest włączany metodami wirtualnymi. W Javie metody są domyślnie wirtualne.
Porządek budowy / zniszczenia
Oczyszczanie obiektów
W C ++ dobrym pomysłem jest deklarowanie destruktora jako wirtualnego, aby mieć pewność, że wywołanie destruktora podklasy zostanie wywołane, jeśli wskaźnik klasy podstawowej zostanie usunięty.
W Javie metoda finalizacji jest podobna do destruktora w C ++; jednak finalizatory są nieprzewidywalne (polegają na GC). Najlepsza praktyka - użyj metody „close”, aby jawnie oczyścić.
protected void close() {
try {
// do subclass cleanup
}
finally {
isClosed = true;
super.close();
}
}
protected void finalize() {
try {
if(!isClosed) close();
}
finally {
super.finalize();
}
}
Metody i klasy abstrakcyjne
Pojęcie | C ++ | Jawa |
---|---|---|
Metoda abstrakcyjna zadeklarowane bez implementacji | czysta wirtualna metoda virtual void eat(void) = 0; | metoda abstrakcyjna abstract void draw(); |
Klasa abstrakcyjna nie można utworzyć instancji | nie można utworzyć instancji; ma co najmniej 1 czystą wirtualną metodę class AB {public: virtual void f() = 0;}; | nie można utworzyć instancji; może mieć metody nieabstrakcyjne abstract class GraphicObject {} |
Berło brak pól instancji | brak słowa kluczowego „interfejs”, ale może naśladować interfejs Java z udogodnieniami klasy abstrakcyjnej | bardzo podobny do klasy abstrakcyjnej, ale 1) obsługuje wielokrotne dziedziczenie; 2) brak pól instancji interface TestInterface {} |
Modyfikatory dostępności
Modyfikator | C ++ | Jawa |
---|---|---|
Publiczny - dostępny dla wszystkich | bez specjalnych notatek | bez specjalnych notatek |
Chroniony - dostępny przez podklasy | dostępne również dla znajomych | dostępne również w ramach tego samego pakietu |
Prywatny - dostępny dla członków | dostępne również dla znajomych | bez specjalnych notatek |
domyślna | domyślna klasa jest prywatna; Struktura domyślna to public | dostępne dla wszystkich klas w tym samym pakiecie |
inny | Przyjaciel - sposób na udzielenie dostępu prywatnym i chronionym członkom bez dziedziczenia (patrz poniżej) |
Przykład znajomego w C ++
class Node {
private:
int key; Node *next;
// LinkedList::search() can access "key" & "next"
friend int LinkedList::search();
};
Problem z przerażającym diamentem
Problemem z diamentami jest dwuznaczność, która powstaje, gdy dwie klasy B i C dziedziczą po A, a klasa D dziedziczy zarówno po B, jak i C. Jeśli istnieje metoda w A, którą B i C zastąpiły, a D jej nie zastąpi, to która wersja metody dziedziczy D: wersja B lub C? (z Wikipedii )
Podczas gdy C ++ zawsze był podatny na problem z diamentem, Java była wrażliwa aż do Java 8. Pierwotnie Java nie obsługiwała wielokrotnego dziedziczenia, ale wraz z pojawieniem się domyślnych metod interfejsu klasy Java nie mogą dziedziczyć „implementacji” z więcej niż jednej klasy .
java.lang.Object Klasa
W Javie wszystkie klasy dziedziczą, pośrednio lub jawnie, od klasy Object. Każde odwołanie Java może być rzutowane na typ obiektu.
C ++ nie ma porównywalnej klasy „Object”.
Kolekcje Java i kontenery C ++
Kolekcje Java są tożsame z kontenerami C ++.
Schemat blokowy kolekcji Java
Schemat blokowy kontenerów C ++
Typy całkowite
Bity | Min | Max | Typ C ++ (na LLP64 lub LP64) | Typ Java |
---|---|---|---|---|
8 | -2 (8-1) = -128 | 2 (8-1) -1 = 127 | zwęglać | bajt |
8 | 0 | 2 (8) -1 = 255 | niepodpisany char | - |
16 | -2 (16-1) = -32 768 | 2 (16-1) -1 = 32 767 | krótki | krótki |
16 | 0 (\ u0000) | 2 (16) -1 = 65 535 (\ uFFFF) | bez znaku krótkie | char (niepodpisany) |
32 | -2 (32-1) = -2,147 miliarda | 2 (32-1) -1 = 2,147 miliarda | int | int |
32 | 0 | 2 (32) -1 = 4,295 miliarda | unsigned int | - |
64 | -2 (64-1) | 2 (16-1) -1 | długo* | długo długo |
64 | 0 | 2 (16) -1 | bez znaku długi * długo bez znaku | - |
*
Interfejs API Win64 jest tylko 32-bitowy
Członkowie klasy statycznej
Elementy statyczne mają zakres klasy w przeciwieństwie do zakresu obiektu
Przykład C ++
// define in header
class Singleton {
public:
static Singleton *getInstance();
private:
Singleton() {}
static Singleton *instance;
};
// initialize in .cpp
Singleton* Singleton::instance = 0;
Przykład Java
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
Klasy zdefiniowane w innych konstrukcjach
Zdefiniowany w innej klasie
C ++
Klasa zagnieżdżona [ref] (wymaga odniesienia do otaczającej klasy)
class Outer {
class Inner {
public:
Inner(Outer* o) :outer(o) {}
private:
Outer* outer;
};
};
Jawa
[niestatyczna] Klasa zagnieżdżona (znana również jako klasa wewnętrzna lub klasa członka)
class OuterClass {
...
class InnerClass {
...
}
}
Zdefiniowane statycznie w innej klasie
C ++
Statycznie zagnieżdżona klasa
class Outer {
class Inner {
...
};
};
Jawa
Static Nested Class (vel Static Member Class) [ref]
class OuterClass {
...
static class StaticNestedClass {
...
}
}
Zdefiniowane w ramach metody
(np. obsługa zdarzeń)
C ++
Klasa lokalna [ref]
void fun() {
class Test {
/* members of Test class */
};
}
Jawa
Klasa lokalna [ref]
class Test {
void f() {
new Thread(new Runnable() {
public void run() {
doSomethingBackgroundish();
}
}).start();
}
}
Przekazywanie według wartości i przekazywanie przez odniesienie
Wielu twierdzi, że Java jest TYLKO przekazywana według wartości, ale jest bardziej dopracowana. Porównaj następujące przykłady C ++ i Java, aby zobaczyć wiele wariantów przekazywania wartości (aka kopiowanie) i przekazywania według referencji (alias).
Przykład C ++ (pełny kod)
// passes a COPY of the object
static void passByCopy(PassIt obj) {
obj.i = 22; // only a "local" change
}
// passes a pointer
static void passByPointer(PassIt* ptr) {
ptr->i = 33;
ptr = 0; // better to use nullptr instead if '0'
}
// passes an alias (aka reference)
static void passByAlias(PassIt& ref) {
ref.i = 44;
}
// This is an old-school way of doing it.
// Check out std::swap for the best way to do this
static void swap(PassIt** pptr1, PassIt** pptr2) {
PassIt* tmp = *pptr1;
*pptr1 = *pptr2;
*pptr2 = tmp;
}
Przykład Java (pełny kod)
// passes a copy of the variable
// NOTE: in java only primitives are pass-by-copy
public static void passByCopy(int copy) {
copy = 33; // only a "local" change
}
// No such thing as pointers in Java
/*
public static void passByPointer(PassIt *ptr) {
ptr->i = 33;
ptr = 0; // better to use nullptr instead if '0'
}
*/
// passes an alias (aka reference)
public static void passByAlias(PassIt ref) {
ref.i = 44;
}
// passes aliases (aka references),
// but need to do "manual", potentially expensive copies
public static void swap(PassIt ref1, PassIt ref2) {
PassIt tmp = new PassIt(ref1);
ref1.copy(ref2);
ref2.copy(tmp);
}
Dziedziczenie a kompozycja
C ++ i Java są językami obiektowymi, dlatego poniższy schemat stosuje się do obu.
Outcasting Downcasting
Uwaga na używanie „downcastingu” - downcasting obniża hierarchię dziedziczenia z klasy podstawowej do podklasy (tj. Przeciwieństwo polimorfizmu). Zasadniczo używaj polimorfizmu i przesłonięcia zamiast instanceof i downcastingu.
Przykład C ++
// explicit type case required
Child *pChild = (Child *) &parent;
Przykład Java
if(mySubClass instanceof SubClass) {
SubClass mySubClass = (SubClass)someBaseClass;
mySubClass.nonInheritedMethod();
}
Metody i klasy abstrakcyjne
Metoda abstrakcyjna
zadeklarowane bez implementacji
C ++
czysta wirtualna metoda
virtual void eat(void) = 0;
Jawa
metoda abstrakcyjna
abstract void draw();
Klasa abstrakcyjna
nie można utworzyć instancji
C ++
nie można utworzyć instancji; ma co najmniej 1 czystą wirtualną metodę
class AB {public: virtual void f() = 0;};
Jawa
nie można utworzyć instancji; może mieć metody nieabstrakcyjne
abstract class GraphicObject {}
Berło
brak pól instancji
C ++
nic porównywalnego z Javą
Jawa
bardzo podobny do klasy abstrakcyjnej, ale 1) obsługuje wielokrotne dziedziczenie; 2) brak pól instancji
interface TestInterface {}