ホームページ >Java >&#&チュートリアル >JavaとC++の違いは何ですか?

JavaとC++の違いは何ですか?

黄舟
黄舟オリジナル
2017-02-06 11:49:111146ブラウズ

C++ プログラマーとして、私たちはオブジェクト指向プログラミングの基本概念をすでにマスターしており、Java の構文は間違いなく非常によく知られています。実際、Java はもともと C++ から派生したものです。

ただし、C++ と Java の間には依然としていくつかの重要な違いがあります。これらの違いはテクノロジーの大きな進歩を表していると言えば十分でしょう。これらの違いを理解すると、Java が優れたプログラミング言語である理由が理解できるでしょう。この付録では、Java と C++ を区別するいくつかの重要な特徴について説明します。


(1). 最大の障害は速度です。解釈された Java は C の実行速度よりも約 20 倍遅いです。 Java 言語のコンパイルを妨げるものは何もありません。この記事の執筆時点では、処理を大幅に高速化できるいくつかの準リアルタイム コンパイラが登場したばかりです。もちろん、より一般的なプラットフォーム用の純粋なネイティブ コンパイラが存在すると考えるのには十分な理由がありますが、それらのコンパイラがなければ、速度の制限により Java では解決できない問題がいくつかあるはずです。


(2). C++ と同様に、Java にも 2 種類のアノテーションが用意されています。


(3) すべてをクラスに配置する必要があります。グローバル関数やグローバル データはありません。グローバル関数と同等の関数を取得したい場合は、静的メソッドと静的データをクラスに配置することを検討してください。構造体、列挙型、共用体などは存在せず、「クラス」があるだけであることに注意してください。


(4) すべてのメソッドはクラスの本体で定義されます。したがって、C++ の観点からは、すべての関数が埋め込まれているように見えますが、実際はそうではありません (埋め込みの問題については後で説明します)。


(5) Javaではクラス定義はC++とほぼ同じ形式になります。ただし、終わりのセミコロンはありません。 class foo 形式のクラス宣言はなく、クラス定義のみがあります。

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


(6) Javaにはスコープ演算子「::」がありません。 Java ではすべてにドット表記が使用されますが、クラス内の要素のみを定義できるため、ドット表記について考える必要はありません。これらのメソッド定義もクラス内に存在する必要があるため、スコープのスコープを指定する必要はありません。私たちが気づいた違いの 1 つは、ClassName.methodName() を使用した静的メソッドの呼び出しです。また、パッケージ(package)の名前はピリオドで設定されており、importキーワードを使用してC++の「#include」の一部の機能を実装できます。たとえば、次のステートメント:
Import java.awt.*;
(#include は import に直接マッピングされていませんが、使用すると似たような感じになります。)


(7) C++ と同様に、Java には系列が含まれています。より効率的なアクセスを実現するための「main Type」(プリミティブ型)。 Java では、これらの型には、boolean、char、byte、short、int、long、float、double が含まれます。すべての主要なタイプのサイズは固有であり、マシンに依存しません (移植の問題を考慮して)。これは、マシンによってはパフォーマンスに確実に影響を与えます。 Java では、型チェックと要件がより厳格になっています。例:

条件式はブール型のみであり、整数は使用できません。

「副作用」を実現するには、X+Y のような式の結果を使用する必要があります。単に「X+Y」を使用することはできません。


(8) char (文字) 型は、国際的に受け入れられている 16 ビット Unicode 文字セットを使用しているため、ほとんどの国の文字を自動的に表現できます。
(9) 静的参照文字列は自動的に String オブジェクトに変換されます。 C や C++ とは異なり、使用できる独立した静的文字配列文字列はありません。
(10) Java は 3 つの右シフト演算子「>>>」を追加しました。これらは、「論理」右シフト演算子と同様の機能を持ち、最後にゼロ値を挿入できます。 「>>」は、シフト中に符号ビットを挿入します (つまり、「算術」シフト)。
(11) Java 配列は表面的には似ていますが、C++ と比較してまったく異なる構造を使用し、独特の動作をします。配列の大きさを知ることができる読み取り専用の長さのメンバーがあります。配列の境界を超えると、ランタイム チェックによって自動的に例外がスローされます。すべての配列はメモリの「ヒープ」内に作成され、ある配列を別の配列に割り当てることができます (配列ハンドルをコピーするだけです)。配列識別子は第 1 レベルのオブジェクトであり、そのすべてのメソッドは通常、他のすべてのオブジェクトに適用されます。
(12) メイン タイプに属さないすべてのオブジェクトは、新しいコマンドを通じてのみ作成できます。 C++ とは異なり、Java には、メイン タイプではないオブジェクトを「スタック上」に作成するための対応するコマンドがありません。すべての主要なタイプは、 new コマンドを使用しないとスタック上にのみ作成できます。すべてのメジャー クラスには独自の「ラッパー」クラスがあるため、new を使用して同等のメモリ「ヒープ」ベースのオブジェクトを作成できます (メイン タイプの配列は例外です。C++ の assign などのコレクションを使用して初期化するか、new を使用できます)。


(13) Javaでは事前に宣言する必要はありません。クラスまたはメソッドを定義する前に使用したい場合は、それを直接使用してください。コンパイラーは、適切な定義が使用されることを保証します。したがって、C++ とは異なり、初期の参照に関連する問題は発生しません。


(14) Java にはプリプロセッサがありません。別のライブラリのクラスを使用する場合は、import コマンドを使用してライブラリ名を指定するだけです。プリプロセッサのようなマクロはありません。


(15) Java は名前空間の代わりにパッケージを使用します。すべてがクラスに入れられ、クラス名の名前空間分解のようなことを行う「カプセル化」と呼ばれるメカニズムのおかげで、名前付けの問題はもう心配ありません。このパッケージでは、ライブラリ コンポーネントも単一のライブラリ名で収集されます。パッケージを「インポート」するだけで、残りの作業はコンパイラーが行います。


(16) クラスメンバーとして定義されたオブジェクトハンドルは自動的に null に初期化されます。 Java では、基本クラス データ メンバーの初期化が確実に保証されています。明示的に初期化されていない場合は、デフォルト値 (ゼロまたは同等の値) が取得されます。これらは、クラス内またはビルダー内で定義することによって、明示的に初期化できます (明示的初期化)。使用される構文は C++ の構文よりも理解しやすく、静的メンバーと非静的メンバーの両方に対して固定されています。 C++ のように静的メンバーの格納方法を外部から定義する必要がありません。


(17) Java には、C や C++ のようなポインターがありません。 new でオブジェクトを作成すると、参照を取得します (本書では常にそれを「ハンドル」と呼びます)。例:
String s = new String("howdy");
ただし、C++ 参照は作成時に初期化する必要があり、別の場所に再定義することはできません。ただし、Java 参照は、必ずしもそれが作成された場所に限定されるわけではありません。これらは状況に応じて任意に定義できるため、ポインターの必要性が一部排除されます。 C および C++ でポインタが頻繁に使用されるもう 1 つの理由は、任意のメモリ位置を指すことができるためです (これにより、ポインタが安全でなくなります。これが、Java がこのサポートを提供しない理由です)。ポインターは、プリミティブ変数の配列内を移動する効率的な手段として見られることがよくあります。 Java を使用すると、より安全な形式で同じ目標を達成できます。ポインターの問題に対する究極の解決策は、「固有のメソッド」(付録 A で説明) です。グローバル関数はなく、クラスだけがあるため、メソッドにポインタを渡しても、通常は大きな問題は発生しません。そして、オブジェクトへの参照を渡すことができます。 Java 言語は当初、「ポインターをまったく使用しない」と主張していましたが、多くのプログラマーが「ポインターなしでどうやって動作するのでしょうか?」と疑問を持つようになりました。そのため、後で「制限されたポインターを使用する」と記載されました。それが「真実」かどうかを自分で判断できる指標です。しかし、いずれにしても、「算術」というポインタは存在しません。


(18) Java は C++ と同様の「コンストラクター」を提供します。自分で定義しない場合は、デフォルトのビルダーが取得されます。また、デフォルト以外のビルダーが定義されている場合、デフォルトのビルダーは自動的に定義されません。これはC++と同じです。すべての引数が参照によって渡されるため、コピー ビルダーがないことに注意してください。


(19) Java には「デストラクター」はありません。変数には「スコープ」の問題はありません。オブジェクトの「存続期間」は、ガベージ コレクターによってではなく、オブジェクトの経過時間によって決まります。すべてのクラスのメンバーである Finalize() メソッドがあり、これは C++ の「デストラクター」に似ています。ただし、finalize() はガベージ コレクターによって呼び出され、「リソース」(開いているファイル、ソケット、ポート、URL など) を解放することだけを担当します。特定の場所で何かを実行したい場合は、特別なメソッドを作成して呼び出す必要があります。finalize() に依存することはできません。一方、C++ のすべてのオブジェクトは破棄されます (または「破棄されるべき」) が、Java のすべてのオブジェクトが「ガベージ」として収集されるわけではありません。 Java はデストロイヤーの概念をサポートしていないため、必要に応じてクリーンアップ メソッドを作成するように注意する必要があります。さらに、すべてのクリーンアップ メソッドは、クラス内の基本クラスおよびメンバー オブジェクトに対して明示的に呼び出す必要があります。


(20) Java にはメソッドの「オーバーロード」メカニズムがあり、C++ 関数のオーバーロードとほぼ同じように機能します。


(21) Java はデフォルトの引数をサポートしません。


(22) Java には goto はありません。採用されている無条件ジャンプ メカニズムは、現在の複数のネストされたループからジャンプするために使用される「ブレーク ラベル」または「コンティニュー スタンダード」です。


(23) Java はシングルルート階層構造を採用しているため、すべてのオブジェクトはルート クラス Object から一律に継承されます。 C++ では、どこからでも新しい継承ツリーを開始できるため、多くの場合、多数のツリーを含む「フォレスト」が表示されることになります。 Java ではとにかく階層構造が 1 つしかありません。これは表面上は制限のように見えるかもしれませんが、すべてのオブジェクトには少なくとも 1 つの Object インターフェイスが必要であることがわかっているため、多くの場合、より強力な機能が得られます。現在、C++ は、単一ルート構造を強制しない唯一の OO 言語と思われます。


(24) Java には、パラメータ化された型のテンプレートやその他の形式がありません。これは、オブジェクト参照を収容するために使用される、Vector (ベクター)、Stack (スタック)、および Hashtable (ハッシュ テーブル) という一連のコレクションを提供します。これらのコレクションを使用すると、さまざまな要件を満たすことができます。ただし、これらのコレクションは、C++ の「標準テンプレート ライブラリ」(STL) のようにすぐに呼び出せるように設計されていません。 Java 1.2 の新しいコレクションはより完全になっているように見えますが、まだ本格的なテンプレートを効率的に使用できていません。


(25) 「ガベージ コレクション」とは、Java でのメモリ リークの可能性ははるかに低いですが、完全に不可能ではないことを意味します (ストレージ領域を割り当てるために固有のメソッドを呼び出した場合、ガベージ コレクターは追跡と監視を行うことができません)。ただし、メモリ リークやリソース リークは、finalize() が不適切に記述されたことや、割り当てられたブロックの最後でリソースが解放されたことが原因で発生することがよくあります (現時点では「デストラクター」が特に便利です)。ガベージ コレクターは C++ に基づいた大きな進歩であり、多くのプログラミングの問題を目に見えなくします。ただし、ガベージ コレクターが対処できないいくつかの問題には適していません。しかし、ガベージ コレクターには数多くの利点があるため、この欠点は些細なもののように思えます。


(26) Java にはマルチスレッドのサポートが組み込まれています。特別な Thread クラスを使用すると、継承を通じて新しいスレッドを作成できます (run() メソッドは放棄されます)。 synchronized キーワードがメソッドの型修飾子として使用される場合、相互排他がオブジェクト レベルで発生します。オブジェクトの同期メソッドを使用できるスレッドは常に 1 つだけです。一方、同期メソッドが入力されると、最初にオブジェクトを「ロック」し、他の同期メソッドがそのオブジェクトを使用できないようにします。このメソッドを終了した後にのみ、オブジェクトは「ロック解除」されます。私たちは依然として、独自の「モニター」クラスを作成することによって、スレッド間のより複雑な同期メカニズムを実装する責任を負います。再帰的な同期メソッドは正常に機能します。スレッドの優先順位が同じ場合、時間の「スライス」は保証できません。


(27) C++ のように宣言コード ブロックを制御する代わりに、各クラス メンバーの定義にアクセス修飾子 (public、private、protected) を入れます。 「明示的な」(明確な) 修飾子が指定されていない場合は、デフォルトで「フレンドリー」が使用されます。これは、同じパッケージ内の他の要素もそれにアクセスできる (C++ で「友達」になるのと同じ) ことを意味しますが、パッケージの外部の要素はアクセスできないことを意味します。クラス、およびクラス内のすべてのメソッドには、ファイルの外部から「見える」かどうかを決定するアクセス修飾子があります。通常、同じパッケージ内の他のクラスからのアクセスを除外するよりも「フレンドリーな」アクセスの方が便利であるため、private キーワードが Java で使用されることはほとんどありません。ただし、マルチスレッド環境では、プライベートを適切に使用することが非常に重要です。 Java の protected キーワードは、「パッケージ内の継承子および他の要素からアクセスできる」ことを意味します。 Java には、C++ の protected キーワードに相当するものがないことに注意してください。これは、「継承者のみがアクセスできる」ことを意味します (以前は、この目的に「private protected」を使用できましたが、このキーワードの組み合わせはキャンセルされました)。


(28) ネストされたクラス。 C++ では、クラスをネストすると、名前が隠蔽され、コードの編成が容易になります (ただし、C++ の「名前空間」により、名前の隠蔽が不要になりました)。 Java の「カプセル化」または「パッケージ化」の概念は C++ の名前空間に相当するため、これは問題になりません。 Java 1.1 では、「内部クラス」の概念が導入されました。これは、内部クラスのオブジェクトを作成するときに必要な、外部クラスへのハンドルを秘密裏に維持します。これは、内部クラス オブジェクトが、あたかも外部クラス オブジェクトのメンバーが内部クラス オブジェクトに直接従属しているかのように、条件なしで外部クラス オブジェクトのメンバーにアクセスできる可能性があることを意味します。これにより、コールバック問題に対するより良い解決策が提供されます。C++ は、メンバーへのポインターを使用してこの問題を解決します。


(29) 先ほど紹介した内部クラスの存在により、Javaにはメンバーへのポインタが存在しません。


(30) Java には「インライン」メソッドはありません。 Java コンパイラはその裁量でメソッドを埋め込むことができますが、これを制御することはできません。 Java では、メソッドの Final キーワードを使用して埋め込みを「提案」できます。ただし、関数の埋め込みは C++ コンパイラに対する提案にすぎません。


(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)!


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。