Java Language
Confronto C ++
Ricerca…
introduzione
Java e C ++ sono lingue simili. Questo argomento funge da guida di riferimento rapido per gli ingegneri Java e C ++.
Osservazioni
Classi definite all'interno di altri costrutti #
Definito all'interno di un'altra classe
C ++
Classe annidata [ref] (richiede un riferimento per includere la classe)
class Outer {
class Inner {
public:
Inner(Outer* o) :outer(o) {}
private:
Outer* outer;
};
};
Giava
[non statico] Classe annidata (alias anche Inner Class o Member Class)
class OuterClass {
...
class InnerClass {
...
}
}
Definito staticamente in un'altra classe
C ++
Classe annidata statica
class Outer {
class Inner {
...
};
};
Giava
Classe annidata statica (aka Classe membro statico) [ref]
class OuterClass {
...
static class StaticNestedClass {
...
}
}
Definito all'interno di un metodo
(es. gestione degli eventi)
C ++
Classe locale [ref]
void fun() {
class Test {
/* members of Test class */
};
}
Vedi anche espressioni Lambda
Giava
Classe locale [ref]
class Test {
void f() {
new Thread(new Runnable() {
public void run() {
doSomethingBackgroundish();
}
}).start();
}
}
Override vs Sovraccarico
I seguenti punti Overriding e Overloading si applicano sia a C ++ che a Java:
- Un metodo sottoposto a override ha lo stesso nome e gli stessi argomenti del suo metodo base.
- Un metodo sovraccarico ha lo stesso nome ma argomenti diversi e non si basa sull'ereditarietà.
- Due metodi con lo stesso nome e argomenti ma tipi di ritorno diversi sono illegali. Vedi le domande relative a StackOverflow relative a "overloading con diverso tipo di ritorno in Java" - Domanda 1 ; Domanda 2
Polimorfismo
Il polimorfismo è la capacità di oggetti di classi diverse legate dall'ereditarietà di rispondere in modo diverso alla stessa chiamata di metodo. Ecco un esempio:
- classe base Forma con area come metodo astratto
- due classi derivate, Square e Circle, implementano i metodi dell'area
- Forma i punti di riferimento su Square e l'area viene invocata
In C ++, il polimorfismo è abilitato con metodi virtuali. In Java, i metodi sono virtuali per impostazione predefinita.
Ordine di costruzione / distruzione
Pulizia degli oggetti
In C ++, è una buona idea dichiarare un distruttore come virtuale per garantire che il distruttore della sottoclasse venga chiamato se il puntatore della classe base viene cancellato.
In Java, un metodo finalizzato è simile a un distruttore in C ++; tuttavia, i finalizzatori sono imprevedibili (si basano su GC). Best practice: utilizzare un metodo "close" per eseguire una pulizia esplicita.
protected void close() {
try {
// do subclass cleanup
}
finally {
isClosed = true;
super.close();
}
}
protected void finalize() {
try {
if(!isClosed) close();
}
finally {
super.finalize();
}
}
Metodi e classi astratte
Concetto | C ++ | Giava |
---|---|---|
Metodo astratto dichiarato senza implementazione | metodo virtuale puro virtual void eat(void) = 0; | metodo astratto abstract void draw(); |
Classe astratta non può essere istanziato | non può essere istanziato; ha almeno un metodo virtuale puro class AB {public: virtual void f() = 0;}; | non può essere istanziato; può avere metodi non astratti abstract class GraphicObject {} |
Interfaccia nessun campo istanza | nessuna parola chiave "interfaccia", ma può simulare un'interfaccia Java con funzioni di una classe astratta | molto simile alla classe astratta, ma 1) supporta l'ereditarietà multipla; 2) nessun campo di istanza interface TestInterface {} |
Modificatori di accessibilità
Modificatore | C ++ | Giava |
---|---|---|
Pubblico - accessibile a tutti | senza note speciali | senza note speciali |
Protetto - accessibile da sottoclassi | accessibile anche dagli amici | accessibile anche all'interno dello stesso pacchetto |
Privato - accessibile dai membri | accessibile anche dagli amici | senza note speciali |
predefinito | l'impostazione predefinita della classe è privata; struct default è public | accessibile da tutte le classi all'interno dello stesso pacchetto |
altro | Amico: un modo per concedere l'accesso a membri privati e protetti senza ereditarietà (vedi sotto) |
Esempio di amico C ++
class Node {
private:
int key; Node *next;
// LinkedList::search() can access "key" & "next"
friend int LinkedList::search();
};
Il temuto problema del diamante
Il problema dei diamanti è un'ambiguità che sorge quando due classi B e C ereditano da A, e la classe D eredita sia da B che da C. Se c'è un metodo in A che B e C hanno scavalcato, e D non lo sovrascrive, quindi quale versione del metodo eredita D: quella di B, o quella di C? (da Wikipedia )
Sebbene C ++ sia sempre stato sensibile al problema dei diamanti, Java era suscettibile fino a Java 8. Originariamente, Java non supportava l'ereditarietà multipla, ma con l'avvento dei metodi di interfaccia predefiniti, le classi Java non possono ereditare "implementazione" da più di una classe .
java.lang.Object Class
In Java tutte le classi ereditano, in modo implicito o esplicito, dalla classe Object. Qualsiasi riferimento Java può essere convertito nel tipo Object.
C ++ non ha una classe "Object" comparabile.
Collezioni Java e contenitori C ++
Le raccolte Java sono sinonimi dei contenitori C ++.
Diagramma di flusso delle raccolte Java
Diagramma di flusso dei contenitori C ++
Tipi interi
bits | min | Max | Tipo C ++ (su LLP64 o LP64) | Tipo Java |
---|---|---|---|---|
8 | -2 (8-1) = -128 | 2 (8-1) -1 = 127 | carbonizzare | byte |
8 | 0 | 2 (8) -1 = 255 | char unsigned | - |
16 | -2 (16-1) = -32.768 | 2 (16-1) -1 = 32.767 | corto | corto |
16 | 0 (\ u0000) | 2 (16) -1 = 65.535 (\ uFFFF) | corto senza firma | char (non firmato) |
32 | -2 (32-1) = -2.147 miliardi | 2 (32-1) -1 = 2,147 miliardi | int | int |
32 | 0 | 2 (32) -1 = 4,295 miliardi | int non firmato | - |
64 | -2 (64-1) | 2 (16-1) -1 | lungo* | lungo lungo |
64 | 0 | 2 (16) -1 | lungo non firmato * non firmato lungo | - |
*
L'API Win64 è solo a 32 bit
Membri della classe statica
I membri statici hanno un ambito di classe rispetto all'ambito dell'oggetto
Esempio di C ++
// define in header
class Singleton {
public:
static Singleton *getInstance();
private:
Singleton() {}
static Singleton *instance;
};
// initialize in .cpp
Singleton* Singleton::instance = 0;
Esempio di Java
public class Singleton {
private static Singleton instance;
private Singleton() {}
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}
Classi definite all'interno di altri costrutti
Definito all'interno di un'altra classe
C ++
Classe annidata [ref] (richiede un riferimento per includere la classe)
class Outer {
class Inner {
public:
Inner(Outer* o) :outer(o) {}
private:
Outer* outer;
};
};
Giava
[non statico] Classe annidata (alias anche Inner Class o Member Class)
class OuterClass {
...
class InnerClass {
...
}
}
Definito staticamente in un'altra classe
C ++
Classe annidata statica
class Outer {
class Inner {
...
};
};
Giava
Classe annidata statica (aka Classe membro statico) [ref]
class OuterClass {
...
static class StaticNestedClass {
...
}
}
Definito all'interno di un metodo
(es. gestione degli eventi)
C ++
Classe locale [ref]
void fun() {
class Test {
/* members of Test class */
};
}
Giava
Classe locale [ref]
class Test {
void f() {
new Thread(new Runnable() {
public void run() {
doSomethingBackgroundish();
}
}).start();
}
}
Pass-by-value e Pass-by-riferimento
Molti sostengono che Java sia SOLO un valore pass-by, ma è più sfumato di così. Confrontate i seguenti esempi C ++ e Java per vedere i molti sapori del pass-by-value (ovvero la copia) e il pass-by-reference (alias alias).
Esempio C ++ (codice completo)
// 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;
}
Esempio Java (codice completo)
// 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);
}
Ereditarietà rispetto alla composizione
C ++ e Java sono entrambi linguaggi orientati agli oggetti, quindi il seguente diagramma si applica a entrambi.
Downcasting dell'outcast
Attenzione all'utilizzo di "downcasting" - Downcasting sta gettando giù la gerarchia dell'eredità da una classe base a una sottoclasse (cioè opposta al polimorfismo). In generale, usa il polimorfismo e l'override invece di instanceof & downcasting.
Esempio di C ++
// explicit type case required
Child *pChild = (Child *) &parent;
Esempio di Java
if(mySubClass instanceof SubClass) {
SubClass mySubClass = (SubClass)someBaseClass;
mySubClass.nonInheritedMethod();
}
Metodi e classi astratte
Metodo astratto
dichiarato senza implementazione
C ++
metodo virtuale puro
virtual void eat(void) = 0;
Giava
metodo astratto
abstract void draw();
Classe astratta
non può essere istanziato
C ++
non può essere istanziato; ha almeno un metodo virtuale puro
class AB {public: virtual void f() = 0;};
Giava
non può essere istanziato; può avere metodi non astratti
abstract class GraphicObject {}
Interfaccia
nessun campo istanza
C ++
niente paragonabile a Java
Giava
molto simile alla classe astratta, ma 1) supporta l'ereditarietà multipla; 2) nessun campo di istanza
interface TestInterface {}