Heim  >  Artikel  >  Java  >  Was ist der Unterschied zwischen Java und C++?

Was ist der Unterschied zwischen Java und C++?

黄舟
黄舟Original
2017-02-06 11:49:111129Durchsuche

Als C++-Programmierer beherrschen wir bereits die Grundkonzepte der objektorientierten Programmierung und die Syntax von Java ist uns zweifellos sehr vertraut. Tatsächlich ist Java ursprünglich von C++ abgeleitet.

Es gibt jedoch immer noch einige wesentliche Unterschiede zwischen C++ und Java. Es genügt zu sagen, dass diese Unterschiede große Fortschritte in der Technologie darstellen. Sobald wir diese Unterschiede verstehen, werden wir verstehen, warum Java eine hervorragende Programmiersprache ist. Dieser Anhang führt Sie durch einige wichtige Merkmale, die Java von C++ unterscheiden.


 (1) Das größte Hindernis ist die Geschwindigkeit: Interpretiertes Java ist etwa 20-mal langsamer als die Ausführungsgeschwindigkeit von C. Nichts kann die Kompilierung der Java-Sprache verhindern. Während ich dies schreibe, sind einige nahezu Echtzeit-Compiler auf den Markt gekommen, die die Arbeit erheblich beschleunigen können. Natürlich gibt es allen Grund zu der Annahme, dass es reine native Compiler für populärere Plattformen geben wird, aber ohne diese Compiler muss es einige Probleme geben, die Java aufgrund von Geschwindigkeitsbeschränkungen nicht lösen kann.


 (2). Wie C++ bietet auch Java zwei Arten von Kommentaren.


  (3) Alles muss in eine Klasse eingeordnet werden. Es gibt keine globalen Funktionen oder globalen Daten. Wenn Sie äquivalente Funktionen zu globalen Funktionen erhalten möchten, sollten Sie erwägen, statische Methoden und statische Daten in einer Klasse zu platzieren. Beachten Sie, dass es keine Strukturen, Aufzählungen oder Unions gibt, sondern nur „Klassen“!


  (4) Alle Methoden werden im Hauptteil der Klasse definiert. Aus C++-Sicht scheint es also, dass alle Funktionen eingebettet wurden, aber das ist nicht der Fall (Einbettungsprobleme werden später besprochen).


  (5) In Java haben Klassendefinitionen fast die gleiche Form wie in C++. Es gibt jedoch kein abschließendes Semikolon. Es gibt keine Klassendeklaration der Form class foo, sondern nur eine Klassendefinition.
 

class aType()
  void aMethod() {/* 方法主体*/}
  }


 (6) In Java gibt es keinen Bereichsoperator „::“. Java verwendet für alles die Punktnotation, aber Sie müssen nicht darüber nachdenken, da Sie nur Elemente in einer Klasse definieren können. Selbst diese Methodendefinitionen müssen sich innerhalb einer Klasse befinden, sodass der Geltungsbereich nicht angegeben werden muss. Ein Unterschied, der uns aufgefallen ist, ist der Aufruf statischer Methoden: Verwendung von ClassName.methodName(). Darüber hinaus wird der Name des Pakets (Pakets) mit einem Punkt festgelegt, und das Schlüsselwort import kann verwendet werden, um einen Teil der Funktion „#include“ von C++ zu implementieren. Zum Beispiel die folgende Anweisung:
