En tant que programmeur C, nous maîtrisons déjà les concepts de base de la programmation orientée objet, et la syntaxe de Java est sans aucun doute très familière. En fait, Java est à l’origine dérivé de C.
Cependant, il existe encore des différences significatives entre C et Java. Il suffit de dire que ces différences représentent de grands progrès technologiques. Une fois que nous aurons compris ces différences, nous comprendrons pourquoi Java est un excellent langage de programmation. Cette annexe vous guidera à travers certaines caractéristiques importantes qui distinguent Java du C.
(1). Le plus gros obstacle est la vitesse : le Java interprété est environ 20 fois plus lent que la vitesse d'exécution du C. Rien ne peut empêcher la compilation du langage Java. Au moment d’écrire ces lignes, certains compilateurs en temps quasi réel viennent d’apparaître et peuvent considérablement accélérer les choses. Bien sûr, il y a toutes les raisons de penser qu'il y aura des compilateurs natifs purs pour les plates-formes les plus populaires, mais sans ces compilateurs, il doit y avoir certains problèmes que Java ne peut pas résoudre en raison des limitations de vitesse.
(2) Comme C, Java propose également deux types d'annotations.
(3) Tout doit être placé dans une classe. Il n'y a pas de fonctions globales ni de données globales. Si vous souhaitez obtenir des fonctions équivalentes aux fonctions globales, pensez à placer les méthodes statiques et les données statiques dans une classe. Remarquez qu'il n'existe pas de structures, d'énumérations ou de syndicats, il y a juste des « classes » !
(4) Toutes les méthodes sont définies dans le corps de la classe. Donc, d'un point de vue C, il semble que toutes les fonctions ont été intégrées, mais ce n'est pas le cas (la question de l'intégration sera abordée plus tard).
(5) En Java, la définition de classe prend presque la même forme que C. Mais il n’y a pas de point-virgule fermant. Il n'y a pas de déclaration de classe du formulaire class foo, seulement une définition de classe.
class aType() void aMethod() {/* 方法主体*/} }
(6) Il n'y a pas d'opérateur de portée "::" en Java. Java utilise la notation par points pour tout, mais vous n'avez pas besoin d'y penser car vous ne pouvez définir que des éléments dans une classe. Même ces définitions de méthodes doivent se trouver à l’intérieur d’une classe, il n’est donc pas nécessaire de spécifier la portée de la portée. Une différence que nous avons remarquée est l'appel aux méthodes statiques : utiliser ClassName.methodName(). De plus, le nom du package (package) est établi avec un point, et le mot-clé import peut être utilisé pour implémenter une partie de la fonction "#include" de C. Par exemple, l'instruction suivante :
Import java.awt.*;
(#include n'est pas directement mappé pour importer, mais il a une sensation similaire lorsqu'il est utilisé.)
( 7) Semblable au C, Java contient une série de « types primitifs » pour obtenir un accès plus efficace. En Java, ces types incluent boolean, char, byte, short, int, long, float et double. Les tailles de tous les principaux types sont intrinsèques et indépendantes de la machine (pour tenir compte des problèmes de portage). Cela aura certainement un impact sur les performances, en fonction de la machine. La vérification de type et les exigences sont devenues plus strictes en Java. Par exemple :
Les expressions conditionnelles ne peuvent être que de type booléen et les entiers ne peuvent pas être utilisés.
Vous devez utiliser le résultat d'une expression comme X Y ; vous ne pouvez pas simplement utiliser « X Y » pour obtenir des « effets secondaires ».
(8) Le type char (caractère) utilise le jeu de caractères Unicode 16 bits internationalement accepté, il peut donc exprimer automatiquement les caractères de la plupart des pays.
(9) Les chaînes de référence statiques seront automatiquement converties en objets String. Contrairement à C et C, aucune chaîne de tableau de caractères statique indépendante n'est disponible.
(10) Java ajoute trois opérateurs de décalage vers la droite ">>>", qui ont des fonctions similaires aux opérateurs de décalage vers la droite "logiques" et peuvent insérer des valeurs nulles à la fin. ">>" insérera le bit de signe lors du décalage (c'est-à-dire un décalage "arithmétique").
(11) Bien que superficiellement similaires, les tableaux Java utilisent une structure assez différente et ont un comportement unique par rapport à C. Il existe un membre de longueur en lecture seule qui vous permet de connaître la taille du tableau. Et une fois la limite du tableau dépassée, la vérification d'exécution lèvera automatiquement une exception. Tous les tableaux sont créés dans le "tas" de mémoire et nous pouvons attribuer un tableau à un autre (en copiant simplement le handle du tableau). Les identifiants de tableau sont des objets de premier niveau et toutes leurs méthodes s'appliquent généralement à tous les autres objets.
(12) Tous les objets qui n'appartiennent pas au type principal ne peuvent être créés que via la nouvelle commande. Contrairement à C, Java n'a pas de commande correspondante pour créer des objets qui ne sont pas du type principal « sur la pile ». Tous les types principaux ne peuvent être créés que sur la pile sans utiliser la nouvelle commande. Toutes les classes principales ont leurs propres classes "wrapper", donc des objets équivalents basés sur un "tas" de mémoire peuvent être créés via new (à l'exception des tableaux de type principal : ils peuvent être initialisés via des collections comme dans C assign, ou utiliser new).
(13) Il n'est pas nécessaire de déclarer à l'avance en Java. Si vous souhaitez utiliser une classe ou une méthode avant de la définir, utilisez-la simplement directement : le compilateur veillera à ce que la définition appropriée soit utilisée. Contrairement au C, nous ne rencontrons aucun problème concernant les premières références.
(14) Java n'a pas de préprocesseur. Si vous souhaitez utiliser une classe dans une autre bibliothèque, utilisez simplement la commande import et spécifiez le nom de la bibliothèque. Il n’existe pas de macro de type préprocesseur.
(15) Java utilise des packages au lieu d'espaces de noms. Puisque tout est mis dans une classe, et grâce à un mécanisme appelé « encapsulation » qui effectue quelque chose comme la décomposition de l'espace de noms sur les noms de classe, les problèmes de nommage ne sont plus un problème. Le package rassemble également les composants de bibliothèque sous un seul nom de bibliothèque. Nous « importons » simplement un package et le compilateur fait le reste.
(16) Les descripteurs d'objet définis en tant que membres de la classe seront automatiquement initialisés à null. L'initialisation des données membres de la classe de base est garantie de manière fiable en Java. S'ils ne sont pas explicitement initialisés, ils obtiennent une valeur par défaut (zéro ou équivalent). Ils peuvent être explicitement initialisés (explicit initialisation) : soit en les définissant au sein de la classe, soit dans le constructeur. La syntaxe utilisée est plus facile à comprendre que la syntaxe C et elle est fixe pour les membres statiques et non statiques. Nous n'avons pas besoin de définir la méthode de stockage des membres statiques de l'extérieur, qui est différente de C.
(17) En Java, il n'y a pas de pointeurs comme C et C. Lorsque vous créez un objet avec new, vous obtiendrez une référence (ce livre l'appellera toujours un "poignée"). Par exemple :
String s = new String("howdy");
Cependant, les références C doivent être initialisées lors de leur création et ne peuvent pas être redéfinies vers un emplacement différent. Mais les références Java ne sont pas nécessairement limitées à l'emplacement où elles sont créées. Ils peuvent être définis arbitrairement en fonction de la situation, ce qui élimine en partie le besoin de pointeurs. Une autre raison de l'utilisation intensive des pointeurs en C et C est de pouvoir pointer vers n'importe quel emplacement mémoire (cela les rend également dangereux, c'est pourquoi Java ne fournit pas ce support). Les pointeurs sont souvent considérés comme un moyen efficace de se déplacer dans un tableau de variables primitives. Java nous permet d'atteindre le même objectif sous une forme plus sécurisée. La solution ultime aux problèmes de pointeurs est la « méthode inhérente » (discutée dans l'Annexe A). Passer un pointeur vers une méthode ne pose généralement pas beaucoup de problèmes car il n'y a pas de fonctions globales, juste des classes. Et nous pouvons passer une référence à l'objet. Le langage Java affirmait initialement qu'il « n'utilisait pas de pointeurs du tout ! » Mais comme de nombreux programmeurs ont commencé à se le demander, comment peut-il fonctionner sans pointeurs ? Ainsi, plus tard, il a été déclaré que « utilisez des pointeurs restreints ». C'est un indicateur qui vous permet de juger par vous-même si c'est « vrai » ou non. Mais de toute façon, il n'y a pas de pointeur « arithmétique ».
(18) Java fournit un "Constructeur" similaire à C. Si vous n'en définissez pas vous-même, vous obtiendrez un générateur par défaut. Et si un constructeur autre que celui par défaut est défini, le constructeur par défaut ne sera pas automatiquement défini pour nous. C'est la même chose que C. Notez qu'il n'y a pas de générateur de copie puisque tous les arguments sont passés par référence.
(19) Il n'y a pas de "Destructeur" en Java. Il n'y a pas de problème de « portée » avec les variables. La « durée de vie » d'un objet est déterminée par son âge et non par le garbage collector. Il existe une méthode finalize() qui est membre de chaque classe, ce qui est quelque peu similaire au "destructeur" de C. Mais finalize() est appelé par le garbage collector et est uniquement responsable de la libération des « ressources » (telles que les fichiers ouverts, les sockets, les ports, les URL, etc.). Si vous souhaitez faire quelque chose à un emplacement spécifique, vous devez créer une méthode spéciale et l'appeler. Vous ne pouvez pas compter sur finalize(). D'un autre côté, tous les objets en C seront (ou "devraient") être détruits, mais tous les objets en Java ne seront pas collectés comme "déchets". Puisque Java ne prend pas en charge le concept de destructeur, il faut veiller à créer une méthode de nettoyage lorsque cela est nécessaire. De plus, toutes les méthodes de nettoyage doivent être explicitement appelées pour les classes de base et les objets membres de la classe.
(20) Java dispose d'un mécanisme de "surcharge" de méthode, qui fonctionne presque exactement de la même manière que la surcharge des fonctions C.
(21) Java ne prend pas en charge les arguments par défaut.
(22) Il n'y a pas de goto en Java. Le mécanisme de saut inconditionnel qu'il adopte est le "break label" ou "continue standard", qui est utilisé pour sortir des multiples boucles imbriquées actuelles.
(23) Java adopte une structure hiérarchique à racine unique, de sorte que tous les objets sont uniformément hérités de la classe racine Object. En C, on peut démarrer un nouvel arbre d'héritage n'importe où, on se retrouve donc souvent avec une « forêt » contenant un grand nombre d'arbres. En Java, nous n’avons de toute façon qu’une seule structure hiérarchique. Bien que cela puisse sembler une limitation à première vue, des capacités plus puissantes sont souvent obtenues car nous savons que chaque objet doit avoir au moins une interface Objet. C semble actuellement être le seul langage OO qui n’applique pas une seule structure racine.
(24) Java n'a pas de modèles ou d'autres formes de types paramétrés. Il fournit une série de collections : Vector (vecteur), Stack (pile) et Hashtable (table de hachage), utilisées pour accueillir les références d'objet. Grâce à ces collections, une série de nos besoins peuvent être satisfaits. Mais ces collections ne sont pas conçues pour être appelées rapidement comme la "Standard Template Library" (STL) C. Les nouvelles collections de Java 1.2 semblent plus complètes, mais ne permettent toujours pas une utilisation efficace des modèles authentiques.
(25) "Garbage collection" signifie que les fuites de mémoire en Java seront beaucoup plus rares, mais pas complètement impossibles (si vous appelez une méthode inhérente d'allocation d'espace de stockage, le garbage collector ne peut pas suivre et surveiller il). Cependant, les fuites de mémoire et de ressources sont souvent causées par une finalize() mal écrite, ou par la libération d'une ressource à la fin d'un bloc alloué (les "destructeurs" sont particulièrement pratiques à ce moment-là). Le garbage collector est une grande amélioration basée sur C, qui rend invisibles de nombreux problèmes de programmation. Mais il ne convient pas à quelques problèmes pour lesquels le ramasse-miettes est incapable d’y faire face. Mais les nombreux avantages du garbage collector font que cette lacune semble triviale.
(26) Java prend en charge le multithreading. En utilisant une classe Thread spéciale, nous pouvons créer un nouveau thread par héritage (la méthode run() est abandonnée). Si le mot clé synchronisé est utilisé comme qualificatif de type pour une méthode, une exclusion mutuelle se produit au niveau de l'objet. À un moment donné, un seul thread peut utiliser la méthode synchronisée d'un objet. D'un autre côté, après l'entrée d'une méthode synchronisée, elle "verrouille" d'abord l'objet, empêchant toute autre méthode synchronisée d'utiliser cet objet. Ce n'est qu'après avoir quitté cette méthode que l'objet sera "déverrouillé". Nous sommes toujours responsables de la mise en œuvre de mécanismes de synchronisation plus complexes entre les threads en créant notre propre classe « moniteur ». Les méthodes synchronisées récursives fonctionnent correctement. Si les threads ont la même priorité, le « découpage » temporel ne peut pas être garanti.
(27) Au lieu de contrôler le bloc de code de déclaration comme C, nous mettons les qualificatifs d'accès (public, privé et protégé) dans la définition de chaque membre de la classe. Si un qualificatif « explicite » (sans ambiguïté) n'est pas spécifié, « convivial » sera la valeur par défaut. Cela signifie que d'autres éléments du même package peuvent également y accéder (ce qui équivaut à ce qu'ils deviennent les "amis" de C - amis), mais pas par un élément extérieur au package. Une classe (et chaque méthode au sein d'une classe) possède un qualificatif d'accès qui détermine si elle est « visible » de l'extérieur du fichier. Le mot clé private est généralement rarement utilisé en Java car un accès « convivial » est généralement plus utile que d'exclure l'accès des autres classes du même package. Cependant, dans un environnement multithread, l’utilisation appropriée de private est très importante. Le mot-clé protégé de Java signifie « accessible aux héritiers et aux autres éléments du package ». Notez que Java n'a pas d'équivalent au mot-clé protected de C, qui signifie "accessible uniquement aux héritiers" (auparavant "private protected" pouvait être utilisé à cet effet, mais cette combinaison de mots-clés a été annulée).
(28) Classes imbriquées. En C, les classes imbriquées permettent de masquer les noms et de faciliter l'organisation du code (mais les "espaces de noms" du C rendent le masquage des noms redondant). Le concept Java d'« encapsulation » ou de « packaging » est équivalent à l'espace de noms C, ce n'est donc plus un problème. Java 1.1 a introduit le concept de « classes internes », qui maintiennent secrètement un handle vers la classe externe – nécessaire lors de la création d'objets de classe interne. Cela signifie que l'objet de classe interne peut accéder aux membres de l'objet de classe externe sans aucune condition - comme si ces membres étaient directement subordonnés à l'objet de classe interne. Cela fournit une meilleure solution au problème de rappel – C est résolu avec des pointeurs vers les membres.
(29) En raison de l'existence de la classe interne introduite précédemment, il n'y a pas de pointeur vers un membre en Java.
(30) Il n'existe pas de méthode "inline" en Java. Le compilateur Java peut embarquer une méthode à sa discrétion, mais nous n'avons plus aucun contrôle sur celle-ci. En Java, vous pouvez utiliser le mot-clé final pour qu'une méthode "suggère" l'intégration. Cependant, les fonctions intégrées ne sont qu'une suggestion pour les compilateurs 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)!