Utilisateur:Joris.deguet/Comparaison entre Java et C Sharp
- → N'hésitez pas à publier sur le brouillon un texte inachevé et à le modifier autant que vous le souhaitez.
- → Pour enregistrer vos modifications au brouillon, il est nécessaire de cliquer sur le bouton bleu : « Publier les modifications ». Il n'y a pas d'enregistrement automatique.
Si votre but est de publier un nouvel article, votre brouillon doit respecter les points suivants :
- Respectez le droit d'auteur en créant un texte spécialement pour Wikipédia en français (pas de copier-coller venu d'ailleurs).
- Indiquez les éléments démontrant la notoriété du sujet (aide).
- Liez chaque fait présenté à une source de qualité (quelles sources – comment les insérer).
- Utilisez un ton neutre, qui ne soit ni orienté ni publicitaire (aide).
- Veillez également à structurer votre article, de manière à ce qu'il soit conforme aux autres pages de l'encyclopédie (structurer – mettre en page).
- → Si ces points sont respectés, pour transformer votre brouillon en article, utilisez le bouton « publier le brouillon » en haut à droite. Votre brouillon sera alors transféré dans l'espace encyclopédique.
Cet article compare les dernières versions des langages de programmation Microsoft C# 5.0 et Oracle (précédemment Sun) Java. Le sujet principal est la comparaison des langages et de leurs caractéristiques, .
Les deux langages partagent énormément de similarité:
- un système de type statique, fort et explicite
- une programmation orientée objet passant par la définition de classes
- une exécution dans une machine virtuelle et l'utilisation de compilation à la volée pour augmenter la performance.
- une gestion automatique de la mémoire par l'utilisation d'un ramasse-miette (garbage collector en anglais)
- l'utilisation d'une syntaxe héritée du C.
Les origines communes des deux langages se retrouvent également dans leurs syntaxes.
Langage et caractéristiques (Guillaume)
modifierCette section présente une comparaison entre les langages en termes de fonctionnalités qui sont ou non disponibles, ou, expliqué différemment, de propriétés que les langages ont ou non. L’absence d’une fonctionnalité ne devrait être automatiquement vue comme un désavantage pour le langage en question. Parfois, des fonctionnalités sont exclues d’un langage parce que ses concepteurs les considèrent nuisibles. Dans d’autres cas, les concepteurs peuvent avoir considéré les fonctionnalités intéressantes mais apportant trop de complexité au langage pour ce qu’elles apportent.
Types de données (Antoine)
modifierData types | Java | C# |
---|---|---|
Single-root (unified) type system | (no) | Oui[1] |
Signed integers | Oui; 8, 16, 32, 64 bits | Oui; 8, 16, 32, 64 bits |
Unsigned integers | (no); deliberately left out[2] | Oui; 8, 16, 32, 64 bits |
Character | Oui | Oui |
Date/time | Oui; reference type | Oui; value type |
IEEE 754 binary32 floating point number | Oui | Oui |
IEEE 754 binary64 floating point number | Oui | Oui |
High precision decimal number | (no);but see Arbitrary size decimals below | 128-bit (28 digits) Decimal type |
Boolean type | Oui | Oui |
Strings | Immutable reference type, Unicode | Immutable reference type, Unicode |
Arbitrary size integers | Reference type; no operators | Oui |
Arbitrary size decimals | Reference type; no operators | (no)[3] |
Complex numbers | (no) | Oui |
Reference types | Oui | Oui |
Arrays | Oui | Oui |
Value types | (no); only primitive types | Oui |
Enumerated types | Oui; reference type | Oui; scalar |
Lifted (nullable) types | (no); but wrapper types | Oui |
Tuples | (no) | Oui |
Pointeurs | (no) | Oui |
Système de types unifié (Jordane)
modifierLes langages utilisent des systèmes de types orientés objet très similaires. En java, les types primitif sont spéciales de tel façon qu'ils ne sont pas orientée objet. Ils ne peuvent pas être définies en utilisant le langage lui-même. Ils ne partagent pas la même base aux types de référence. Les types de référence Java dérivent toutes d'un type de racine commune. C# dispose d'un système de type unifié dans lequel tous les types (à l'exception des pointeurs non sécurisés[4]) dérivent finalement d'un type de racine commune. Par conséquent, tous les types exécutent les méthodes de type racine. Les méthodes d'extensions définies pour le type d'objet
s'appliquent à tous les type, y compris les types primitifs Entier
littéraux et délégués. Contrairement à Java, cela permet à C# de supporter des objets avec l'encapsulation qui ne sont pas des type référence.
En Java, les types de composés sont des synonymes des types de références; les méthodes ne peuvent pas être définis pour un type sauf si elles sont aussi des classes de références. En C#, les concepts d'encapsulation et les méthodes ont été découplées de l'obligation de référence de sorte qu'un type peut supporté des méthodes et l'encapsulation sans être un type de référence. Seuls les types de référence soutien les méthodes virtuelles et la spécialisation.
Les deux langages supportent un certain nombre de types intégrés qui sont copiés et passés par valeur plutôt que par référence. Java appelle ces types des types primitifs, alors qu'ils sont appelés "types simples" en C#. Les types simples/primitifs ont généralement la prise en charge native de l'architecture du processeur.
Les types primitifs de C# implémente un certain nombre d’interfaces et offre par conséquent un nombre de méthodes directement sur les instances des types – même sur les littéraux. Les noms des types en C# sont aussi simplement des alias pour les types de Common Language Runtime. Le type Int64
en C# est exactement le même type que le type long
; la seule différence est que le premier est le nom canonique en .NET tandis que l’autre est un alias pour C#.
Java ne propose pas de méthodes directement pour les types primitifs. Au lieu, les méthodes qui fonctionnent sur les valeurs primitives sont offerts par l’entremise de compagnon wrapper classes. Un ensemble fixe de ces classes d’encapsulation existent, chacun d’entre elles enveloppes l’ensemble fixe des types primitifs. Par exemple, le type Long
en Java est un type de réference qui enveloppe le primitif long
. Par contre, ils ne sont pas du même type.
Entiers
modifierLes deux langages définissent des entiers signés de 8, 16, 32 et 64 bits. En dehors des entiers de 8 bits appelés byte
en Java et sbyte
(signed byte) en C#, les noms sont les mêmes.
C# définit en plus des entiers non signés. Les types signés sont byte
(8 bits), ushort
(16 bits), uint
(32 bits) and ulong
(64 bits). Les opérateurs conservent ces types, la somme de deux uint
est elle même de type uint
. Java ne définit pas de type primitif entier non signé.
L'absence d'un type octet (byte) non signé est considéré comme une potentielle source de complication du code[5].
Caractères (Joris)
modifierLes deux langages sont dotés d'un type char
(caractère). Il s'agit d'un type représenté sur 16 bits (2 octets) représentant les caractères Unicode.
Le type char
permet d'utiliser des opérateurs au niveau bit. Le résultat est un type numérique entier dans les deux langages parce que le char
est converti en entier (integer) avant l'opération.
Date et heure
modifierNombres en virgule flottante de 32 et 64 bits
modifierNombre décimaux de grande précision (Antoine)
modifierC# a un type et une notation littérale de l'arithmétique décimale de haute précision (28 chiffres après la virgule) qui est appropriée pour les calculs financiers et monétaires. [6][7][8] Contrairement aux types de données float
et double
, les nombres fractionnaires tels que 0,1 peuvent être représentés exactement en représentation décimale. Dans les types float
et double
, ces nombres ont souvent une représentation approchée, ce qui rend les erreurs d'arrondi fréquentes[7].
Java n'a pas une telle fonctionnalité intégrée, la bibliothèque Java fournit un type de précision arbitraire. Ce n'est pas considéré comme un type du langage et il ne supporte pas les opérateurs arithmétiques usuels, c'est plutôt un type de référence qui doit être manipulé à l'aide des méthodes de sa classe. Voir plus sur la taille arbitraire / nombres de précision ci-dessous. below.
Types numériques avancés (Alexandre 「Fait, Commentaires disponibles pour certaines parties」)
modifierLes deux langages offrent des entiers (int) à précision arbitraire, définis dans les librairies.
Seul Java offre des types de données arbitraires pour les chiffres à virgules et seul C# offre des types pour les nombres complexes.
C# permet aussi aux types définis par librairies d'être intégrés aux types et opérateurs déjà existants grâce à l'utilisation de conversions implicite/explicite, ainsi qu'à la surcharge d'opérateurs.
Dans les deux cas, le nombre d'opérations possibles sur les types numériques avancés est limité. Par exemple, aucun des types arbitraires ne supporte la racine carrée ou les logarithme.
Types de données primitifs intégrés (Skander) [DONE]
modifierLes deux langages traitent les strings (objet immuable) comme des types d'objets de référence. Également, dans les deux langages, les types de données contiennent plusieurs méthodes qui permettent de manipuler des strings, parse, format, etc. Les expressions régulières sont implémentées dans des classes séparées.
Par ailleurs, les librairies Java et C Sharp définissent des classes capables de traiter des informations et dates de différentes cultures. Ainsi, peu importe la culture, les deux langages supportent les opérations arithmétiques de dates et heures. Ceci dit, java.util.Date
de Java est un type de référence mutable, ce qui signifie que lors d'un changement d'une copie de Date, cela ne change que la copie et seulement cette copie. Par contre, en C#, System.DateTime
est une structure, ce qui signifie que toutes les copies qui ont été faits à partir d'une copie changée seront de la même valeur. De plus, C# définit un TimeSpan
pour traiter les intervalles de temps.
Value types (Jordane)
modifierC # permet au programmeur de créer des types de valeurs définies par l'utilisateur, en utilisant le mot-clé struct
. Contrairement aux classes et comme les standards primitifs, les types de valeur sont passés et attribués par valeur plutôt que par référence. Ils peuvent également faire partis d’un objet (en tant que champ ou en boîte), ou stockées dans un tableau sans l’indirection de la mémoire qui existe normalement pour les classes.
Parce que les types de valeur n’ont pas de notion de valeur nulle
et peuvent être utilisés dans des tableaux sans être initialisés, ils viennent toujours par défaut avec un constructeur implicite qui remplit essentiellement l’espace mémoire de la structure mémoire avec des zéros. Le programmeur peut seulement définir des constructeurs supplémentaires avec un ou plusieurs arguments. Les types de valeur ne sont pas des tables de méthodes virtuelles, et à cause de cela (et de l’empreinte de mémoire fixe), ils sont implicitement fermés. Cependant, les types peuvent (et le font souvent) implémenter des interfaces. Par exemple, les types d’entiers intégrés implémentent un nombre d’interfaces.
Outre les types primitifs intégrés, Java ne comprend pas le concept de types de valeurs.
Énumerations (Vincent)
modifierJava | C# | |
---|---|---|
Définition | En java, les types d’énumération et (optionnellement) et les valeurs d’énumération individuelles sont des classes Java. Les seules valeurs valides sont celles listées dans l’énumération. Le type de l’énumération peut déclarer ou surcharger des membres (tel que des méthodes toString() dédiées) qui seront héritées par les valeurs d’énumération individuelles et celui-ci peut être étendu par l'ajout de méthodes, de champs ou d'interfaces peuvent même y être implémentées.[9] The individual enumerated values may in turn override members or even define new members only valid for that specific value.
|
Enumerations in C# are implicitly derived from the Enum type that again is a value type derivative. The value set of a C# enumeration is defined by the underlying type that can be a signed or unsigned integer type of 8, 16, 32 or 64 bits. The enumeration definition defines names for the selected integer values and is syntactic sugar.[9][10][11] By default the first name is assigned the value 0 (zero) and the following names are assigned in increments of 1. Any value of the underlying primitive type is a valid value of the enumeration type, though an explicit cast may be needed to assign it.
|
Combining | Java enumeration set and map collections provide functionality to combine multiple enumeration values to a combined value. These special collections allows compiler optimization to minimize the overhead incurred by using collections as the combination mechanism. | C# supports bit-mapped enumerations where an actual value may be a combination of enumerated values bitwise or'ed together. The formatting and parsing methods implicitly defined by the type will attempt to use these values. |
In both C# and Java, programmers can use enumerations in a switch statement without conversion to a string or primitive integer type. However, C# disallows fall-throughs unless the case statement does not contain any code, as they are a main cause for hard-to-find bugs.[12] Fall-throughs must be explicitly declared using goto[13]
Delegate / method references (Justin)
modifierEn C#, il existe des pointeurs de méthodes sous la forme de delegate. Une variable de type delegate
conserve une référence de méthode qui peut être ensuite appeler au besoin. Un delegate
peut stocker un pointeur de référence vers n'importe quel méthode static
, méthode d'instance, des méthodes anonymes ou encore des expression lambda.
Les delegate
ne doivent pas être confondu avec les Fermeture_(informatique) ou les fonctions en lignes(inline functions), qui doivent être stocker dans un delegate
afin d'être appeler. Les delegate
et les MulticastDelegate
sont la base des évènements en C#, mais ne doivent pas être confondus avec eux où les EventsHandler
.
Les delegate
ont été volontairement laissé de côté en JAVA pour des raisons de problèmes de performances potentiels. Des mécanismes existent pour contourner ces lacunes, tel les adapteur, qui permmettent d'appeler des méthodes définis dans une interface.
Voir des exemples C# delegates and equivalent Java constructs
Types élevés (lifted) (Joris)
modifierC# permet au types du langage d'être élevé ("lifted") pour permettre la valeur null
habituellement réservé au types référence. Une variable est élevée en ajoutant le suffixe ?
au nom du type. Les conversions sont implicites entre le type normal et le type élevé. Une variable peut être comparée à null
et on peut invoquer HasValue
. La valeur null
est propagée par la plupart des opérateurs.
Java ne fournit pas cette possibilité. Toutefois chaque type primitif est complété par une classe (Integer pour int, par exemple), qui permet la valeur null
. En Java, l'utilisation de null
dans une opération provoque une NullPointerException
à l'exécution.
En C#, les opérateurs élevés * propage la valeur null
; en Java, l'accès à null lance une exception.
Certains opérateurs C# ne propagent pas null
: les opérateurs booléens produisent une logique ternaire compatible avec SQL.
Late-bound (dynamic) type (Kevin)
modifier(Brouillon)
C# est caractérisé par un type dynamique dit «late bound» qui supporte l'invocation dynamique sans réflexion, l'interopérabilité entre les languages dynamiques de même qu'une liaison ad-hoc avec (par exemple) le DOM. Le mot clé dynamic
résoud l'accessabilité aux membres de manière dynamique lors de l'exécution à comparar à de manière statique/virtuelle à la compilation. Le méchanisme de rechrche des membres est extensible avec la reflexion comme méchanisme de *repli*.
Il y a de multiple utilisation du mot-clé dynamic
en C# :
- Moins de reflexion explicite: En transtypant une instance avec le mot-clé
dynamic
, les membres tels que les propriétés, les méthodes, les évènements,etc. vont être directement invoqués sur l'instance sans utiliser directement l'API de refelection. - L'interopérabilité avec les langages dynamiques : Le type dynamique vient avec un support dit «hub-and-spoke» pour l'implémentation d'objets typés dynamiquement et d'infrastructures d'exécution pour la recherche efficace des membres.
- Création d'abstractions dynamiques «on the fly»: Par exemple, un type dynamique pourrait donné des accès à un DOM tel que du XML ou du XHTML.
La librairie standard de Java ne supporte le type «late bound». The use cases for C# dynamic type have different corresponding constructs in Java: *Les cas d'utilisation du type dynamique en C#*
- For dynamic late-bound by-name invocation of preexisting types, reflection should be used.
- For interoperability with dynamic languages, some form of interoperability API specific to that language will have to be used. The Java Virtual Machine platform does have multiple dynamic languages implemented on top of it, but there is no common standard for how to pass objects between languages. Usually this will involve some form of reflection or reflection-like API. As an example of how to use JavaFX objects from Java, voir How to Use JavaFX in Your Swing Application pour plus amples informations.
- For creating and interacting with objects entirely at runtime, e.g. interaction with a document object model abstraction, a specific abstraction API will have to be used.
The C# dynamic
enables seamless interoperability with dynamic (late-bound) languages by allowing C# code to manipulate foreign objects using the same syntax as, if they were native C# objects. Lacking this capability, Java developers must use a Java based API to access such objects. Consider a Ruby class (defined in a file called Deepthought.rb
) that has two attributes (a, b) with read/write accessors and a Calculate
method that returns the product of the attributes. The following examples illustrate how to instantiate and use such a class from within Java and C#, respectively.
Voir les exemples #Interaction_avec_les_autres_langages_dynamiques
Pointeurs (Kevin)
modifierC# allows use of pointers and corresponding pointer arithmetic. Pointers and pointer-arithmetic are potentially unsafe in a managed environment as they can be used to bypass the strict rules for object access. C# addresses that concern by requiring that code blocks or methods that use the feature be marked with the unsafe
keyword, so that all clients of such code can be aware that the code may be less secure than otherwise. The compiler requires the /unsafe switch to allow compilation of a program that uses such code, and assemblies containing unsafe code may only execute, if explicitly granted security permissions. Generally, unsafe code is either used to allow better interoperability with unmanaged APIs or system calls (that are inherently "unsafe"), or for performance reasons.
Java does not permit pointers or pointer-arithmetic within the Java runtime environment and native interop is handled externally through JNI or other mechanisms.
Types référence (Kevin)
modifierIn both languages references are a central concept. All instances of classes are by reference.
While not directly evident in the language syntax per se, both languages support the concept of weak references. An instance that is only referenced by weak references is eligible for garbage collection just as if there were no references at all. In both languages this feature is exposed through the associated libraries, even though it is really a core runtime feature.
In addition to weak references, Java has soft references. Soft references are much like weak references, but the JVM will not deallocate softly-referenced objects until the memory is actually needed.
Reference types | Java | C# |
---|---|---|
Garbage collection | Oui | Oui |
Weak references | Oui | Oui |
Soft and Phantom references | Oui | (no) |
Proxy support | Oui; proxy generation | Oui; object contexts |
Orienté objet (Félisha)
modifierJava et c# sont tous deux des langages orientés objets avec lesquels il est possible de faire une répartition dynamique en utilisant une syntaxe similaire au C++. La répartition dynamique est un processus qui consiste à implémenter des fonctions ou des méthodes qui appliquent le concept du polymorphisme, lors de l'exécution. Java et c# utilisent le sous-système de ramasse-miette. Ce sous-système, aussi appelé le récupérateur de mémoire, gère automatiquement la mémoire. En effet, il se charge de récupérer de la mémoire déjà allouée puis inutilisée. Cependant, si un objet possède des ressources qui ne sont pas des ressources mémoires, cet objet sera signalé explicitement, une fois qu'il ne sera plus utilisé et sera géré par une interface fournie, autant en Java qu'en C#, par le biais de méthode dispose.
Object orientation | Java | C# |
---|---|---|
Classes | Oui | Oui |
Interfaces | Oui | Oui |
Classes abstraites | Oui | Oui |
Niveaux d'accessibilité | Modèle:Oui; public, package, protected, private | Modèle:Oui; public, internal, protected, private, protected internal |
Classe de niveaux Classe interne | Oui;static Classes internes sont des Classes de niveaux |
Oui; Toutes les classes internes sont des classes de niveaux |
Instance de niveau classe interne | Oui | Non |
Instruction de niveau Classes anonymes | Oui | Non |
Classes partielles | Non | Oui |
Classes anonymes implicites | Non | Oui |
Dépréciation/obsolescence | Oui | Oui |
Surchage de versioning | Modèle:Parfois | Oui |
Enumérateurs peuvent implémenter des interfaces | Oui | Non |
Propriétés | Non, voir JavaBeans spec | Oui |
Évènements | Fourni par des librairies standards | Caractéristiques propre au language |
Définition d'opération | Non | Oui |
Indexeurs | Non | Oui |
Conversions implicites | Non | Oui |
Conversions explicites | Non | Oui |
Classes partielles (Félisha)
modifierC# offre la possibilité de fractionner la définition d'une classe, d'un struct ou d'une interface dans plusieurs fichiers source. Pour ce faire, chaque partie fractionnée doit être identifiée avec le mot clé partiel. Les fichiers source, qui comportent une section de la définition de la classe, se combinent une fois que l'application est compilée. Cette manière de faire est généralement utilisée lorsque la classe a beaucoup trop de code, d'où vient l'idée de diviser la classe en plusieurs fichiers pour, idéalement, les regrouper par fonctionnalités. La classe partielle est aussi utile lorsqu'on travaille avec une source générée automatiquement; du code peut être ajouté à la classe sans recréer le fichier source. Notons que l'utilisation du mot partiel pousse le développeur à l'utiliser pour toutes les parties à implémenter. Chacune de ces parties devra avoir la même accessibilité et devra être disponible lors de la compilation, afin de former le type final. Java ne possède pas de concept semblable à la classe partielle.
Classe interne et locale (Félisha)
modifierLa classe interne est une classe qui est déclarée dans une autre classe ou dans une interface. En Java la classe interne peut être déclarée static, non static, anonyme ou locale. Une classe locale interne a une portée est limitée à sa classe englobante. Cependant il est possible pour cette classe locale d'accéder aux attributs, aux paramètres ainsi qu'aux méthodes de sa classe mère, seulement si ceux-ci sont "final". La classe anonyme est aussi une classe locale. Toutefois, elle peut directement étendre une classe ou implémenter une interface. Pour ce qui est de la classe static, elle fonctionne comme une classe static normale. Cette dernière ainsi que celle qui l'englobe ne sont pas rattachées à une instance. Elle peut juste accéder aux variables et aux méthodes statiques de la classe qui l'englobe En c# la classe interne, aussi appelé la classe imbriquée, fonctionne comme une classe normale. En effet, c'est la classe qui l'englobe agit comme un namespace. La classe imbriquée est "private" par défaut. Le développeur peut la mettre public ou protected tout dépendant s'il veut rendre le contenu de la classe interne accessible.
Évènements (Guillaume)
modifierEn C#, les délégués multicast (multicast-delegates) sont appelés “événements” (events). Les événements permettent de faire de la programmation orientée évènements et implémentent le patron de conception Observateur (patron de conception). Afin de permettre cela, une syntaxe spécifique est utilisée pour définir les évènements dans les classes et les opérateurs à inscrire, désinscrire ou combiner les délégués.
Voir ici pour plus d’informations sur comment les évènements sont implémentés en Java.
Surcharge d'opérateurs et conversion implicite et explicite (Marc André)
modifierOperator overloading and user-defined casts are separate features that both aim to allow new types to become first-class citizens in the type system. By using these features in C#, types such as Complex
and decimal
have been integrated so that the usual operators like addition and multiplication work with the new types. Unlike C++, C# does restrict the use of operator overloading, prohibiting it for the operators new
, ( )
, ||
, &&
, =
, and any variations of compound statements like +=
. But compound operators will call overloaded simple operators, like -=
calling -
and =
[14].
Java does not include operator overloading, nor custom conversions in order to prevent abuse of the feature and to keep the language simple[15].
Indexers (Skander) [DONE]
modifierC# inclut des indexeurs qui sont considérées comme soit des cas spéciales de surcharge d'opérateur (comme en C++ avec operator[]
), ou bien des accesseurs qui acceptent des paramètres. Un indexeur est une propriété nommée this[]
qui utilise un ou des paramètres (index). L'indice peut être un objet de n'importe quel type, par exemple:
maListe[4] = 5;
string nom = xmlNode.Attributes["nom"];
commandes = mapClient[leClient];
Java n'inclut pas des indexeurs. La méthode commune en java consiste à écrire des getters et des setters explicites, là où les programmeurs C# utilisent des indexeurs.
Champs et initialisation (Yohann)
modifierChamps et initialisation | Java | C# |
---|---|---|
Champs | Oui | Oui |
Constantes | Oui | Oui; Ne supporte pas les constantes passées en paramètre[16] |
Constructeur static (Classe) | Oui | Oui |
Constructeur (Classe) | Oui | Oui |
"Finalizers" et "Destructors" | Oui | Oui |
Initialiser une instance | Oui | Non |
Initialisation d'objet | Du bas vers le haut (Champs et constructeurs) |
Du haut vers le bas (Champs); Du bas vers le haut (Constructeurs) |
Initialiser un objet | Non | Oui |
Initialiser une collection | Non; peut être modélisée | Oui |
Initialiser un tableau | Oui | Oui |
Fields and initialization | Java | C# |
---|---|---|
Fields | Oui | Oui |
Constants | Oui | Oui; but no support for constant passed parameters[16] |
Static (class) constructors | Oui | Oui |
Instance constructors | Oui | Oui |
Finalizers/destructors | Oui | Oui |
Instance initializers | Oui | (no) |
Object initialization | Bottom-up (fields and constructors) |
Top-down (fields); bottom-up (constructors) |
Object initializers | (no) | Oui |
Collection initializers | (no); can be modelled | Oui |
Array initializers | Oui | Oui |
Initialisation d'objets (Joris)
modifierEn C# et Java, les champs d'un objet peuvent être initialisés par des :
- affectation des variables
- une expression est affectée à chaque champ à l'endroit de sa déclaration
- constructeurs
- une forme de méthode ayant le nom de la classe qui est appelée à la création d'un objet.
EXEMPLES
En plus, Java fournit des blocs d'initialisation d'instance. Ce sont des blocs de code anonyme (pas de nom de méthode) sans paramètres qui sont appelés après l'appel (implicite ou explicite) au constructeur de la superclasse, avant l'appel au constructeur de la classe.
EXEMPLE
C# initializes object fields in the following order when creating an object:
- Derived static fields
- Derived static constructor
- Derived instance fields
- Base static fields
- Base static constructor
- Base instance fields
- Base instance constructor
- Derived instance constructor
Some of the above fields may not be applicable (e.g. if an object does not have static fields). Derived fields are those that are defined in the object's direct class, while base field is a term for the fields that are defined in one of the object's superclasses. Note that an object representation in memory contains all fields defined in its class or any of its superclasses, even, if some fields in superclasses are defined as private.
It is guaranteed that any field initializers take effect before any constructors are called, since both the instance constructor of the object's class and its superclasses are called after field initializers are called. There is, however, a potential trap in object initialization when a virtual method is called from a base constructor. The overridden method in a subclass may reference a field that is defined in the subclass, but this field may not have been initialized because the constructor of the subclass that contains field initialization is called after the constructor of its base class.
In Java, the order of initialization is as follows:
- Invocation of another constructor (either of the object's class or of the object's superclass)
- Instance variable initializers and instance initializers (in the order they appear in the source code)
- The constructor body
Like in C#, a new object is created by calling a specific constructor. Within a constructor, the first statement may be an invocation of another constructor. If this is omitted, the call to the argumentless constructor of the superclass is added implicitly by the compiler. Otherwise, either another overloaded constructor of the object's class can be called explicitly, or a superclass constructor can be called. In the former case, the called constructor will again call another constructor (either of the object's class or its subclass) and the chain sooner or later ends up at the call to one of the constructors of the superclass.
After another constructor is called (that causes direct invocation of the superclass constructor, and so forth, down to the Object class), instance variables defined in the object's class are initialized. Even if there are no variable initializers explicitly defined for some variables, these variables are initialized to default values. Note that instance variables defined in superclasses are already initialized by this point, because they were initialized by a superclass constructor when it was called (either by the constructor's code or by variable initializers performed before the constructor's code or implicitly to default values). In Java, variable initializers are executed according to their textual order in the source file.
Finally, the constructor body is executed. This ensures proper order of initialization, i.e. the fields of a base class finish initialization before initialization of the fields of an object class begins.
There are two main potential traps in Java's object initialization. First, variable initializers are expressions that can contain method calls. Since methods can reference any variable defined in the class, the method called in a variable initializer can reference a variable that is defined below the variable being initialized. Since initialization order corresponds to textual order of variable definitions, such a variable would not be initialized to the value prescribed by its initializer and would contain the default value. Another potential trap is when a method that is overridden in the derived class is called in the base class constructor, which can lead to behavior the programmer would not expect when an object of the derived class is created. According to the initialization order, the body of the base class constructor is executed before variable initializers are evaluated and before the body of the derived class constructor is executed. The overridden method called from the base class constructor can, however, reference variables defined in the derived class, but these are not yet initialized to the values specified by their initializers or set in the derived class constructor. The latter issue applies to C# as well, but in a less critical form since in C# methods are not overridable by default.
Méthodes et propriétés (frédéric (fait))
modifierMéthodes et propriétés | Java | C# |
---|---|---|
Imports statiques | Oui | Non |
Méthodes virtuelles | Virtuelles par défaut | Non-virtuelles par défaut |
Abstraction | Oui | Oui |
Encapsulation | Oui | Oui |
Implémentation explicite d'interface | Non | Oui[17] |
Paramètre intrant (input) | Oui | Oui |
Paramètre de référence (input/output) | Non | Oui |
Paramètre extrant (output) | Non | Oui |
Fonction variadique | Oui | Oui |
Arguments optionnels | Non | Oui |
Arguments nommés | Non | Oui |
Méthodes génératrices | Non | Oui |
Méthodes d'extension | Non | Oui |
Méthodes conditionnelles | Non | Oui |
Méthodes partielles | Non | Oui |
Méthodes d'extension (Julien)
modifierEn utilisant un désignateur spécial this sur le premier paramètre d'une méthode, C# permet à la méthode d'agir comme si elle était une méthode membre du type du premier paramètre. Cette extension de la classe étrangère est purement syntaxique. La méthode d'extension doit être statique et être définit dans une classe purement statique. Elle doit obéir à aucune restriction sur ces méthodes statiques externes et ne peut donc pas briser l'encapsulation d'objets. Cette "extension" est active seulement que dans l'étendue où l'espace de noms de la classe d'accueil statique a été importée. Java ne possède pas d'une fonctionnalité équivalente (même si une telle fonctionnalité est en discussion pour Java 8).
Méthodes partielles (Justin)
modifierLes méthodes et les classes partielles en C# permettent de spécifier des méthodes partielles qui sont séparées à l’intérieur d'une classe. Une méthode partielle peut avoir une signature dans un fichier, et déclarer le corps dans un autre fichier. La méthode ne peut pas avoir de type de retour (void
), et ne peut pas avoir de paramètre de retour (out, ref
). Les méthodes partielles, qui ne sont pas implémentées, seront ignorées lors de la compilation, ainsi tous les appels à la méthodes seront ignorés. Il est important de noter que les méthodes partielles sont implicitement privées (private
). Cette caractéristique permet d'offrir plusieurs points d'interceptions au code, et ce, sans compromettre la vitesse d’exécution si ces méthodes ne sont pas implémentées.
C# |
---|
//Fichier 1
partial void Foo();
//Fichier 2
partial void Foo()
{
//Corps de la méthode
}
|
Il n'existe aucun équivalent au mot clé partial
en JAVA.
Méthodes virtuelles (Justin)
modifierLes Méthodes en C# peuvent être déclarées virtuelles (Virtual
) explicitement au besoin, contrairement en Java, où toutes les méthodes qui ne sont pas static
, final
ou private
sont virtuelles par défaut. Les méthodes virtuelles assurent qu'un membre de substitution sera recherché dans le type courant, et éventuellement exécuté si ce membre de substitution existe. Cette recherche du membre de substitution résulte en une légère augmentation du temps d'exécution. Cependant, la plupart des compilateurs récents ont une fonction 'd'inlinning', qui élimine ce délai.
En Java, même si les méthodes sont 'virtual' par défaut, il est possible de l'empêcher en rajoutant le mot clé final
devant la méthode. Il deviendra alors impossible de définir un membre de substitution.
Donc, les méthodes dérivées en Java et en C# peuvent avoir la même signature que celle de la classe de base. Quand la méthode est appelée à partir d'une référence de la classe parent, comme 'object', la dernière implémentation de la méthode sera appelée.
C# | Java |
---|---|
public class Livre
{
public virtual string Nom
{
get{return "Livre";}
}
}
|
public class Livre
{
public String Nom()
{
return "Livre";
}
}
|
public class Roman : Livre
{
public override string Nom
{
get{return "Roman";}
}
}
|
public class Roman extends Livre
{
public override String Nom()
{
return "Roman";
}
}
|
Livre livre = new Roman();
Console.WriteLine(livre.Nom);
Retourne "Roman" |
Livre livre = new Roman();
System.Out.PrintLn(livre.Nom());
Retourne "Roman" |
En JAVA, si une classe implémente une méthode avec la même signature qu'une autre dans la classe de base, le méthode héritière sera donc appeler et masquera la méthode de la classe de base, et ce même si les dévelloppeurs des deux classes n'en voulait rien.
Afin de prévenir ceci, C# oblige le programmeur a mettre la mot clé overide
pour masquer une méthode virtuelle, ou new
pour masquer une méthode qui ne l'est pas.
Constant/immutable parameters
modifierIn Java, it is possible to make the passed parameters to a method unchangeable by using the [java] keyword. The language C# does not have this functionality.[16]
Java | C# |
---|---|
/**
* Getter for a value from the value array
* @param INDEX
* @return Requested value or -1, if the index is out of bounds.
*/
public short getValue(final short INDEX) {
if (INDEX < values.length) {
INDEX++; // ERROR: The final local variable INDEX cannot be assigned.
// It must be blank and not using a compound assignment
return values[INDEX];
}
else return -1;
}
|
no C# language equivalent |
This missing feature, however, has only limited use. For primitive types that are implemented as call by value, a modified value of a passed parameter inside the method does not affect the caller. Thus, for primitive types, to pass a parameter as [java] is only preventing a change of this parameter's value. For passed objects, a [java] parameter would prevent that another object is assigned to it, which is indeed a gain. It will, however, not prevent that the value contained by the object is safe.
Both languages do not support essential feature of const-correctness that exists in C/C++, which makes a method constant[18].
Generator methods (Marc André)
modifierModèle:Further
Any C# method declared as returning IEnumerable
, IEnumerator
or the generic versions of these interfaces can be implemented using yield
syntax. This is a form of limited, compiler-generated continuations and can drastically reduce the code required to traverse or generate sequences, although that code is just generated by the compiler instead. The feature can also be used to implement infinite sequences, e.g. the sequence of Fibonacci numbers.
Java does not have an equivalent feature. Instead generators are typically defined by providing a specialized implementation of a well-known collection or iterable interface, which will compute each element on demand. For such a generator to be used in a for each statement, it must implement interface java.lang.Iterable
.
See also example Fibonacci sequence below.
Explicit interface implementation (Marc André)
modifierC# also has explicit interface implementation that allows a class to specifically implement methods of an interface, separate to its own class methods, or to provide different implementations for two methods with the same name and signature inherited from two base interfaces.
In either language, if a method (or property in C#) is specified with the same name and signature in multiple interfaces, the members will clash when a class is designed that implements those interfaces. An implementation will by default implement a common method for all of the interfaces. If separate implementations are required (because the methods really do serve separate purposes, or because return values differ between the interfaces) C#'s explicit interface implementation will solve the problem, though allowing different results for the same method, depending on the current cast of the object. In Java there is no way to solve this problem other than refactoring one or more of the interfaces to avoid name clashes[17].
Reference (input/output) parameters (Marc André)
modifierThe arguments to a method are passed by value in Java, if they are primitive types and not objects. The String is also treated like a primitive type. This means that a method operates on copies of the items passed to it instead of on the actual items. In C#, it is possible to enforce a reference with the ref
keyword, similar to C++ and in a sense to C. This feature of C# is particularly useful when one wants to create a method that returns more than one object. In Java trying to return multiple values from a method is not supported[19].
See also example #Pass by reference below.
Généricité (Frédéric)
modifierPour ce qui est de la généricité, les deux languages comportent des différences syntaxiques superficielles. Par contre, ils ont des profondes différences en termes d'implémentation.
Les génériques | Java | C# |
---|---|---|
Implémentation | Effacage de type | Réification |
Réalisation à l'exécution | Non | Oui |
Covariance | Oui | Oui |
Contravariance | Oui | Oui |
Reference type constraint | Oui; implicit | Oui |
Value/primitive type constraint | (no) | Oui |
Constructor constraint | (no) | Oui |
Relation constraint | Oui | Oui |
Primitive/value type support | (no) | Oui |
Migration compatibility | Oui | (no) |
Type erasure versus reified generics (Frédéric)
modifierGenerics in Java are a language-only construction; they are implemented only in the compiler. The generated classfiles include generic signatures only in form of metadata (allowing the compiler to compile new classes against them). The runtime has no knowledge of the generic type system; generics are not part of the JVM. Instead, generics classes and methods are transformed during compilation through a process known as type erasure. During this process the compiler replaces all generic types with their raw version and inserts casts/checks appropriately in client code where the type and its methods are used. The resulting byte code will contain no references to any generic types or parameters (See also Generics in Java).
The language specification intentionally prohibits certain uses of generics; this is necessary to allow for implementing generics through type erasure, and to allow for migration compatibility[20].
C# builds on support for generics from the virtual execution system itself, i.e. it is not just a language feature. The language is merely a front-end for cross-language generics support in the CLR. During compilation generics are verified for correctness, but code generation for actually implementing the generics are deferred to class-load time. Client code (code invoking generic methods/properties) are fully compiled and can safely assume generics to be type-safe. This is called reification. At runtime, when a unique set of type parameters for a generic class/method/delegate is encountered for the first time, the class loader/verifier will synthesize a concrete class descriptor and generate method implementations. During the generation of method implementations all reference types will be considered a single type, as reference types can safely share the same implementations. Note, this is merely for the purpose of implementing code. Different sets of reference types will still have unique type descriptors; their method tables will merely point to the same code.
The following list illustrates some differences between Java and C# when managing generics. It is not exhaustive:[21]
Java | C# |
---|---|
Type checks and downcasts are injected into client code (the code referencing the generics). Compared to non-generic code with manual casts, these casts will be the same,[22] but compared to compile-time verified code that would not need runtime casts and checks, these operations represent a performance overhead. | C#/.NET generics guarantee type-safety and are verified at compile time, making extra checks/casts are unnecessary at runtime. Hence, generic code will run faster than non-generic (or type-erased) code that require casts when handling non-generic or type-erased objects. |
Cannot use primitive types as type parameters; instead, the developer must use the wrapper type corresponding to the primitive type. This incurs extra performance overhead by requiring boxing and unboxing conversions as well a memory and garbage collection pressure, as the wrappers will be heap-allocated as opposed to stack-allocated. | Primitive and value types are allowed as type parameters in generic realizations. At runtime code will be synthesized and compiled for each unique combination of type parameters upon first use. Generics that are realized with primitive/value type do not require boxing/unboxing conversions. |
Generic exceptions are not allowed[23] and a type parameter cannot be used in a catch clause[24] | Can both define generic exceptions and use those in catch clauses |
Static members are shared across all generic realizations[25] (during type erasure all realizations are folded into a single class) | Static members are separate for each generic realization. A generic realization is a unique class. |
Type parameters cannot be used in declarations of static fields/methods or in definitions of static inner classes | No restrictions on use of type parameters |
Cannot create an array where the component type is a generic realization (concrete parameterized type)
Object tenPairs =
new Pair<Integer, String>[10]; // error
|
A generic realization is a 1st class citizen and can be used as any other class; also an array component
object tenPairs =
new Pair<int, string>[10]; // OK
|
Cannot create an array where the component type is a type parameter
public class Lookup<TKey,TValue> {
public TValue[] getEmptyValues(TKey key) {
return new TValue[0]; // error
}
}
|
Type parameters represent actual, discrete classes and can be used like any other type within the generic definition.
public class Lookup<TKey, TValue> {
public TValue[] GetEmptyValues(TKey key) {
return new TValue[0]; // OK
}
}
|
There is no class literal for a concrete realization of a generic type | A generic realization is an actual class. |
instanceof is not allowed with type parameters or concrete generic realizations
|
The is and as operators work the same for type parameters as for any other type.
|
Cannot create new instances using a type parameter as the type | With a constructor constraint, generic methods or methods of generic classes can create instances of classes that have default constructors. |
Type information is erased during compilation. Special extensions to reflection must be used to discover the original type. | Type information about C# generic types is fully preserved at runtime, and allows complete reflection support as well as instantiation of generic types. |
Reflection cannot be used to construct new generic realizations. During compilation extra code (typecasts) are injected into the client code of generics. This precludes creating new realizations later. | Reflection can be used to create new realizations for new combinations of type parameters. |
C# allows generics directly for primitive types. Java, instead, allows the use of boxed types as type parameters (e.g., List<Integer>
instead of List<int>
). This comes at a cost since all such values need to be boxed/unboxed when used, and they all need to be heap-allocated. However, a generic type can be specialized with an array type of a primitive type in Java, for example List<int[]>
is allowed[26].
Compatibilité avec les versions précédentes (Frédéric)
modifierJava's type erasure design was motivated by a design requirement to achieve migration compatibility - not to be confused with backward compatibility. In particular, the original requirement was "… there should be a clean, demonstrable migration path for the Collections APIs that were introduced in the Java 2 platform".[27] This was designed so that any new generic collections should be passable to methods that expected one of the pre-existing collection classes[28].
C# generics were introduced into the language while preserving full backward compatibility, but did not preserve full migration compatibility: Old code (pre C# 2.0) runs unchanged on the new generics-aware runtime without recompilation. As for migration compatibility, new generic collection classes and interfaces were developed that supplemented the non-generic .NET 1.x collections rather than replacing them. In addition to generic collection interfaces, the new generic collection classes implement the non-generic collection interfaces where possible. This prevents the use of new generic collections with pre-existing (non-generic aware) methods, if those methods are coded to use the collection classes.
Covariance et contravariance (Frédéric)
modifierModèle:Further Covariance and contravariance is supported by both languages. Java has use-site variance that allows a single generic class to declare members using both co- and contravariance. C# has define-site variance for generic interfaces and delegates. Variance is not supported directly on classes but is supported through their implementation of variant interfaces. C# also has use-site covariance support for methods and delegates.
Programmation fonctionnelle (Frédéric)
modifierFunctional programming | Java | C# |
---|---|---|
Method references | (no); but see Delegates / method references | Oui |
Closures | (no); but see Delegates / method references | Oui |
lambda expressions | (no); but see Delegates / method references | Oui |
Expression trees | (no) | Oui |
Generic query language | (no) | Oui |
Closures (Frédéric)
modifierA closure is an inline function that captures variables from its lexical scope.
C# supports closures as anonymous methods or lambda expressions with full-featured closure semantics[29],[30].
In Java, anonymous inner classes remains the preferred way to emulate closures. This is a more verbose construction.
This approach also has some differences compared to real closures, notably more controlled access to variables from the enclosing scopes: only final members can be referenced.
When a reference to a method can be passed around for later execution, a problem arises about what to do when the method has references to variables/parameters in its lexical scope. C# closures can access any variable/parameter from its lexical scope. In Java's anonymous inner classes, only references to final members of the lexical scope are allowed, thus requiring the developer to mark which variables to make available, and in what state (possibly requiring boxing).
While Java does not currently feature closures, it has been announced that some form of closures or lambdas will be included in JDK 8 that at latest update (10 October 2010) is scheduled for release "late 2012"[31].
Lambdas et arbres d'expression (Guillaume)
modifierC# offre un type de spécial de fermeture «en-ligne» (in-line) appelé lambda. Ce sont des fonctions anonymes : Elles ont une signature et un corps, mais pas de nom. Elles sont principalement utilisées pour spécifier des arguments locaux évalués par fonctions dans des appels à d’autres méthodes : Une technique surtout associée à la programmation fonctionnelle. De plus, les fonctions lambda servent aussi pour définir des types spéciaux de structures de données appelés arbres d’expression. C’est l’inférence de types et le type de variable ou de paramètre à laquelle elle est assignée ou convertit à qui établit si un lambda est une fonction exécutable ou une structure de données. Les lambdas et les arbres d’expression jouent des rôles clé dans le LINQ.
Java ne propose pas de lambdas ou d’arbres d’expression; son mécanisme principal pour la capture de portée en-ligne et la définition de méthode est la syntaxe de classe interne anonyme.
Late binding voir s'il y en avait pas plus haut (Kevin)
modifierRuntime (dynamic) binding | Java | C# |
---|---|---|
Late-bound (dynamic) type | (no) | Oui |
Information et manipulation de types à l'exécution (Guillaume)
modifierInformation et manipulation de types à l'exécution | Java | C# |
---|---|---|
Information de types à l'exécution | Oui; mais avec l'effaçage de type | Oui |
Réalisation de génériques à l'exécution | (no) | Oui |
Construction de type à l'exécution | (no); mais des outils de tiers-partis existent | Oui |
Statements (Yohann)
modifierStatements | Java | C# |
---|---|---|
Loops | Oui | Oui |
Conditionals | Oui | Oui |
Flow control | Oui | Oui |
Assignment | Oui | Oui |
Exception control | Oui | Oui |
Variable declaration | Oui | Oui |
Variable type inference | (no) | Oui |
Deterministic disposal (ARM-blocks) | Oui (starting with Java 7) | Oui |
Expressions et opérateurs (Julien)
modifierExpressions and operators | Java | C# |
---|---|---|
Opérateurs arithmétiques | Oui | Oui |
Opérateurs logiques | Oui | Oui |
Opérateurs de bits logiques | Oui | Oui |
Conditionnel | Oui | Oui |
Concaténation de chaîne | Oui | Oui |
Transtypage | Oui | Oui |
Conversion type en objet | Oui; implicit | Oui; implicit |
Conversion objet en type | Oui; implicit | Oui; explicit |
Opérateurs levés | (no) | Oui |
Contrôle d'overflow | (no) | Oui |
Ébaluation d'un float strict | Oui; opt-in/out | (no) |
Littéral de chaîne textuel | (no) | Oui[32] |
Boxing and unboxing (ressemble au 1.3.4 conversions explicites)
modifierBoth languages allow automatic boxing and unboxing, i.e. they allow for implicit casting between any primitive types and the corresponding reference types.
In C#, the primitive types are subtypes of the Object type. In Java this is not true; any given primitive type and the corresponding wrapper type have no specific relationship with each other, except for autoboxing and unboxing, which act as syntactic sugar for interchanging between them. This was done intentionally, to maintain backward compatibility with prior versions of Java, in which no automatic casting was allowed, and the programmer worked with two separate sets of types: the primitive types, and the wrapper (reference) type hierarchy[33].
This difference has the following consequences. First of all, in C#, primitive types can define methods, such as an override of Object's ToString()
method. In Java, this task is accomplished by the primitive wrapper classes.
Secondly, in Java an extra cast is needed whenever one tries to directly dereference a primitive value, as it will not be boxed automatically. The expression ((Integer)42).toString()
will convert an integer literal to string in Java while 42.ToString()
performs the same operation in C#. This is because the latter one is actually an instance call on the primitive value 42
, while the former one is an instance call on an object of type java.lang.Integer
.
Finally, another difference is that Java makes heavy use of boxed types in generics (see below).
Exceptions (Marc-Oliver)
modifierExceptions | Java | C# |
---|---|---|
Checked exceptions | Oui | (no) |
Try-catch-finally | Oui | Oui |
Les exceptions de type «Checked» (Marc-Oliver)
modifierEn plus des exceptions unchecked, Java possède des exceptions de type checked. De son côté, C# ne supporte que les exceptions de type unchecked. Les exceptions de type checked force le programmeur à déclarer l’exception à l’aide du mot clef throws
dans la déclaration de la méthode ou à entourer celui-ci de blocs try/catch
.
Les exceptions de type checked peuvent encourager les programmeurs à bien programmer, en les forçant à s’assurer que toutes les erreurs sont gérées. Toutefois Anders Hejlsberg, chef-architecte du langage C#, affirme que ce type d’exception était en quelque sorte une expérimentation en Java et qu’ils n’avaient pas réussi à démontrer leur utilité, sauf dans les programmes de petite ampleur[34],[35].
Une des critiques à propos des exceptions de type checked avance que ces exceptions encouragent les programmeurs à utiliser des blocs «catch» vide (catch (Exception e) {}) dans le but d’étouffer l’exception plutôt que de laisser les exceptions se propager à un niveau supérieur de gestion des exceptions. Cependant dans certain cas, un exception chaining
peut être utilisée en relançant une autre exception apprêt avoir attraper la première. Par exemple, si un objet est modifié pour accéder à une base de données plutôt qu’à un fichier quelconque, une SQLException
pourrait être attrapée et un IOException
pourrait être relancé à la place, puisque la personne recevant cette exception n’a pas nécessairement besoin de connaître le fonctionnement interne de l’objet.
D’un autre côté, ce n’est pas tous les programmeurs qui s’entendent sur cette affirmation. En effet, James Gosling et plusieurs autres maintiennent que les exceptions de type checked sont une bonne idée et qu'elles ne sont pas utilisées correctement et que cela cause des problèmes. Il est effectivement possible d’étouffer l’exception, mais il faut pour cela explicitement dire ce que l’exception doit faire, contrairement aux exceptions de type unchecked qui ne permettent aucun default
. Il est possible de l’ignorer, mais pour il faut explicitement écrire le code le permettant[36],[37].
Try-catch-finally (Marc-Oliver)
modifierIl y a aussi quelque différence entre les deux langages dans le traitement des blocs try-finally
. Le bloc finally
fini toujours par s’exécuter et cela même, si le bloc try contient des instructions comme return
ou throw
. En Java, cela peut causer des erreurs lorsqu’une instruction try
possède une instruction qui retourne une valeur et que le bloc finally
possède aussi une instruction qui retourne une valeur différente. En C#, le problème a été régler. Il est impossible d’entré une instruction comme return
ou break
dans le bloc finally
.
Une raison courante pour l'utilisation de blocs try-finally
est de garder le code de gestion des ressources, garantissant ainsi la libération des ressources dans le bloc finally
. C # dispose de l'instruction using comme un raccourci syntaxique pour ce scénario commun, dans lequel la méthode Dispose () de l'objet est toujours appelé.
Une différence assez subtile est le moment où le stack trace est créé lorsqu'une exception est levée. En Java, le stack trace
est créé au moment où l'exception est créée.
class Foo {
Exception e = new Exception();
int foo() throws Exception {
throw e;
}
}
L'exception dans la déclaration ci-dessus contient toujours le stack-trace du constructeur - peu importe combien de fois foo est appelé. En C #, d'autre part, le stack-trace est créé le moment "throw
est exécuté.
class Foo {
Exception e = new Exception();
int foo() {
try {
throw e;
} catch (Exception e) {
throw;
}
}
}
Dans le code ci-dessus, l’exception contiendra le stack trace du premier throw-line
. Lorsqu’il attrape une exception, il y a deux options quand à ce qui peut être relancer: throw
va seulement relancer l’exception original avec le stack trace original, alors que throw e
va créer un nouveau stack trace.
Blocs finally (Marc-Oliver)
modifierJava permet au contrôle de flux de quitter le bloc finally
d'une instruction try
, indépendamment de la façon dont elle a été saisie. Cela peut provoquer un autre contrôle de flux (comme le return
) pour se terminer à mi-exécution. Par exemple:
int foo() {
try {
return 0;
} finally {
return 1;
}
}
Dans le code ci-dessus, l’instruction return
au sein du bloc try
fait en sorte que le contrôle sorte du bloc. Cependant, le bloc finally
s’exécute lui aussi avant que le résultat soit rendu. Ainsi la méthode retourne 1 plutôt que 0.
C # ne permet pas de déclarations qui permettent aux contrôle de flux de quitter le bloc finally
prématurément, à l'exception le l’instruction throw
. En outre, l’instruction return
n'est pas autorisée du tout, de même que l’instruction goto
n'est pas autorisé. De plus les instructions continue
et break
ne sont pas non plus accepter
Tableaux et collections (Skander) [Almost Done]
modifierLes tableaux et les collections sont deux concepts intégrés dans les deux langages.
Tableaux et collections | Java | C# |
---|---|---|
Type de données abstraites | Oui | Partiel |
Tableaux une dimension, commençant avec l'index 0 | Oui | Oui |
Tableaux multidimensionnels, rectangulaire (tableau simple) | (no) | Oui |
Tableaux multidimensionnels, (tableaux de tableaux) | Oui | Oui |
Tableaux ne commençant pas avec l'index 0 | (no) | Parfois |
Tableaux et collections unifiés | (no) | Oui |
Maps/dictionnaires | Oui | Oui |
Dictionnaires triées | Oui | Oui[38] |
Sets | Oui | Oui |
Sets triés | Oui | Oui[39] |
Listes/vecteurs | Oui | Oui |
Files/piles | Oui | Oui |
Files prioritaires | Oui | (no) |
Multiensembles | Oui | Oui |
La syntaxe utilisée pour déclarer et accéder aux tableaux est identique, à une seule exception où C# se dote d'une syntaxe pour déclarer et manipuler des tableaux multidimensionnels.
Java | C# |
---|---|
Les tableaux sont implicitement des spécialisations directes de Object . Ils ne sont pas unifiés avec des types de collection.
|
Les tableaux sont implicitement des spécialisations directes de la classe System.Array qui implémente de nombreuses collections d'interface.
|
Les tableaux et collections sont complètement séparés sans unification quelconque. Les tableaux ne peuvent être délégués s'il y a des séquences ou des collections attendues. | Les tableaux peuvent être délégués là où il y a des séquences (IEnumerables ) ou des listes/collections d'interface qui sont attendues. Cependant, les opérations de collection qui altèrent de nombreux éléments (ajouter/modifier/supprimer) peuvent lancer des exceptions si ces opérations ne sont pas supportées par les tableaux.
|
La boucle for accepte soit des tableaux ou des Iterables . Toutes les collections implémentent des Iterables . Cela signifie que la même syntaxe est utilisée dans les boucles for .
|
La boucle foreach itère à travers une séquence utilisant l'interface IEnumerable ou IIEnumerable<T> . Et parce que les tableaux implémentent toujours et implicitement ces interfaces, la boucle va itérer également à travers ces tableaux.
|
Dans les deux langages, les tableaux sont covariants. Cela signifie que le tableau de String[] est assignable à des variables d'Object[] puisque la String est une spécialisation de Object . Par sécurité, les tableaux des deux langages vont toujours vérifier les type de données lorsqu'il y a ajout de nouvelles valeurs.
| |
Pas de tableaux multidimensionnels (tableaux rectangulaires), mais les tableaux peuvent référencer d'autres tableaux. | Possibilité de faire des tableaux multidimensionnels (tableaux rectangulaires), tout comme des tableaux qui référencent d'autres tableaux. |
Les tableaux ne peuvent être redimensionnés (cependant la méthode System.arraycopy() permet de faire des redimensions de tableaux graduellement).
|
En utilisant la méthode static Array.Resize() , les tableaux peuvent être redimensionnés en préservant les données existantes.
|
La bibliothèque java.util contient plusieurs caractéristiques, comme des structures de données comme des Sets et des Sets liés qui ne sont pas présents dans C#. De plus, elle présente de nombreux algorithmes pour manipuler les éléments d'une collection, comme chercher la plus grand élément en se basant sur quelques comparateurs d'objet, chercher le plus petit élément, mélanger la liste , faire des recherches en binaires, créer des versions immutables d'une collection, etc. [40]
|
Les collections de C# se composent de classes à partir des namespaces System.Collections et de System.Collections.Generic , avec de nombreuses interfaces utiles, classes abstraites, et de structures de données.[41]
|
Les tableaux multidimensionnels peuvent dans certains cas améliorer la performance à cause de la localité de référence (puisqu’il n’y a qu’une seule déréférence de pointer plutôt que un pour chaque dimension du tableau, comme c’est le cas avec un tableau de tableaux). Cependant, puisque tous les accès d’élément de tableau dans un tableau multidimensionnel requièrent une multiplication / un décalage entre plusieurs dimensions, c’est une avantage seulement dans le cas où les accès sont presque purement aléatoires.
Une autre différence est que l’entièreté d’un tableau multidimensionnel peut être assigné avec une seule utilisation de l’opérateur new
, tandis que les tableaux de tableaux nécessitent des boucles et des allocations pour chaque dimension. Il est à noter que bien que Java offre une construction syntaxique pour assigner des tableaux de tableaux avec des tailles régulières, les boucles et assignations multiples sont alors accomplies par la machine virtuelle et n’ont pas à être explicitement déclarées.
Les deux langages offre un ensemble extensif de types de collections qui incluent plusieurs listes ordonnées et non-ordonnées, dictionnaires, ensembles, etc.
Java supporte aussi la syntaxe du C/C++ par rapport à l’instanciation de tableaux :[42]
Java | C# |
---|---|
// Est valide, puisque "numbers"
// est un objet de type short[]
short[] numbers = new short[100];
// Est valide, mais déplace la spécification
// du tableau sur le nom de l'objet
double values[] = new double[100];
|
// Est valide, puisque "numbers"
// est un objet de type short[]
short[] numbers = new short[100];
// Ne va pas compiler
double values[] = new double[100];
|
Metadata annotations (Joris)
modifierMetadata | Java | C# |
---|---|---|
Metadata annotations/attributes | Interface based; user-defined annotations can be created[43] | Class based |
Positional arguments | (no); unless a single argument | Oui |
Paramètres nommés | Oui | Oui |
Valeurs par défaut | At definition | Through initialization |
Nested types | Oui | Oui |
Spécialisation | (no) | Oui |
Conditional metadata | (no) | Oui |
Preprocessing, compilation and packaging (alexandre)
modifierPreprocessing, Compilation and Packaging | Java | C# |
---|---|---|
Namespaces | Packages | Namespaces |
File contents | (no) | Free |
Packaging | Package | Assembly |
Classes/assembly search path | ClassPath | Both compile-time and runtime[44][45] |
Conditional compilation | (no) | Oui |
Custom errors/warnings | (no) | Oui |
Explicit regions | (no) | Oui |
Espace de noms et contenu des fichers sources (alexandre) Terminé, commentaires à l'intérieur
modifierEn C#, les espace de noms sont similaire à ceux du C++. Contrairement aux packages de Java, les espaces de noms ne sont aucunement liés a l'emplacement, sur le disque, du fichier source. Quoiqu'il n'est pas nécessaire pour un fichier source Java de refléter son emplacement, ceci reste une norme d'organisation.
Java a une syntaxe d'importation statique qui permets l'utilisation du nom court de méthodes et champs dans une classe. Par exemple, foo(bar)
où foo()
est importé de façon statique a partir d'une autre classe.
C# a aussi une syntaxe statique, mais celle-ci sert a obliger une classe a n'utiliser que des méthodes statiques. Les versions 3.0 et supérieures de C# permettent l'utilisation de méthodes d'extensions, celle-ci servent a ajouter statiquement une méthode à un type.
Le compilateur Java exige que le fichier source aie le même nom que la seule et unique classe qu'il contient. Contrairement à C# qui permets d'avoir un nom de classe et de fichier source différent. Il est aussi possible avec C# d'avoir plusieurs classe dans un même ficher source ou plusieurs fichiers source pour une même classe, les deux précédent sont impossible en Java.
C# et Java permettent l'importation de classes, ceci permets de faire référence à cette même classe par son nom. Lorsque plusieurs classe existent avec le même nom, il est possible de référencer ces classes avec leurs fully qualified names, par exemple import java.util.List
. C# permets de renommer localement une classe en utilisant la syntaxe suivante : using IntList = System.Collections.Generic.List<int>
.
Compilation conditionnelle (Alexandre)
modifierContrairement à Java, C# implémente la compilation conditionelle grâce aux directives préprocesseur. Celà fournit aussi un attribut conditionnel servant à définir les méthodes qui sont seulement appelées lorsqu'une constante de compilation précise est définie. De cette façon, les assertions peuvent être fournies en tant que attribut de framework à l'aide de la méthode Debug.Assert()
. Celle-ci est seulement évaluée lorsque la constante DEBUG
est définie.
Depuis la version 1.4 de Java, Il est possible d'activer les assertions en utilisant les commandes -enableassertions
ou -ea
lors de l'appel de la JVM, car celles-ci sont désactivées par défaut.
Fils d'exécution (mieux connu sous le nom de "Threads") et fonctionnalités asynchronisées (Billy)
modifierLes deux langages informatiques incluent le mécanisme du fil d'exécution, nommé la synchronisation. Le fil d'exécution fait partie de la syntaxe de leur langage.
Les fil d'exécution et la Synchronisation | Java | C# |
---|---|---|
Fils d'exécution | Oui | Oui |
Thread pool | Oui | Oui |
Parallelisme basé sur les tâches | Modèle:Partiel[46] | Oui[47] |
Semaphores | Oui | Oui |
Moniteurs | Oui | Oui |
Variables locales du fil d'exécution | Oui | Oui; ThreadStaticAttribute (Attribut Statique du fil d'exécution) |
Native interoperability (Billy)
modifierNative interoperability | Java | C# |
---|---|---|
Cross-language interoperability | Non (only with CORBA or JNI)[48] | Oui; C# a été conçu pour cela[48] |
Méthodes natives externes | Oui | Oui |
Triage | Non; Glue code externe requis | Oui; Les données meta (metadata) sont controllées |
Pointeurss et les opérations arithmétiques | Non | Oui |
Types natifs | Non | Oui |
Tampons(buffers) à taille fixe | Non | Oui |
Allocation de pile(stack) explicite | Non | Oui |
Address-of | Non | Oui |
Object pinning (Fixer une variable à une adresse) Fixed | Non | Oui |
La particularité de l' interface native Java (INJ/JNI) permet aux logiciels utilisant Java d'appeler du code n'étant pas de Java. Cependant, l'INJ a besoin d'avoir des instructions de code qui suivent plusieurs conventions et impose certaines restrictions sur les types et les noms étant utilisés. Cela signifie que l'on doit souvent adapter la couche du code Java ainsi que son héritage au besoin. Cette adaptation du code doit se faire dans un langage qui n'est pas du Java, soit en C ou en C++. L'Accès Natif de Java (ANJ/JNA) permet d'appeler plus facilement du code natif qui a seulement besoin du code Java, mais l'ANJ est coûteux du côté performance de l'application.
De plus, les bibliothèques d'applications tierces fournissent à Java-COM le pontage (ref), e.g. JACOB (gratuit), etJ-Integra for COM (propriétaire).
.NET Platform Invoke (P/Invoke) offrent les même capacités en permettant d'appeler de C# du code. Microsoft détermine que ce code est du code qui n'est pas gérer. À travers les attributs de données méta (metadata), le programmeur peut contrôler efficacement comment les paramètres et les résultats seront triés, donc cela évitera le besoin d'adapter le code qui n'a pas besoin de l'être. P/Invoke permet presque tout l'accès complet aux APIs de manière procédurales (tels que Win32 ou POSIX), mais ils limitent l'accès aux bibliothèques de classe C++.
De plus, .NET Framework permet aussi un pont de .NET à COM, permettant l'accès aux composantes COM comme si elles étaient des objets .NET de première classe.
C# est un langage qui permet au programmeur de désactiver l'option de correction automatique à l'écriture ainsi que d'autres fonctionnalités sécuritaires du CLR. C'est son runtime, qui traduit différents langages de programmation en code intermédiaire puis exécute ce dernier (car il comprend une machine virtuelle). Est à .NET approximativement ce qu'est une JVM à Java. C'est le CLR qui permet l'utilisation des variables de pointeurs. Lorsque cette fonctionnalité est utilisée, le programmeur doit annoter le code en utilisant les unsafe
balises. JNI, P/Invoke, et le code "unsafe" sont des fonctionnalités également dangereuses puisque cela expose l'application à certaines failles de sécurité et une instabilité de celle-ci. L'avantage du code "unsafe" et du code gérer tandis que celui du P/Invoke ou INJ/JNI est que cela permet au programmeur de continuer à travailler avec son environnement C# familier afin d'accomplir certaines tâches qui n'aurait pas pu accomplir en raison du code non gérer. Un assembleur (logiciel ou bibliothèque) utilisant du code "unsafe" doit être compilé avec un switch spécial et devrait être annoté de cette façon. Cela permets aux environnements runtime en prendre de plus amples précautions avant d'exécuter du code dangereux à compiler.
Plateformes supportées (Justin)(Done)
modifierPlatform support | Java | C# |
---|---|---|
Linux | Oui | via Mono (logiciel) |
Mac OS X | Oui | via Mono (logiciel) |
Solaris | Oui | via Mono (logiciel) |
FreeBSD | Oui | via Mono (logiciel) |
AIX | Oui | Partiel? |
iOS | via in-the-box[réf. nécessaire] | via Mono (logiciel) |
Windows | Oui | Oui |
Windows Mobile | Oui | Oui |
Windows Phone | Non | Oui |
Android | via Dalvik (machine virtuelle) | via Mono (logiciel) |
Feature phones | Oui | Non |
Symbian | Oui | Obsolete |
Blackberry | Oui | via cross-compiler[49] |
Syntaxe (Julien)
modifierLes deux langages sont considérés comme des langages "accolades" dans la famille C/C++. Dans l'ensemble, la syntaxe des deux langages sont très semblables. La syntaxe au niveau de la déclaration et de l'expression est quasi identique avec de l'inspiration évidente de la tradition C/C++. Au niveau de la définition de types (classes et interfaces), quelques différences mineures existent. Java est explicite quant à l'extension de classes et à l'implémentation d'interfaces, tandis que C# les déduit du genre de types qu'une nouvelle classe/interface dérive.
C# supporte plus de fonctionnalités que Java. Il est donc, dans une certaine mesure, évident qu'il y ait plus de mots-clés et de règles de grammaire dans la syntaxe que Java.
Mots-clés et rétrocompatibilité (Julien)
modifierPendant que les langages évoluaient, les concepteurs des deux langages ont fait face à des situations où ils voulaient étendre les langages avec de nouveaux mots-clés ou avec la syntaxe. Les nouveaux mots-clés, en particulier, peuvent briser le code existant au niveau de la source, c'est-à-dire que le vieux code ne pourrait plus compiler s'il est présenté à un compilateur d'une version ultérieure du langage. Les concepteurs de langages sont soucieux d'éviter de telles régressions. Les concepteurs des deux langages ont pris différents chemins quand ils ont rencontré ce problème.
Les concepteurs de langage Java ont évité les nouveaux mots-clés le plus possible, préférant introduire de nouvelles constructions syntaxiques qui n'étaient pas légales avant ou réutiliser des mots-clés dans de nouveaux contextes. De cette façon, ils n'ont pas compromis la rétrocompatibilité. Un exemple du passé peut être trouvé dans comment la boucle for
a été étendue pour accepter les types pouvant être itérés. Un autre exemple plus récent peut être trouver dans comment les mots-clés extends
et, particulièrement, super
ont été réutilisés pour spécifier les limites des types quand les génériques ont été introduits dans Java 1.5. À un moment donné, dans Java 1.4, un nouveau mot-clé assert
a été introduit qui n'était pas réservé comme mot-clé avant. Cela a eu le potentiel de rendre le code valide invalide si le code utilisait assert
comme un identifiant par exemple. Les concepteurs ont choisi d'approcher ce problème avec une solution à quatre étapes: 1) En introduisant un commutateur de compilateur qui indique si Java 1.4 ou une version ultérieure devait être utilisée, 2) En marquant seulement assert
comme un mot-clé en compilant avec Java 1.4 et les versions ultérieures, 3) En rendant par défaut Java 1.3 pour éviter de rendre (le code non courant 1.4) précédant invalide et 4) en émettant des avertissements si le mot-clé est utilisé en mode Java 1.3, afin de permettre aux développeurs de changer le code.
Les concepteurs du langage C# ont introduit plusieurs nouveaux mots-clés depuis la première version. Cependant, au lieu de définir ces mots-clés comme des mots-clés "globaux", ils les ont définit comme des mots-clés "sensibles au contexte". C'est-à-dire que même lorsqu'ils ont introduit (avec plusieurs autres) les mots-clés partial
et yield
dans C# 2.0, l'utilisation des ces mots comme identifiants est encore valide puisqu'il n'y a pas de conflits possibles entre l'utilisation en tant que mot-clé et en tant qu'identifiant, selon le contexte. De plus, la syntaxe du C# actuel est complètement rétro compatible avec le code source écrit pour toutes les versions précédentes sans spécification la version du langage utilisé.
Notation and special features
modifierSpecial feature keywords (Alexandre D.)
modifierMot clé | caractéristique et des exemples d'usage. |
---|---|
checked , unchecked |
En C#, par-défaut si une opération arithmétiques dépasse la valeur maximale du type primitif,l'opération arithmétiques causera une OverflowException . Par contre , si on ajoute checked le résultat sera 0 , et aucun problème d'exception.
public class Checkuncheck
{
static int valeurmax1 = int.MaxValue;
static int valeurmax2 = int.MaxValue;
public void TestCheck()
{
int valeurMystere = 0;
valeurMystere = checked((short)(valeurmax1 + valeurmax2));
}
}
}
}
|
get , set |
En c# le set et le get correspond à être des attributs d'une classe donc d'un objet. Le get permet d'avoir un accès en lecture et le set en écriture. C'est dans l'écriture (le set ) qu'on fait de la validation. La validation d'un attribut doit passer par le set et non dans une méthode ou bien dans une condition if. |
goto |
En c# le mot clef goto est utile lors d'un changement de bloc de commande dans une boucle switch . Java ne supporte pas ce mot clef goto (mais le mot clef goto est un mot réservé) Java peux supporté ce mot clef break et continue quand les situations la requière à l'occasion on peux utiliser le mot clef goto
switch(color)
{
case Color.Blue:
Console.WriteLine("Color is blue"); break;
case Color.DarkBlue:
Console.WriteLine("Color is dark");
goto case Color.Blue;
// ...
}
|
lock |
In C#, the lock keyword is a shorthand for synchronizing access to a block of code across threads (using a Monitor ), wrapped in a try … finally block.
|
out , ref |
C# has support for output and reference parameters. These allow returning multiple output values from a method, or passing values by reference. |
strictfp |
Java utilise strictfp est un modificateur d'accès comme son nom l'indique, strictfp agit sur les opérations en virgule flottante. C'est à dire sur les types primitifs double et float.
|
switch |
In C#, the switch statement also operates on strings and longs. Fallthrough is allowed for empty statements and possible via 'goto case' for statements containing code. Java's switch statement does not operate on strings (before Java 7) nor long primitive type but falls through for all statements (excluding those with 'break ').[50]
|
synchronized |
In Java, the synchronized keyword is a shorthand for synchronizing access to a block of code across threads (using a Monitor ), wrapped in a try … finally block.
|
throws |
Java requires every method to declare the checked exceptions or superclasses of the checked exceptions that it can throw. Any method can also optionally declare the unchecked exception that it throws. C# has no such syntax.
public int readItem() throws java.io.IOException
{
// ...
}
|
using |
In C#, using causes the Dispose method (implemented via the IDisposable interface) of the object declared to be executed after the code block has run or when an exception is thrown within the code block.
// Create a small file "test.txt", write a string,
// ... and close it (even if an exception occurs)
using (StreamWriter file = new StreamWriter("test.txt"))
{
file.Write("test");
}
|
Numeric applications
modifierTo adequately support applications in the field of mathematical and financial computation, several language features exist.[51] In this category, Java provides the strictfp keyword, which enables strict floating-point calculations for a region of code. This will ensure that calculations return exactly the same result on all platforms. C# provides no equivalent, but does provide the built-in decimal
type which has higher accuracy than the Java/C# double (128 bits vs 64 bits).
The BigDecimal and BigInteger types provided with Java allow arbitrary-precision representation of numbers. Modèle:As of the current stable release of the .NET framework (4.0) includes classes for manipulating arbitrary-precision integers and complex numbers (with operators overloaded for easy use so that C# BigInteger objects can be used just like any other primitive data type), but still the .NET Framework lacks classes to deal with arbitrary-precision floating point numbers (see software for arbitrary-precision arithmetic).
C# can help mathematical applications with the checked
and unchecked
operators that allow the enabling or disabling of run-time checking for arithmetic overflow for a region of code.
Language integrated query (LINQ)
modifierC#s Language Integrated Query (LINQ) is not really a single feature; rather it is a number of features designed to work together to allow for in-language querying capabilities. LINQ has emerged as one of the most distinguishing features between Java and C#Modèle:Whom?.
LINQ consists of the following features:
- Extension methods allow existing interfaces or classes to be extended with new methods. Implementations can be shared or an interface can have a dedicated implementation.
- Lambdas allow for expression of criteria in a functional fashion.
- Expression trees allow a specific implementation to capture a lambda as an abstract syntax tree rather than an executable block. This can be utilized by implementations to represent criteria in a different language, e.g. in the form of an SQL where clause as is the case with e.g. Linq, LINQ to SQL.
- Anonymous types and type inference supports capturing and working with the result type of a query. A query may both join and project over query sources that may lead to a result type that cannot be named.
- Query expressions to support a syntax familiar to SQL users.
- Nullable (lifted) types to allow for a better match with query providers that support nullable types, like e.g. SQL.
Exemples
modifierInput/output
modifierExample illustrating how to copy contents from one text file to another using both languages.
Java | C# |
---|---|
import java.io.*;
public class FileIOTest {
public static void main(String... args) throws IOException {
String string = null;
try (
BufferedReader br = new BufferedReader(
new FileReader(new File("input.txt")));
BufferedWriter bw = new BufferedWriter(
new FileWriter(new File("output.txt")))
) {
while ((string = br.readLine()) != null)
bw.write(string);
}
}
}
|
using System.IO;
class FileIOTest {
public static void Main(string[] args) {
using (var sr = new StreamReader("input.txt"))
using (var sw = new StreamWriter("output.txt"))
while (!sr.EndOfStream)
sw.WriteLine(sr.ReadLine());
}
}
|
Integration of library defined types
modifierC# allows library defined types to be integrated with existing types and operators by using custom implicit/explicit conversions and operator overloading as illustrated by the following example:
Java | C# |
---|---|
BigInteger bigNumber =
new BigInteger("123456789012345678901234567890");
BigInteger answer = bigNumber.multiply(new BigInteger("42"));
BigInteger square = bigNumber.multiply(bigNumber);
BigInteger sum = bigNumber.add(bigNumber);
|
var bigNumber =
BigInteger.Parse("123456789012345678901234567890");
var answer = bigNumber * 42;
var square = bigNumber * bigNumber;
var sum = bigNumber + bigNumber;
|
C# delegates and equivalent Java constructs
modifierJava | C# |
---|---|
// define a common interface for all invokeable objects
// (will use the wrapper pattern)
interface Invokeable {
boolean invoke(String arg);
}
// a target class
class Target {
public boolean targetMethod(String arg) {
// do something
return true;
}
}
// usage
void doSomething() {
// construct a target with the target method
final Target target = new Target();
// wrap the target
Invokeable ivk = new Invokeable() {
public boolean invoke(String arg) {
return target.targetMethod(arg);
}
};
// use the target through the wrapper
boolean result = ivk.invoke("argumentstring");
}
|
// a target class
class Target
{
public bool TargetMethod(string arg)
{
// do something
return true;
}
}
// usage
void DoSomething()
{
// construct a target with the target method
var target = new Target();
// capture the delegate for later invocation
Func<string, bool> dlg = target.TargetMethod;
// invoke the delegate
bool result = dlg("argumentstring");
}
|
Type lifting
modifierJava | C# |
---|---|
Integer a = 42;
Integer b = null;
// This will generate a runtime NullPointerException,
// because it attempts to unbox the null value.
Integer c = a * b;
|
int? a = 42;
int? b = null;
// c will receive the null value
// because * is lifted and one of the operands are null
int? c = a * b;
|
Interaction avec les autres langages dynamiques
modifierCet exemple illustre comment C# et Java sont utilisés pour initialiser et instancier une classe qui est implémentée dans un autre langage de programmation. La classe "Deepthought" est une classe implémentée en Ruby et représente une calculatrice qui multiple deux nombres (a
et b
) lorsque la méthode Calculate
est appelée.
Java | C# | |
---|---|---|
// Initialise et instancie Engine
ScriptEngineManager factory = new ScriptEngineManager();
ScriptEngine engine = factory.getEngineByName("jruby");
Invocable invocable = (Invocable) engine;
FileReader fr = new FileReader("Deepthought.rb");
engine.eval(fr);
|
// Initialise et instancie Engine
var runtime = ScriptRuntime.CreateFromConfiguration();
dynamic globals = runtime.Globals;
runtime.ExecuteFile("Deepthought.rb");
| |
// Instancie une nouvelle calculatrice "Deepthought"
Object calcClass = engine.eval("Deepthought");
Object calc = invocable.invokeMethod(calcClass, "new");
// Définir les champs de la calculatrice
invocable.invokeMethod(calc, "a=", 6);
invocable.invokeMethod(calc, "b=", 7);
// Effectue le calcul
Object answer = invocable.invokeMethod(calc, "Calculate");
|
// Instancie une nouvelle calculatrice "Deepthought"
var calc = globals.Deepthought.@new();
// Définir les champs de la calculatrice
calc.a = 6;
calc.b = 7;
// Effectue le calcul
var answer = calc.Calculate();
| |
Note lors de l'implémentation en Java:
|
Notes lors de l'implémentation en C#:
|
Passage par référence
modifierJava | C# |
---|---|
public class PassByRefTest {
public static void changeMe(String string) {
string = "Changed";
}
public static void swap(int x, int y) {
int temp = x;
x = y;
y = temp;
}
/**
* @param args
*/
public static void main(String[] args) {
int a = 5, b = 20;
String s = "still unchanged";
swap(a, b);
changeMe(s);
System.out.println("a = " + a + ", b = "
+ b + ", s = " + s);
}
}
|
using System;
class PassByRefTest{
public static void ChangeMe(out string s){
s = "Changed";
}
public static void Swap(ref int x, ref int y){
int z = x;
x = y;
y = z;
}
public static void Main(string[] args){
int a = 5, b = 10;
string s;
Swap(ref a, ref b);
ChangeMe(out s);
Console.WriteLine("a = " + a + ", b = " + b + ", s = " + s);
}
}
|
a = 5, b = 20, s = still unchanged |
a := 10, b := 5, s = Changed
|
Suite de Fibonacci
modifierThis example illustrates how the Fibonacci sequence can be implemented using the two languages. The C# version takes advantage of C# generator methods.
Java | C# |
---|---|
public class Fibonacci implements Iterable<Integer> {
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
private int a = 0;
private int b = 1;
public boolean hasNext() {
return true; // infinite sequence
}
public Integer next() {
int tmp = a;
a = b;
b = a + tmp;
return tmp;
}
public void remove() {
throw new UnsupportedOperationException
("Not supported on the Fibonacci sequence.");
}
};
}
}
|
public static IEnumerable<int> Fibonacci() {
int a = 0;
int b = 1;
while (true) {
yield return a;
a += b;
yield return b;
b += a;
}
}
|
The Java version defines a Fibonacci
class which represents the infinite sequence. The class implements a method which returns an #anonymous class based on the Iterator
interface. This interface allows client code to repeatedly call the hasNext()
method to inquire whether there are more numbers. As the Fibonacci sequence is infinite this method simply returns true (there's always next number). The next()
method calculates and returns the next number. As the interface formally also allows the client to request removal of numbers, this methods also has to be implemented. However, in this case removal of numbers is not supported as the Fibonacci sequence is a mathematically defined sequence.
The C# version defines a method as opposed to a class. The method returns an IEnumerable
which makes it eligible for being implemented as a generator method by using the yield
syntax. The fact that the Fibonacci sequence is an infinite sequence is represented by an infinite loop. Inside the loop the numbers are "yielded". A yield return
statement returns the next number in the sequence but will continue the execution at the following statement when (and if) the client requests the next number.
Environments d'exécution (Alexandre)
modifierJava est conçu pour s’exécuter sous la Plateforme Java, via le [[Java Runtime Environment] ou JRE. La plateforme Java inclut la Java Virtual Machine ou JVM, ainsi qu'un lot de librairies communes.
Au départ, la JRE avait été conçue pour supporter l’exécuter interprété avec une compilation finale en option, ce qui n'est plus le cas. Le plupart des JRE exécutent des programmes totalement ou au moins partiellement compilés, possiblement avec l'optimisation adaptative.
Le compilateur Java produit du bytecode Java. Lors de l'exécution, le bytecode est chargé par Java et est pas la suite sois interprété directement ou compilé, puis exécuté.
C# est conçu pour s'exécuter sur le Common Language Runtime, ou CLR. Le CLR exécute du code complétement compilé. Le compilateur C# produit des instructions Common Intermediate Language. Lors de cette exécution, le runtime charge le code et le compile en instructions machine pour l'architecture ciblée.
Voir aussi
modifierReferences
modifier- The type system is unified by default, unless the compiler is switched into unsafe mode where raw pointers are available as a datatype. Pointers are not derived from object nor does it have implicit conversions to/from the object data type
- Unsigned integers were deliberately left out of Java because James Gosling believed that programmers would not understand how unsigned arithmetic works.
retrieved from http://www.artima.com/intv/gosling3P.htmlIn programming language design, one of the standard problems is that the language grows so complex that nobody can understand it. One of the little experiments I tried was asking people about the rules for unsigned arithmetic in C. It turns out nobody understands how unsigned arithmetic in C works. There are a few obvious things that people understand, but many people don't understand it.
- C# and the base class library does not implement arbitrary size decimals. However, 3rd party implementaions exists, e.g. the BigRational at codeplex: [1]
- types de pointeur (C# Guide de programmation)
- (en) Joshua Bloch; Neal Gafter, Java puzzlers : traps, pitfalls, and corner cases, Upper Saddle River, NJ [u.a.], 5. print., (ISBN 978-0-321-33678-1), p. 36 :
« The lesson for language designers is that sign extension of byte values is a common source of bugs and confusion. The masking that is required in order to suppress sign extension clutters programs, making them less readable. Therefore, the byte type should be unsigned. »
- « decimal », C# Reference, Microsoft
- (en) Jon Jagger, Nigel Perry, Peter Sestoft, C♯ annotated standard, Amsterdam, Elsevier/Morgan Kaufmann Publishers, (ISBN 978-0-12-372511-0), « 11.1.7 The decimal type »
- (en) Heng Ngee Mok, From Java to C♯ : a developer's guide, Harlow, England, Addison-Wesley, (ISBN 978-0-321-13622-0), « 9.5. The decimal type »
- Dare Obasanjo, « A COMPARISON OF MICROSOFT'S C# PROGRAMMING LANGUAGE TO SUN MICROSYSTEMS' JAVA PROGRAMMING LANGUAGE » [archive du ], Dare Obasanjo, (consulté le ) : « In Java, enumerated types are a full fledged class which means they are typesafe and can be extended by adding methods, fields or even implementing interfaces. Whereas in C#, an enumerated type is simply syntactic sugar around an integral type (typically an int) meaning they cannot be extended and are not typesafe. »
- (de) Dominik Prof. Dr. Gruntz, « Java 5: Taming the Tiger: Syntactic Sugar » [archive du ], Fachhochschule Aargau, Nordwestschweiz, (consulté le ) : « Enumerationen sind die heimlichen Sieger von Java 1.5. Nach vielen Beteuerungen durch Sun, Enums seien in Java überflüssig und können einfach nachgebildet werden, wurden sie nun doch eingeführt. Die einfachste Möglichkeit einer Enumeration der Jahreszeiten sieht wie folgt aus … Das Schlüsselwort enum steht für eine spezielle Art von Klasse, die eine Enumeration definiert. … Im Gegensatz zu anderen Programmiersprachen wie C/C++ und C# kann man ihnen per Gleichheitszeichen keine ganzen Zahlen zuordnen. »
- Christoff Truter, « Syntactic sugar (C#): Enum » [archive du ], CSTrüter, (consulté le ) : « // Poorly designed enum don't do this … Obviously (like with everything else), we can misuse this piece of sugar ending up with a system suffering from hyperglycemia. … Seeing as the underlying type of our enum is an int (can also use other integral types) it can lead to some interesting issues when using an enum as bit flags via bitwise operators. »
- Dare Obasanjo, « A COMPARISON OF MICROSOFT'S C# PROGRAMMING LANGUAGE TO SUN MICROSYSTEMS' JAVA PROGRAMMING LANGUAGE: C. An Ever So Slight Feeling Of Dèjà Vu: 4. switch Statment » [archive du ], Dare Obasanjo, (consulté le )
- http://msdn.microsoft.com/en-us/library/13940fs2(v=vs.71).aspx
- Dare Obasanjo, « A COMPARISON OF MICROSOFT'S C# PROGRAMMING LANGUAGE TO SUN MICROSYSTEMS' JAVA PROGRAMMING LANGUAGE: Operator Overloading » [archive du ], Dare Obasanjo, (consulté le Date invalide (2012-09-06 )) : « NOTE: Unlike C++, C# does not allow the overloading of the following operators; new, ( ), »
- August 1998 Java News
- Corey Sunwold, « C# Equivalent to Java's "final" » [archive du ], Corey Sunwold, (consulté le ) : « There is than one use of the final keyword that C# does not have an equivalent for. When you pass a parameter to a method in Java, and you don't want that parameter's value to change within the scope of that method you can set it as final… » Erreur de référence : Balise
<ref>
incorrecte : le nom « final » est défini plusieurs fois avec des contenus différents. - Dare Obasanjo, « A COMPARISON OF MICROSOFT'S C# PROGRAMMING LANGUAGE TO SUN MICROSYSTEMS' JAVA PROGRAMMING LANGUAGE: D. Now For Something Completely Different: 15. Explicit Interface Implementation » [archive du ], Dare Obasanjo, (consulté le )
- « const-correctness: Methods », Wikipedia (consulté le ) : « Applying the const qualifier to instance methods thus is an essential feature for const-correctness, and is not available in many other object-oriented languages such as Java and C# or in Microsoft's C++/CLI or Managed Extensions for C++. »
- Dare Obasanjo, « A COMPARISON OF MICROSOFT'S C# PROGRAMMING LANGUAGE TO SUN MICROSYSTEMS' JAVA PROGRAMMING LANGUAGE: D. Now For Something Completely Different: 12. Pass by Reference » [archive du ], Dare Obasanjo, (consulté le ) : « In Java the arguments to a method are passed by value meaning that a method operates on copies of the items passed to it instead of on the actual items. In C#, as in C++ and in a sense C, it is possible to specify that the arguments to a method actually be references to the items being passed to the method instead of copies. This feature is particularly useful when one wants to create a method that returns more than one object. In Java trying to return multiple values from a method is not supported and leads to interesting anomalies like the fact that a method that swaps two numbers which has been the hallmark of freshman computer science classes for years is impossible to do in Java without resorting to coding tricks. »
- The Java Language Specification.
- see also Java Generics FAQs - Frequently Asked Questions by Angelika Langer
- http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ110
- http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ302
- http://www.angelikalanger.com/GenericsFAQ/FAQSections/TechnicalDetails.html#FAQ304
- there one instances of a static field per instantiation of a parameterized type?
- Generics in C#, Java, and C++
- JSR 14: http://www.jcp.org/en/jsr/detail?id=14
- http://gafter.blogspot.com/2004/09/puzzling-through-erasure-answer.html
- Jeffrey Richter, « An Introduction to Delegates », MSDN Magazine, (consulté le )
- Dustin Campbell, « What's In A Closure? », Did it with .NET, (consulté le )
- Mark Reinhold’s Blog: Plan B: The details [2] retrieved
- Dare Obasanjo, « A COMPARISON OF MICROSOFT'S C# PROGRAMMING LANGUAGE TO SUN MICROSYSTEMS' JAVA PROGRAMMING LANGUAGE: D. Now For Something Completely Different: 13. Verbatim Strings » [archive du ], Dare Obasanjo, (consulté le )
- The separation of primitive and reference types is a fundamental property of the Java programming language.: [3]
- The Trouble with Checked Exceptions
- Why doesn't C# have exception specifications?
- http://www.artima.com/intv/solid.html
- http://www.shaunabram.com/checked-exceptions-article/
- http://msdn.microsoft.com/en-us/library/f7fta44c.aspx
- http://msdn.microsoft.com/en-us/library/dd412070.aspx
- Dare Obasanjo, « A COMPARISON OF MICROSOFT'S C# PROGRAMMING LANGUAGE TO SUN MICROSYSTEMS' JAVA PROGRAMMING LANGUAGE: C. An Ever So Slight Feeling Of Dèjà Vu: 6. Collections » [archive du ], Dare Obasanjo, (consulté le ) : « The Java collection framework is similar to that in C# except for the fact that it can be considered a superset of the C# collection framework since it contains a number of extra features. The Java collection framework contains data structures that are missing from those in C# such as sets and linked lists. Also the Java collections framework not only has methods that enable one to access unsafe collections in a thread safe manner but contains thread-safe versions of most of the data structures as well. Finally, the Java collections framework has a number of algorithms for manipulating the elements within the data structures including algorithms that can do the following; find the largest element based on some Comparator, find the smallest element, find sublists within a list, reverse the contents of a list, shuffle the contents of a list, creates immutable versions of a colection, performs sorts, and binary searches. »
- Dare Obasanjo, « A COMPARISON OF MICROSOFT'S C# PROGRAMMING LANGUAGE TO SUN MICROSYSTEMS' JAVA PROGRAMMING LANGUAGE: C. An Ever So Slight Feeling Of Dèjà Vu: 6. Collections » [archive du ], Dare Obasanjo, (consulté le ) : « The C# collections framework consists of the classes in the System.Collections and the System.Collections.Generic namespaces. The Systems.Collections namespace contains interfaces and abstract classes that represent abstract data types such as IList, IEnumerable, IDictionary, ICollection, and CollectionBase which enable developers to manipulate data structures independently of how they are actually implemented as long as the data structures inherit from the abstract data types. The System.Collections namespace also contains some concrete implementations of data structures such as ArrayList, Stack, Queue, HashTable and SortedList. All four of the concrete data structure implementations enable one to obtain synchronized wrappers to the collection which allows for access in a thread-safe manner. The System.Collections.Generic namespace has generic implementations of the key data structures in the System.Collections namespace including generic List<T>, Stack<T>,Queue<T>, Dictionary<K,T> and SortedDictionary<K,T> classes. »
- Dare Obasanjo, « A COMPARISON OF MICROSOFT'S C# PROGRAMMING LANGUAGE TO SUN MICROSYSTEMS' JAVA PROGRAMMING LANGUAGE » [archive du ], Dare Obasanjo, (consulté le )
- Dare Obasanjo, « A COMPARISON OF MICROSOFT'S C# PROGRAMMING LANGUAGE TO SUN MICROSYSTEMS' JAVA PROGRAMMING LANGUAGE: Metadata Annotations » [archive du ], Dare Obasanjo, (consulté le ) : « However a key difference between C# attributes and Java annotations is that one can create meta-annotations (i.e. annotations on annotations) in Java but can not do the same in C#. Developers can create their own custom annotations by creating an annotation type which is similar to an interface except that the keyword @interface is used to define it. »
- http://msdn.microsoft.com/en-us/library/823z9h8w.aspx
- http://www.vcskicks.com/csharp_assembly.php
- Fork-join framework included with Java SE 7. Will be part of Java EE 7 when released.
- Microsoft Task Parallel Library
- Dare Obasanjo, « A COMPARISON OF MICROSOFT'S C# PROGRAMMING LANGUAGE TO SUN MICROSYSTEMS' JAVA PROGRAMMING LANGUAGE: C. An Ever So Slight Feeling Of Dèjà Vu: 15. Cross Language Interoperability » [archive du ], Dare Obasanjo, (consulté le ) : « There are a number of ways cross language interoperability works in Java. First of all, there is the Java Native Interface (JNI) … Java also has the ability to interact with distributed objects that use the common object request broker architecture (CORBA) via Java IDL. … C# and the .NET runtime were created with seamless cross-language interoperability as a design goal. »
- http://code.google.com/p/csharpblackberry/
- Dare Obasanjo, « A COMPARISON OF MICROSOFT'S C# PROGRAMMING LANGUAGE TO SUN MICROSYSTEMS' JAVA PROGRAMMING LANGUAGE: An Ever So Slight Feeling Of Dèjà Vu: 4. switch Statment » [archive du ], Dare Obasanjo, (consulté le )
- Java for Scientific Computation: Prospects and Problems
Liens externes
modifier- Spécifications du langage C# version 4.0
- Spécifications du langage Java version 7
- (en) C# and Java: Comparing Programming Languages at MSDN
- MSDN: Langage de programmation C# pour les développeurs Java
{{Portail|programmation informatique}} {{DEFAULTSORT:Comparaison Java et C Sharp}} <!--Categories--> [[Category:Java programming language]] [[Category:C programming language family]] <!--Interwikis--> [[en:Comparison_of_C_Sharp_and_Java]]