Import java.awt.*;
(#include ist nicht direkt dem Import zugeordnet, hat aber bei Verwendung ein ähnliches Gefühl.)


( 7) Ähnlich wie C++ enthält Java eine Reihe „primitiver Typen“, um einen effizienteren Zugriff zu erreichen. In Java umfassen diese Typen boolean, char, byte, short, int, long, float und double. Die Größen aller Haupttypen sind intrinsisch und maschinenunabhängig (um Portierungsproblemen Rechnung zu tragen). Dies wird sich je nach Maschine definitiv auf die Leistung auswirken. Typprüfung und Anforderungen sind in Java strenger geworden. Beispiel:

Bedingte Ausdrücke können nur vom Typ boolean sein und ganze Zahlen können nicht verwendet werden.

Muss das Ergebnis eines Ausdrucks wie X+Y verwenden; man kann nicht einfach „X+Y“ verwenden, um „Nebenwirkungen“ zu erzielen.


(8) Der Typ char (Zeichen) verwendet den international akzeptierten 16-Bit-Unicode-Zeichensatz, sodass Zeichen aus den meisten Ländern automatisch ausgedrückt werden können.
(9) Statische Referenzzeichenfolgen werden automatisch in String-Objekte umgewandelt. Im Gegensatz zu C und C++ sind keine unabhängigen statischen Array-Zeichenfolgen verfügbar.
(10) Java fügt drei Rechtsverschiebungsoperatoren „>>>“ hinzu, die ähnliche Funktionen wie die „logischen“ Rechtsverschiebungsoperatoren haben und am Ende Nullwerte einfügen können. „>>“ fügt das Vorzeichenbit beim Verschieben ein (d. h. „arithmetische“ Verschiebung).
(11) Obwohl Java-Arrays oberflächlich betrachtet ähnlich sind, verwenden sie im Vergleich zu C++ eine ganz andere Struktur und weisen ein einzigartiges Verhalten auf. Es gibt ein schreibgeschütztes Längenelement, das Ihnen mitteilt, wie groß das Array ist. Und sobald die Array-Grenze überschritten wird, löst die Laufzeitprüfung automatisch eine Ausnahme aus. Alle Arrays werden im Speicher-„Heap“ erstellt und wir können ein Array einem anderen zuweisen (durch einfaches Kopieren des Array-Handles). Array-Bezeichner sind Objekte der ersten Ebene und alle ihre Methoden gelten im Allgemeinen für alle anderen Objekte.
(12) Alle Objekte, die nicht zum Haupttyp gehören, können nur über den neuen Befehl erstellt werden. Im Gegensatz zu C++ gibt es in Java keinen entsprechenden Befehl zum Erstellen von Objekten, die nicht vom Haupttyp „auf dem Stapel“ sind. Alle Haupttypen können nur auf dem Stapel erstellt werden, ohne den neuen Befehl zu verwenden. Alle Hauptklassen haben ihre eigenen „Wrapper“-Klassen, sodass äquivalente Speicher-„Heap“-basierte Objekte über „new“ erstellt werden können (eine Ausnahme bilden Haupttyp-Arrays: Sie können über Sammlungen wie in C++ „assign“ initialisiert oder „new“ verwendet werden).


(13) In Java ist keine Voranmeldung erforderlich. Wenn Sie eine Klasse oder Methode verwenden möchten, bevor Sie sie definieren, verwenden Sie sie einfach direkt – der Compiler stellt sicher, dass die entsprechende Definition verwendet wird. Anders als in C++ stoßen wir also nicht auf Probleme mit frühen Referenzen.


(14) Java hat keinen Präprozessor. Wenn Sie eine Klasse in einer anderen Bibliothek verwenden möchten, verwenden Sie einfach den Importbefehl und geben Sie den Bibliotheksnamen an. Es gibt kein präprozessorähnliches Makro.


(15) Java verwendet Pakete anstelle von Namespaces. Da alles in eine Klasse eingeordnet wird und dank eines Mechanismus namens „Kapselung“, der so etwas wie eine Namespace-Zerlegung für Klassennamen durchführt, sind Namensprobleme kein Problem mehr. Das Paket sammelt außerdem Bibliothekskomponenten unter einem einzigen Bibliotheksnamen. Wir „importieren“ einfach ein Paket und der Compiler erledigt den Rest.


(16) Als Klassenmitglieder definierte Objekthandles werden automatisch auf Null initialisiert. Die Initialisierung grundlegender Klassendatenelemente ist in Java zuverlässig garantiert. Wenn sie nicht explizit initialisiert werden, erhalten sie einen Standardwert (Null oder gleichwertig). Sie können explizit initialisiert werden (explizite Initialisierung): entweder durch Definition innerhalb der Klasse oder im Builder. Die verwendete Syntax ist einfacher zu verstehen als die Syntax von C++ und ist sowohl für statische als auch für nicht statische Elemente festgelegt. Wir müssen die Speichermethode statischer Mitglieder nicht von außen definieren, was sich von C++ unterscheidet.


(17) In Java gibt es keine Zeiger wie C und C++. Wenn Sie mit new ein Objekt erstellen, erhalten Sie eine Referenz (in diesem Buch wird es immer als „Handle“ bezeichnet). Zum Beispiel:
String s = new String("howdy");
C++-Referenzen müssen jedoch beim Erstellen initialisiert werden und können nicht an einem anderen Ort neu definiert werden. Aber Java-Referenzen sind nicht unbedingt auf den Ort beschränkt, an dem sie erstellt werden. Sie können je nach Situation beliebig definiert werden, wodurch ein Teil der Notwendigkeit von Zeigern entfällt. Ein weiterer Grund für die starke Verwendung von Zeigern in C und C++ besteht darin, auf beliebige Speicherorte zeigen zu können (dies macht sie auch unsicher, weshalb Java diese Unterstützung nicht bietet). Zeiger werden oft als effizientes Mittel zur Bewegung in einem Array primitiver Variablen angesehen. Mit Java können wir dasselbe Ziel auf sicherere Weise erreichen. Die ultimative Lösung für Zeigerprobleme ist die „inhärente Methode“ (siehe Anhang A). Die Übergabe eines Zeigers an eine Methode stellt normalerweise kein großes Problem dar, da es keine globalen Funktionen, sondern nur Klassen gibt. Und wir können einen Verweis auf das Objekt übergeben. Die Java-Sprache behauptete zunächst, dass sie „überhaupt keine Zeiger verwendet!“ Doch viele Programmierer begannen sich zu fragen: Wie kann sie ohne Zeiger funktionieren? Daher wurde später erklärt, dass „eingeschränkte Zeiger verwendet werden sollten“. Es ist ein Hinweis, anhand dessen Sie selbst beurteilen können, ob es „wahr“ ist oder nicht. Aber auf jeden Fall gibt es keinen Zeiger „Arithmetik“.


(18) Java bietet einen „Konstruktor“ ähnlich wie C++. Wenn Sie selbst keinen definieren, erhalten Sie einen Standard-Builder. Und wenn ein nicht standardmäßiger Builder definiert ist, wird der Standard-Builder nicht automatisch für uns definiert. Dies ist dasselbe wie C++. Beachten Sie, dass es keinen Copy Builder gibt, da alle Argumente als Referenz übergeben werden.


(19) In Java gibt es keinen „Destruktor“. Bei Variablen gibt es kein „Umfangs“-Problem. Die „Lebensdauer“ eines Objekts wird durch das Alter des Objekts bestimmt, nicht durch den Garbage Collector. Es gibt eine finalize()-Methode, die Mitglied jeder Klasse ist und dem C++-„Destruktor“ etwas ähnelt. Aber finalize() wird vom Garbage Collector aufgerufen und ist nur für die Freigabe von „Ressourcen“ (wie offene Dateien, Sockets, Ports, URLs usw.) verantwortlich. Wenn Sie an einem bestimmten Ort etwas tun möchten, müssen Sie eine spezielle Methode erstellen und diese aufrufen. Sie können sich nicht auf finalize() verlassen. Andererseits werden (oder „sollten“) alle Objekte in C++ zerstört, aber nicht alle Objekte in Java werden als „Müll“ gesammelt. Da Java das Konzept eines Zerstörers nicht unterstützt, muss bei Bedarf darauf geachtet werden, eine Bereinigungsmethode zu erstellen. Darüber hinaus müssen alle Bereinigungsmethoden explizit für die Basisklassen und Mitgliedsobjekte innerhalb der Klasse aufgerufen werden.


(20) Java verfügt über einen Mechanismus zum „Überladen“ von Methoden, der fast genauso funktioniert wie das Überladen von C++-Funktionen.


(21) Java unterstützt keine Standardargumente.


(22) In Java gibt es kein Goto. Der bedingungslose Sprungmechanismus, den es verwendet, ist das „Break Label“ oder „Continue Standard“, mit dem aus den aktuellen mehreren verschachtelten Schleifen herausgesprungen wird.


(23) Java verwendet eine hierarchische Struktur mit einer Wurzel, sodass alle Objekte einheitlich von der Wurzelklasse Object geerbt werden. In C++ können wir überall einen neuen Vererbungsbaum beginnen, sodass wir am Ende oft einen „Wald“ sehen, der eine große Anzahl von Bäumen enthält. In Java haben wir ohnehin nur eine hierarchische Struktur. Obwohl dies oberflächlich betrachtet wie eine Einschränkung erscheinen mag, werden oft leistungsfähigere Fähigkeiten gewonnen, da wir wissen, dass jedes Objekt mindestens eine Objektschnittstelle haben muss. C++ scheint derzeit die einzige OO-Sprache zu sein, die keine einzelne Root-Struktur erzwingt.


(24) Java verfügt nicht über Vorlagen oder andere Formen parametrisierter Typen. Es bietet eine Reihe von Sammlungen: Vector (Vektor), Stack (Stapel) und Hashtable (Hash-Tabelle), die zur Aufnahme von Objektreferenzen verwendet werden. Mit diesen Kollektionen können wir eine Reihe unserer Anforderungen erfüllen. Diese Sammlungen sind jedoch nicht darauf ausgelegt, schnell aufgerufen zu werden, wie die „Standard Template Library“ (STL) von C++. Die neuen Sammlungen in Java 1.2 erscheinen vollständiger, verfügen jedoch immer noch nicht über die effiziente Nutzung authentischer Vorlagen.


(25) „Garbage Collection“ bedeutet, dass Speicherlecks in Java viel weniger wahrscheinlich, aber nicht völlig unmöglich sind (wenn Sie eine inhärente Methode zum Zuweisen von Speicherplatz aufrufen, kann der Garbage Collector nicht nachverfolgen und überwachen Es). Speicherlecks und Ressourcenlecks werden jedoch häufig durch falsch geschriebenes finalize() oder durch die Freigabe einer Ressource am Ende eines zugewiesenen Blocks verursacht („Destruktoren“ sind derzeit besonders praktisch). Der Garbage Collector ist eine große Weiterentwicklung auf Basis von C++, die viele Programmierprobleme unsichtbar macht. Für einige Probleme, bei denen der Müllsammler nicht in der Lage ist, damit umzugehen, ist es jedoch nicht geeignet. Doch die zahlreichen Vorteile des Garbage Collectors lassen dieses Manko trivial erscheinen.


(26) Java verfügt über integrierte Unterstützung für Multithreading. Mithilfe einer speziellen Thread-Klasse können wir durch Vererbung einen neuen Thread erstellen (die Methode run() wird aufgegeben). Wenn das synchronisierte Schlüsselwort als Typqualifizierer für eine Methode verwendet wird, erfolgt ein gegenseitiger Ausschluss auf Objektebene. Zu jedem Zeitpunkt kann nur ein Thread die synchronisierte Methode eines Objekts verwenden. Andererseits „sperrt“ sie nach dem Eintritt einer synchronisierten Methode zunächst das Objekt und verhindert so, dass andere synchronisierte Methoden dieses Objekt verwenden. Erst nach Verlassen dieser Methode wird das Objekt „entsperrt“. Wir sind weiterhin für die Implementierung komplexerer Synchronisationsmechanismen zwischen Threads verantwortlich, indem wir unsere eigene „Monitor“-Klasse erstellen. Rekursive synchronisierte Methoden funktionieren einwandfrei. Wenn Threads die gleiche Priorität haben, kann eine zeitliche Aufteilung nicht garantiert werden.


(27) Anstatt den Deklarationscodeblock wie C++ zu steuern, fügen wir die Zugriffsqualifizierer (öffentlich, privat und geschützt) in die Definition jedes Klassenmitglieds ein. Wenn kein „explizites“ (eindeutiges) Qualifikationsmerkmal angegeben wird, wird standardmäßig „freundlich“ verwendet. Dies bedeutet, dass auch andere Elemente im selben Paket darauf zugreifen können (was bedeutet, dass sie C++-„Freunde“ werden), aber kein Element außerhalb des Pakets darauf zugreifen kann. Eine Klasse – und jede Methode innerhalb einer Klasse – verfügt über einen Zugriffsqualifizierer, der bestimmt, ob sie außerhalb der Datei „sichtbar“ ist. Das Schlüsselwort private wird in Java im Allgemeinen selten verwendet, da ein „freundlicher“ Zugriff normalerweise nützlicher ist, als den Zugriff anderer Klassen im selben Paket auszuschließen. In einer Multithread-Umgebung ist die ordnungsgemäße Verwendung von Private jedoch sehr wichtig. Das geschützte Schlüsselwort von Java bedeutet „zugänglich für Erben und andere Elemente im Paket“. Beachten Sie, dass Java kein Äquivalent zum geschützten Schlüsselwort von C++ hat, was bedeutet, dass „nur von Erben darauf zugegriffen werden kann“ (zuvor konnte für diesen Zweck „private protected“ verwendet werden, diese Schlüsselwortkombination wurde jedoch abgeschafft).


(28) Verschachtelte Klassen. In C++ hilft das Verschachteln von Klassen dabei, Namen zu verbergen und die Codeorganisation zu erleichtern (aber die „Namespaces“ von C++ haben das Ausblenden von Namen überflüssig gemacht). Das Java-Konzept der „Kapselung“ oder „Verpackung“ entspricht dem Namespace von C++, sodass dies kein Problem mehr darstellt. Mit Java 1.1 wurde das Konzept der „inneren Klassen“ eingeführt, die heimlich ein Handle für die äußere Klasse verwalten, das beim Erstellen innerer Klassenobjekte benötigt wird. Dies bedeutet, dass das innere Klassenobjekt möglicherweise ohne Bedingungen auf die Mitglieder des äußeren Klassenobjekts zugreifen kann – als ob diese Mitglieder dem inneren Klassenobjekt direkt untergeordnet wären. Dies bietet eine bessere Lösung für das Rückrufproblem – C++ löst es mit Zeigern auf Mitglieder.


(29) Aufgrund der Existenz der zuvor eingeführten inneren Klasse gibt es in Java keinen Zeiger auf Member.


(30) In Java gibt es keine „Inline“-Methode. Der Java-Compiler kann nach eigenem Ermessen eine Methode einbetten, wir haben jedoch keine Kontrolle mehr darüber. In Java können Sie das Schlüsselwort final für eine Methode verwenden, um eine Einbettung „vorzuschlagen“. Das Einbetten von Funktionen ist jedoch nur ein Vorschlag für C++-Compiler.


(31) Java中的继承具有与C++相同的效果,但采用的语法不同。Java用extends关键字标志从一个基础类的继承,并用super关键字指出准备在基础类中调用的方法,它与我们当前所在的方法具有相同的名字(然而,Java中的super关键字只允许我们访问父类的方法——亦即分级结构的上一级)。通过在C++中设定基础类的作用域,我们可访问位于分级结构较深处的方法。亦可用super关键字调用基础类构建器。正如早先指出的那样,所有类最终都会从Object里自动继承。和C++不同,不存在明确的构建器初始化列表。但编译器会强迫我们在构建器主体的开头进行全部的基础类初始化,而且不允许我们在主体的后面部分进行这一工作。通过组合运用自动初始化以及来自未初始化对象句柄的异常,成员的初始化可得到有效的保证。
  

public class Foo extends Bar {
   public Foo(String msg) {
   super(msg); // Calls base constructor
   }
   public baz(int i) { // Override
   super.baz(i); // Calls base method
   }
  }


(32) Java中的继承不会改变基础类成员的保护级别。我们不能在Java中指定public,private或者protected继承,这一点与C++是相同的。此外,在衍生类中的优先方法不能减少对基础类方法的访问。例如,假设一个成员在基础类中属于public,而我们用另一个方法代替了它,那么用于替换的方法也必须属于public(编译器会自动检查)。


(33) Java提供了一个interface关键字,它的作用是创建抽象基础类的一个等价物。在其中填充抽象方法,且没有数据成员。这样一来,对于仅仅设计成一个接口的东西,以及对于用extends关键字在现有功能基础上的扩展,两者之间便产生了一个明显的差异。不值得用abstract关键字产生一种类似的效果,因为我们不能创建属于那个类的一个对象。一个abstract(抽象)类可包含抽象方法(尽管并不要求在它里面包含什么东西),但它也能包含用于具体实现的代码。因此,它被限制成一个单一的继承。通过与接口联合使用,这一方案避免了对类似于C++虚拟基础类那样的一些机制的需要。
  为创建可进行“例示”(即创建一个实例)的一个interface(接口)的版本,需使用implements关键字。它的语法类似于继承的语法,如下所示:
 

 public interface Face {   
 public void smile();  
 }  
 public class Baz extends Bar implements Face {   
 public void smile( ) {   
 System.out.println("a warm smile");   
 }  
 }

(34) Java中没有virtual关键字,因为所有非static方法都肯定会用到动态绑定。在Java中,程序员不必自行决定是否使用


以上就是java到底和C++有啥区别?的内容,更多相关内容请关注PHP中文网(www.php.cn)!


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn