C# versus Java
Hanspeter Mössenböck
Universität Linz
Institut für Praktische Informatik (Systemsoftware)
[email protected]
Der Kontext
Java-Technologie
.NET-Technologie
Entstehungsjahr
1995
2002
Betriebssysteme
Unix/Linux,
Windows, MacOS, ...
Windows (Linux, MacOS X)
Leitidee
Eine Sprache
auf vielen Plattformen
Viele Sprachen
auf einer Plattform
(VB, C++, J#, Eiffel, Fortran, ...)
VM
Java-VM
Common Language Runtime
Zwischencode
Java-Bytecodes
Common Intermediate Language
JIT-Compilation
per Methode
gesamt
Komponenten
Beans, EJB
Assemblies
Versionierung
-
ja
Applets
ja
-
Datenbanken
JDBC
ADO.NET
Web-Programmierung
Servlets, JSP
ASP.NET
2
Merkmale von C#
Sehr ähnlich zu Java
70% Java, 10% C++, 10% Visual Basic, 10% neu
Wie in Java
Wie in C++
•
•
•
•
•
•
•
•
•
•
• (Operator) Overloading
• Zeigerarithmetik in Unsafe Code
• Einige syntaktische Details
Objektorientierung (einf. Vererbung)
Interfaces
Exceptions
Threads
Namespaces (wie Packages)
Strenge Typprüfung
Garbage Collection
Reflection
Dynamisches Laden von Code
...
3
Neue Features in C#
Wirklich neu (vs. Java)
"Syntactic Sugar"
•
•
•
•
•
•
•
•
•
•
• Komponentenunterstützung
- Properties
- Events
• Delegates
• Indexers
• Operator Overloading
• foreach-Iterator
• Boxing/Unboxing
• ...
Referenzparameter
Objekte am Stack (Structs)
Blockmatrizen
Enumerationen
Uniformes Typsystem
goto
Systemnahes Programmieren
Versionierung
Attribute
Kompatibel mit anderen .NETSprachen
4
Typsystem von C#
Typen
Werttypen
Einfache Typen
bool
char
sbyte
short
int
long
byte
ushort
uint
ulong
Enums
Referenztypen
Structs
float
double
decimal
Klassen Interfaces Arrays Delegates
Benutzerdefinierbare Typen
Alle Typen sind kompatibel mit object
- können object-Variablen zugewiesen werden
- verstehen object-Operationen
5
Boxing und Unboxing
Auch Werttypen (int, struct, enum) sind zu object kompatibel!
Boxing
Bei der Zuweisung
object obj = 3;
Java 1.4
Object obj = new Integer(3);
wird der Wert 3 in ein
Heap-Objekt eingepackt
obj
3
Unboxing
Bei der Zuweisung
int x = (int) obj;
int x = ((Integer)obj).intValue();
wird der eingepackte int-Wert
wieder ausgepackt
6
Klassen und Vererbung
C#
Java
class A {
private int x;
public void Foo() {...}
public A(int x) { this.x = x; }
}
class A {
private int x;
public void Foo() {...}
public A(int x) { this.x = x; }
}
class B : A, I1, I2 {
private int y;
class B extends A implements I1, I2 {
private int y;
public int Bar() { ...}
public int Bar() { ...}
public B(int x, int y) : base(x) {
this.y = y;
}
public B(int x, int y) {
super(x);
this.y = y;
}
}
}
7
Überschreiben von Methoden
C#
Java
class A {
...
public virtual void Foo() { ...}
}
class A {
...
public void Foo() { ...}
}
class B : A {
...
public override void Foo() {
base.Foo();
...
}
}
class B extends A {
...
public void Foo() {
super.Foo();
...
}
}
8
Properties
Syntaktische Kurzform für get/set-Methoden
class Data {
FileStream s;
Typ des Properties
Name des Properties
public string FileName {
set {
s = new FileStream(value, FileMode.Create);
}
get {
return s.Name;
}
}
"Eingangsparameter"
von set
}
Wird wie ein Feld benutzt ("smart fields")
Data d = new Data();
d.FileName = "myFile.txt";
string s = d.FileName;
// ruft d.set("myFile.txt") auf
// ruft d.get() auf
9
Properties (Fortsetzung)
get oder set kann fehlen
class Account {
long balance;
public long Balance {
get { return balance; }
}
}
x = account.Balance;
account.Balance = ...;
// ok
// verboten
Nutzen von Properties
•
•
•
read-only und write-only-Daten möglich.
Validierung beim Zugriff möglich.
Benutzersicht und Implementierung der Daten können verschieden sein.
10
Indexer
Programmierbarer Operator zum Indizieren einer Folge (Collection)
class File {
FileStream s;
Typ des indizierten Ausdrucks
Name
(immer this)
Typ und Name
des Indexwerts
public int this [int index] {
get { s.Seek(index, SeekOrigin.Begin);
return s.ReadByte();
}
set { s.Seek(index, SeekOrigin.Begin);
s.WriteByte((byte)value);
}
}
}
Benutzung
File f = ...;
int x = f[10];
f[10] = 'A';
// ruft f.get(10)
// ruft f.set(10, 'A')
11
C# ist oft griffiger als Java
C#
Java
Hashtable tab = new Hashtable();
...
tab["John"] = 123;
...
int x = (int) tab["John"];
Hashtable tab = new Hashtable();
...
tab.put("John", new Integer(123));
...
int x = ((Integer) tab.get("John")).intValue();
String s = ...;
...
for (int i = 0; i < s.Length; i++)
process(s[i]);
String s = ..;
...
for (int i = 0; i < s.length(); i++)
process(s.charAt(i));
foreach (char ch in s)
process(ch);
12
Ausnahmebehandlung (Exceptions)
C#
try {
...
... throw myException;
...
} catch (E1 e) {
...
} catch (E2) {
...
} catch {
...
} finally {
...
}
Java
try {
...
... throw myException;
...
} catch (E1 e) {
...
} catch (E2 e) {
...
} catch (Throwable e) {
...
} finally {
...
}
13
Keine Checked Exceptions in C#
C#
void Foo() {
try {
if (...)
throw new E1();
else
throw new E2();
...
} catch (E1 e) {
...
}
}
Java
void Foo() throws E2 {
try {
if (...)
throw new E1();
else
throw new E2();
...
} catch (E1 e) {
...
}
}
Keine Checked Exceptions
Checked Exceptions
Wenn keiner der Rufer E2
abfängt, bricht das Programm mit
einem Laufzeitfehler ab.
Ausnahmen müssen abgefangen
oder mit throws im Methodenkopf
spezifiziert werden.
14
Checked Exceptions
Pro
+ Dokumentation für den Programmierer
+ Zwingt dazu, jeden Fehlerfall zu bedenken
Kontra
- Mühsam, wenn Ausnahme weitergereicht wird
void P() {
try {
... Q(); ...
} catch (E e) {...}
}
void Q() throws E {
... R(); ...
}
void R() throws E {
... S(); ...
}
void S() throws E {
...
throw new E();
}
- Verführt zu folgendem "Hack"
try {
...
} catch (E e) {}
Fehler wird verschluckt!
15
Delegate = Methodentyp
Deklaration eines Delegate-Typs
delegate void Notifier (string sender);
// normale Methodensignatur
// mit Schlüsselwort delegate
Deklaration einer Delegate-Variablen
Notifier notify;
Zuweisung einer Methode an eine Delegate-Variable
void SayHello(string sender) {
Console.WriteLine("Hello " + sender);
}
void SayGoodBye(string sender) {
Console.WriteLine("Good bye " + sender);
}
notify = new Notifier(SayHello);
notify = new Notifier(SayGoodBye);
Aufruf der Delegate-Variablen
notify("Max");
// Aufruf von SayHello("Max") => "Hello Max"
16
Multicast-Delegates
Delegate-Variable kann mehrere Werte gleichzeitig aufnehmen
Notifier notify;
notify = new Notifier(SayHello);
notify += new Notifier(SayGoodBye);
notify("Max");
// "Hello Max"
// "Good bye Max"
notify -= new Notifier(SayHello);
notify("Max");
// "Good bye Max"
17
Threads
C#
void P() {
... thread actions ...
}
Thread t = new Thread(new ThreadStart(P));
t.Start();
Java
class MyThread extends Thread {
public void run() {
... thread actions ...
}
}
Thread t = new MyThread();
t.start();
• Beliebige Methode kann als Thread
gestartet werden
• Thread-Aktionen müssen in einer
run-Methode stecken
• Keine Unterklasse von Thread nötig
• Unterklasse von Thread nötig, bzw.
Implementierung von Runnable
18
Thread-Synchronisation
Java
C#
class Buffer {
int[] data;
class Buffer {
int[] data;
public void Put(int x) {
lock(this) {
...
}
}
public void put(int x) {
synchronized(this) {
...
}
}
[MethodImpl(MethodImplOptions.Synchronized)]
public int Get() {
...
}
public synchronized int get() {
...
}
}
}
Monitor.Wait(this);
wait();
Monitor.Pulse(this);
Monitor.PulseAll(this);
notify();
notifyAll();
19
Attribute
Benutzerdefinierte Informationen über Programmelemente
•
•
•
•
Können an Typen, Felder, Methoden, etc. angehängt werden.
Werden als Metadaten gespeichert.
Können zur Laufzeit abgefragt werden.
Sind Unterklassen von System.Attribute.
Beispiel
[Serializable]
class C {...}
// macht C serialisierbar
Mehrfache Attribute zuweisbar
[Serializable] [Obsolete]
class C {...}
[Serializable, Obsolete]
class C {...}
20
Beispiel: [Conditional]-Attribut
Für bedingte Aufrufe von Methoden
#define debug
// Präprozessor-Anweisung
class C {
[Conditional("debug")]
static void Assert (bool ok, string errorMsg) {
if (!ok) {
Console.WriteString(errorMsg);
System.Environment.Exit(0);
}
}
static void Main (string[] arg) {
Assert(arg.Length > 0, "no arguments specified");
Assert(arg[0] == "...", "invalid argument");
...
}
}
Assert wird nur aufgerufen, wenn debug definiert wurde.
21
J# - Java unter .NET
• Vollständige Java-Syntax (JDK 1.1.4), ähnlich J++
• Delegates wie in C#
• Unterstützt die meisten Java-Bibliotheken (nicht RMI, JNI)
• Unterstützt die meisten .NET-Bibliotheken (ASP.NET, ADO.NET,
Windows Forms)
• Kann unter Visual Studio.NET verwendet werden
• Erzeugt keine Java-Bytecodes sondern .NET-Assemblies
=> nicht portabel, keine Applets
22
Was bringt die Zukunft?
Generische Typen
C# 2.0
Java 1.5
class Stack<T> {
void Push(T x) {...}
T Pop() {...}
...
}
class Stack<T> {
void Push(T x) {...}
T pop() {...}
...
}
Stack<int> s = new Stack<int>();
...
int x = s.Pop();
Stack<String> s = new Stack<String>();
...
String x = s.pop();
• Erzeugt neue Klasse Stack_int
• Keine Casts zur Laufzeit
•
•
•
•
Erzeugt keine neue Klasse
Stack-Elemente als Objects gespeichert
Versteckte Casts zur Laufzeit
Keine primitiven Typen (int, char, ...)
als Typparameter erlaubt!
23
Java 1.5 holt auf ...
Boxing / Unboxing
Object obj = 3;
int x = obj; // kein Cast nötig!
in C#
Object obj = 3;
int x = (int) obj;
Enumerationen
enum Color {red, blue, green}
...
if (color == Color.red) ...
enum Color {red, blue, green}
...
if (color == Color.red) ...
Spezielle for-Schleife ( foreach)
for (Object s : collection)
System.out.println((String)s);
foreach (string s in collection)
Console.WriteLine(s);
Metadaten ( Attribute)
public @interface Author {
String name();
}
...
@Author(name = "HM")
public void foo() {...}
public class Author : Attribute {
string _name;
public string Name { set {_name = value; } }
}
...
[Author(Name = "HM")]
public void Foo() {...}
24
C# 2.0 führt neue Features ein ...
Anonyme Methoden
delegate void Notifier (string s);
...
Notifier var = delegate (string s) {
Print("I got an " + s);
}
Partielle Typen
public partial class A { // in Datei X.cs
public void Foo() {...}
...
}
public partial class A { // in Datei Y.cs
public void Bar() {...}
...
}
Iteratoren
public class Stack {
private int[] data;
private int top;
public void Push(int x) {...}
public int Pop() {...}
...
public IEnumerator GetEnumerator() {
for (int i = 0; i < top; i++)
yield return data[i];
}
}
Stack stack = new Stack();
...
foreach (int x in stack)
Console.WriteLine(x);
25
Zusammenfassung
C#
mächtiger
Java
kleiner und einfacher
Structs, Referenzparameter,
Attribute, ...
bequemer und griffiger
größere Verbreitung
Indexer, Delegates, ...
flexibler
strikter
erlaubt Systemprogrammierung
Checked Exceptions,
kein Unsafe Code
besser unter Windows
portabler
26
Danke für Ihre Aufmerksamkeit
Folien unter
http://dotnet.jku.at
Beer, Bringruber,
Mössenböck, Wöß:
Mössenböck:
Die .NET-Technologie
Softwareentwicklung
mit C#
dpunkt.verlag, 2002
dpunkt.verlag, 2003