JavaLanguage
The Language
Identifier
Java is case sensitive. Any identifier can start with a letter, even with an Ä,ö,... . Als special chars sind nur '_ und $' zugelassen.
Keywords
| const | is a reserved word, but is not part of the language |
| goto | is a reserved word, but is not part of the language |
Comments
// <CommentText> /* <CommentText> */ /** <Documentation text used by javadoc> */
Operators
+ i * / += -= *= /= %= &= |= ^= <<= >>= >>>= ++ -- == === < <= > >= && || & | ^ ~ >> >>> << ? : ,===
Die Abarbeitung von conditions erfolgt von links nach rechts und stoppt sofort. Vorsicht ist jedoch bei den binären Vergleichsoperatoren geboten, denn dort wird nicht abgebrochen (no short circuit):
if (v == null | v.size() > 1) // crash if v == null, use || instead.
Es sind mehrfach Zuweisungen der Form a = b = c; erlaubt.
- remainder operator\\
Der % operator schmeißt eine ArithmeticException, wenn der zweite Operand 0 ist.
Control Flow
| break; | jumps out of the current loop |
| break <label>; | the label has to be defined right before the n loops which should be breaked; if the break keyword is followed by an identifier that is the label of an arbitrary enclosing statement execution transfers out of the enclosing statement. Required finally clauses are executed and control resumes at the statement following the terminated statement. |
| continue; | |
| continue <label>; | [20] page 38 |
| do while | |
| for (<initialization>; <test>; <incrementation>)\\{\\ <statements>\\} | a declared variable inside the for-statement goes out of scope at the end of the for block. this is different from c++; there is a comma operator in the initialization and increment section; although variables declared in the initialization section have their scope in the for block the names must not collide with other variables |
| if then else | |
| switch | als case values sind nur basic datatypes ohne float und double erlaubt. |
| while |
Variables and Data Types
Java is a strongly typed language. The primitive data types are:
| boolean | 1 bit |
== no use with arithmetic expression=={| border=1 cellpadding=2 cellspacing=0 |-
|byte |1 byte | | |-
|char |2 bytes |‘\FA01’ or '\u1F23' |0 bis (2^32)-1\\\\"a" is not a valid literal |-
|double |8 bytes |1.1d | |-
|float |4 bytes |1.14, 4.23E23, 1.4f | |-
|int |4 bytes |0x1c, 0x1C, 0X1c, 034, 28 |2^31 bis (2^31)-1 |-
|long |8 bytes |400000000L,1l, 0xCAFE | |-
|short |2 bytes | |2^15 bis (2^15)-1 |} Ein weiterer impliziter Datentyp ist:
| void |
only for return of a method, even not for an parameter
The size and format and therefore the range of the primitive data types are defined by the language specification and so the language is platform independent. Char is a 16-bit Unicode character. Bei mathematischen Operationen wird automatisch (promotion) in den größten erforderlichen Datentyp gewandelt (widening), aber trotzdem ist gibt bei folgendem Beispiel Datenverlust:
class X
{
void printFloat(float f)
{
System.out.println(f);
}
}
X x = new X();
x.printFloat(12/5); // da beide Werte integers sind, wird nicht gecastet
Das Gegenstück narrowing ist bis auf die Ausnahme der Zuweisung (nicht Methodenaufrufe) eines konstanten int in byte, short or char nur explizit erlaubt. Ein cast eines floats oder doubles auf ein numerischen Typ enthält ergibt den fractional part des floats bzw. doubles. Man kann nicht von boolean auf einen numerischen Typ casten. Implizite casts sind byte -> short -> int -> long -> float -> double. Ein literal value like "23.4" is considered as double. Example(u) zeigt, wie es zu einem impliziten Datenverlust kommen kann.
Konvertierung zwischen Datentypen
Für die Basisdatentypen gibt es sogenannte wrapper classes:
- Spezialisierungen von java.lang.number: Integer, Float,..
- Boolean
- Character
so daß Variablen mit den Objekt-Methoden behandelt werden können wie z.B. in einem Object-Array abgespeichert zu werden. Objekte der wrapper classes sind leider immutable, und eignen sich daher nicht als in-out parameter. In diesem Fall kann man einen Array der Länge 1 verwenden.
Konvertierungen nach char bzw. Character
von int to char: c = (char)i von char to Character: new Character(c)
Konvertierung nach int
von char to int: i = (int)c;
Referenz Datentyp
All other types as arrays, objects or interfaces are references, that is even return values, so be carefully returning objects and check whether you shouldn’t better clone it . There are no structs, pointer or unions. Alle Referenzvariablen also nahezu alle Variablen müssen mit new instanziert werden.
C ObjectOfC; ObjectOfC.DoSomething(); // does not compile because no new ObjectOfC = new C(); // this is correct (don’t forget the parantheses)
Man kann alle Referenzvariablen explizit auf null setzen
ObjectOfC = null;
bzw. auf null abfragen. Local Variables are not automatically initialized with null. Am besten ist der Vergleich von Java Referenzvariablen zu Objekt-Pointern von C++. Dies ist ein enorm wichtiger Punkt. Wenn z.B. ein Objekt eine Referenz auf ein anderes Objekt als Methodenparamter erhält und sich dieses Objekt intern als Referenz merkt betreffen alle Änderungen an dem Objekt zu einem späteren Zeitpunkt natürlich auch Verwendungen innerhalb weiterer Methoden .
Speichert man beispielsweise in einem Array of Superclasses Subclasses und ruft Methoden auf, so geht werden bei derefernzierten Aufrufen über die Array-Elemente die Subclass Methoden aufgerufen, da im allgemeinen Fall alle Member virtuell sind.
You can declare a variable in any scope to be final, including parameters to methods and constructors. The value of a final variable cannot change after it has been initialized.
final int aFinalVar = 0;
By convention variables start with a lowercase letter and classes with an uppercase letter.
Man kann auch quasi anonyme Variablen anlegen, z.B. beim Aufruf einer Methode, die ein Objekt als Parameter hat.
Casts
Man kann immer ein Subclass Objekt auf ein Superclass Objekt ohne expliziten cast casten, die umgekehrte Richtung geht nur mit einem expliziten cast. Geht ein cast schief z.B. weil ein downcast nicht korrekt ist wird eine Exception ausgelöst. Um zu prüfen, ob ein downcast erlaubt ist gibt es den instanceof-Operator der wie folgt eingesetzt wird:
if (<VariableName> instanceof <ClassInterfaceName>)
If <VariableName> == null dann ist es keine Instanz von <ClassInterfaceName>. Der folgende Ausdruck ist ebenfalls legal und liefert true:
if (<VariableName> instanceof Object)
Arrays
Array enthalten entweder:
- basic types
- object references
- array references.
Für alle Typen wird bei der Konstruktion der Defaultwert des Datentyps (null bei objects) eingesetzt. Arrays are declared by
int[] Array1; int Array[];
and constructed by
int[] Array2 = new int[n];
char[] Array3 = {'\u0031','\u0033'};
wobei n vom basic type byte, short oder int sein muß - long geht nicht. Arrays have the standard property length which can be used through
if (Array2.length > 1)
{
...
}
Creating an array of objects only allocates storage for object references, not the object themselves. Elements are initialized to their default value which is 0 for int for instance or null for references .
If you pass an array to an method you would declare the method like this
<return type> <method name>(<type>[(<Space>)*][][(<Space>)*]<parameter name>)
The initialization of an array can be
<Class> <VarName>;
<type>[] <array name> = { [<Varname> = ] <element> {,<element>} };
In this case you don’t have to call new. Another initialization is
<Method>( new <Type>[] { <Element1>, ..., <ElementN> } );
An java array remembers the type of elements. Java arrays are 0-based.
Der java compiler übersetzt allerdings einen Ausdruck wie i = xxx-1;
Arrays can be cast to Object and Clonable, but not to String.
Under some conditions (obviously if the accessed element is actually used) the access of array elements outside the arrays bounds generates an java.lang.ArrayIndexOutOfBoundsException exception . This is the behavior if you compile with the JDK compiler, if you compile within Visual Cafe you get an exception even if you use the JDK JVM, if you compile with the command line compiler sj you won’t get the exception.
If an array is created you cannot change its size. If you need to change the size at runtime and you only want to store subclasses of object you should use the class vector. Der Nachteil von vectors ist, dass es kein typisierter Speicher ist sondern alle Objekt-Subclasses speichert. Dies führt leicht zu Fehlern. Beim Auslesen aus einem vector muss man immer casten.
Enumeration/Iteratoren
Für Iteratoren definiert die Java-Bibliothek zwei unterschiedliche Schnittstellen. Das hat historische Gründe. Die Schnittstelle Enumeration gibt es seit den ersten Java-Tagen; die Schnittstelle Iterator gibt es seit Java 1.2, seit der Collection-API. Der Typ Iterator ist jedoch deutlich weiter verbreitet.
Iterator hasNext() next()
Beiden Schnittstellen ist eine Funktion gemeinsam, die das nächste Element erfragt, und eine Funktion, die ermittelt, ob es überhaupt ein nächstes Element gibt. So wandert der Iterator einen Datengeber (in der Regel eine Datenstruktur) Element für Element ab. Die Namen der Operationen unterscheiden sich in den Schnittstellen ein wenig und sind beim Iterator kürzer. Die Schnittstelle Iterator bietet eine Möglichkeit, die Enumeration nicht bietet. Das zuletzt aufgezählte Element lässt sich aus dem zugrunde liegenden Container mit remove() entfernen. Vor dem Aufruf muss jedoch next() das zu löschende Element als Ergebnis geliefert haben. Eine Enumeration kann die aufgezählte Datenstruktur grundsätzlich nicht verändern. Sie stellt quasi eine Pointer-Liste darstellen und es aus diesem Grund gefährlich ist, die Quelle zu modifizieren, während man interiert. In der Regel löst dies eine ConcurrentModificationException aus.
import java.util.Enumeration; for ( Enumeration e = ds.elements(); e.hasMoreElements(); ) System.out.println( e.nextElement() );
Die Collection liefert mit iterator() einen typisierten Iterator und überträgt somit den generischen Typ der Datenstruktur auf den Iterator.
Bitsets
Hash Tables
Property Sets
Hash Sets
Linked Lists
Queues
Stacks
Multi-Dimensional Array
Vector
The Vector class implements a growable array of objects. Like an array, it contains components that can be accessed using an integer index. However, the size of a Vector can grow or shrink as needed to accommodate adding and removing items after the Vector has been created.
Access Modifiers
access modifier := public | protected | package | private
Wenn keiner angegeben wird ist der Default package.
Packages and Imports
Java allows you to group classes in a collection called package. Just as you have nested subdirectories on your disk, you can organize packages using levels of nesting. To add a file to a package insert the line
package <PackageName>;
to your file. It must be the first line after any comment. Java code that is part of a package has access to all classes (public and non-public) in the package and to all non-private methods and fields in all those classes. Everything in the java.lang package is automatically imported into every Java program. There you do not need to specify a package prefix in front of e.g. the system object. The java.lang packages contains the following parts: Math ... You can import special classes of a package or all classes of a package (s. example (x)), e.g.:
import <Part1>.<PartN>.(*|<ClassName>);
import java.applet.Applet; import java.awt.*; // * is only allowed for a single package // you cannot write import java.*Normally importing all classes in a package is simpler. It has no negative effect on compile time or code size, so there is generally no reason not to do it. Wenn es zwei packages gibt, die eine Klasse mit dem gleichen Namen enthalten, können nicht beide importiert werden, sondern eine muss über den voll qualifizierten Namen verwendet werden. Wenn die Klasse die importiert wurde nicht als *.class file vorliegt, wird sie implizit durch das import statement übersetzt. Kann sie z.B. wegen Syntaxfehlern nicht übersetzt werden, wird auch die importierende Datei nicht übersetzt. All files of a package must be located in a subdirectory that matches the full package name. These subdirectories need not branch off from the root directory; they can branch from any directory in the CLASSPATH environment variable. JVM looks for <CLASSPATH>\<PACKAGENAME_PART1>¬\..\<PACKAGENAME_PARTN>¬\<CLASSNAME>¬.¬CLASS. The files can also be located in a CLASSES.ZIP file with the correct path information. If no package statement is specified the class is thrown into a default package with all other package-less classes and all the non-private members are visible there. In 1.4 you can no longer import a class from the default package. You can only import a class that is in a named package. If your classes are in the default package, you do not need to use the import statement. Otherwise, you will need to package the classes or only use the default package.
Classes
Classes are declared by
[public] [abstract] [final] class <ClassName> extends <BaseClassName>
[implements <InterfaceName>]
{
<Methods>
<Attributes|Fields >
<ctors>
{
static
{
<static initialization>
}
}
}
Class names can be used anywhere primitive data types can be used. Variables have to be defined before using them. Es ist keine Vorwärtsdeklaration innerhalb eines Moduls notwendig.
Final classes cannot be parent classes.
A class with one or more abstract methods must itself be declared abstract.
Inner classes can even be declared private.
The static initialization is something like a ctor for static attributes. It is called when the class is loaded. There can be variables declared in the static initialization block, there can be even multiple static initialization blocks which are concatenated. Der Compiler überprüft, dass in diesen Blöcken nicht fälschlicherweise Variablen vor ihrer Initialisierung verwendet werden. Diese Überprüfung läßt sich leider umgehen, in dem man statische Methoden in diesen Blöcken aufruft, in denen auf nicht initialisierte member zugegriffen wird (24 page 25). Classes declared as abstract can have methods which have an implementation. They can also have static method which can be called anyway.
Attributes bzw. Fields
[public|private|protected] [static|final|transient|volatile] <Type> <MemberName> [ = ...];
Attribute werden manchmal fields oder member genannt. A public member is accessible anywhere the class name is accessible. Private member besagen, dass die nur Methoden dieser Klasse auf sie zugreifen können. A protected member is throughout the package that contains the class in which the field is declared, and is also also accessible (unless shadowed) within the body of any subclass of that class. Variables may be marked transient to indicate to low-level parts of the Java virtual machine that they are not part of the persistent state of an object. The default package visibility (nothing specified) is more restrictive than protected but less restrictive than private. They are only visible by classes in the same package and not even by subclasses of different packages. A variable declared volatile is known to be modified asynchronously. The compiler arranges to use such variables carefully so that unsynchronized accesses to volatile variables are observed in some global total order. This means that variables which are declared volatile are reloaded from and stored to memory at each use, in a way that is coherent throughout a multiprocessor. Static variables or class variables are declared as static. They get unlike local variables a default initialization. Class variables are accessed by <Class¬name>.<Va¬riablename>.
Hidden member
Members can be hidden durch local variables or parameters of the same name or by members of a subclass with the same name. Such collisions can be resolved using ‘super.’ or ‘this.’ or ‘<Classname>.’ or ‘(<Classname>this).’. Something like ‘super.super.’ is not allowed. Im Unterschied zum Overriding von Methoden kann man von außen durch casts auf die hidden member der Basisklassen zugreifen. Ein weiterer Unterschied ist, daß ein statischer member einen nicht statischen member hiden kann.
Methods
[public|private|protected]
[static|abstract|final|native|synchronized]
<Type>|void|<Type>[] <MethodName>() [throws <Exception>{,<Exception}] {...};
Für den Namen der Methode gibt es keine Beschränkung. Er kann auch wie die Klasse heissen und wird vom ctor nur durch den return type unterschieden. Calling a method is called invoking a method of an object or sending a message to an object.
All primitive type parameters are passed by value and all object parameters and arrays are passed by reference. To manipulate parameters you have to use objects or arrays. A method can never change the values of their parameters z.B. die Referenz umhängen, so daß diese Änderung den Methodenaufruf überdauert. Methods that change instance fields are called mutator methods and those that only access instance fields are called accessor methods.
Beim Aufruf einer Methode kann der return value ignoriert werden d.h. man muss den return value im Code keiner Variablen zuweisen:
A.DoSomething(); // der return value von DoSomething() wird ignoriert
There is a this member available in every method. The this member can be used to discriminated between a parameter and an attribute e.g.
void <Operation>(int x) { this.x = x;}
or for ctor calling (see chapter 1.11.11.2.1).
There is also a super member to access members or methods of the super class with
super.<MethodName>(<Parameter>);\\
but it is not possible to call the method an indirect base class.
Static methods or class methods do not operate on objects. You can use them without creating an instance of the object like
<ClassName>.<StaticMethodName>(<Parameter>);
Static methods can not be declared in interfaces, cannot be declared abstract and cannot be overriden (but hidden).
Final methods can not be overwritten, d.h. Methoden in direkten oder indirekten subclasses mit der gleichen Signatur werden vom Compiler abgelehnt. Reasons can be efficiency (inline) and security (you know what you call).
Abstract methods don’t have a body. If there is at least one abstract method the class must also be declared abstract.
A method can be declared native, in which case the method is implemented in a platform-dependent way, for example, in C or assembly language. Because the implimentation is not provided by Java Language code, the method declaration contains no body (a semicolon appears instead of a block). Native methods are otherwise like normal Java methods; they are inherited, may be static or not, may be final or not, may override or be overridden by non-native methods, and so on.
- ctor
[public|private|protected| <ClassName>(<ParameterList>)
{
[this(<ParameterList>);|super(ParameterList);]
<statements>}
If no special ctor is specified and only if no special ctor is specified java will provides one with no arguments and which does nearly nothing (alle member werden mit ihren default values initialisiert und der super.ctor() wird aufgerufen). Wenn mindestens ein ctor spezifiziert wird, generiert der Compiler keinen default ctor mehr. A ctor has no return value and it is not allowed to use the return statement with an argument. The compiler decides depending on the parameters which base class ctor is used. Wenn man fälschlicherweise eine Methode mit gleichem Namen wie die Klasse und einem return type definiert, so handelt es sich um eine normale Methode und nicht um einen ctor.
The base class has to be constructed by a special call in the ctor which has to be the first statement
super(....); // it must be the first line of a ctor
ctors
If an explicit ctor call for the superclass or for another ctor is missing ‘super();’ is inserted implicitly at the first line, so all ctors are chained. If the base class does not have a ctor without an argument this will lead to a compile error. A call super ( ... ); to a superclass constructor, whether it actually appears as an explicit constructor call statement or is implicitly assumed, performs an additional implicit action after a normal return of control from the superclass constructor: all the instance variables that have initializers are initialized at that time. More precisely: for every instance variable declared in the class containing the call, taken in the order in which the instance variables appear in the class declaration: if that variable has an initializer and either the initialization expression is not a constant expression or its value is not the standard default value for the variable, then the initialization expression is executed and its value is assigned to the instance variable. It is a compile-time error for instance variable initializations to have a forward dependency.
Private ctors verhindern, dass eine Klasse angelegt wird (s. Example (w)).
A special ctor feature is the possibility to call a different ctor by
ctor1(a,b,c) { this(new X(), a, b, c); // it must be the first line of a ctor === }
which also must be the first statement in the ctor. A call this(... ); to another constructor in the same class does not perform the mentioned additional implicit action.
Bei ctor design ist generell zu beachten, daß subclasses damit zurechtkommen. Man ruft am besten keine privaten Methoden auf, und schreibt am besten immer auch einen parameterlosen ctor und eine Menge von u.U. private Methoden, die die Einzelschritte implementieren (s. 24 page 26).
- Finalize
Before an object gets garbage-collected, the garbage collector gives the object an opportunity to clean up after itself through a call to the object's finalize method. This process is known as finalization. The finalize method must be declared as follows:
protected void finalize() throws Throwable { <statements>}
Finalize() methods are not chained automatically but have to be chained explicitly.
In einem standard java program finalize is not called for the object with the main method (logisch but Java 1.1 had added a static method called runFinalizerOnExit() in the system class that will guarantee the the finalize method is called before java shuts down. Remember that you do not know when it is called. ===
Objects
The Object class is the top of Java's class hierarchy and the parent of everything even if it is not specified in the extension list (but it can be specified there).
- Initializing an Object\\
Bevor ein ctor aufgerufen wird werden alle numerischen Member mit 0, alle boolschen Member mit false und alle Referenzen mit null initialisiert (lokale Variablen werden im Gegensatz dazu nicht initialisiert), es sei denn in der Klassendefinition sind Defaultwerte (auch für Referenzen) angegeben .
Inner bzw. Nested Classes
Inheritance
public class <ClassName> extends <ClassName>
- Overriding Methods \\
A non-static method defined in a subclass with the same name and paramter list (signature) as a method in one of its ancestors classes overrides the method of the ancestor class from the subclass. Alle Methoden sind virtual. The access modifier of the overriding method must provide at least as much access as the overridden method, which seems a little bit strange. Overriden methods cannot be accessed outside of the class that overrides them.
A method with the same signature but different return types or a static method with a the same signature as one of one of the ancestor classes or a non-static method with the same signature as a static method of one of the ancestor classes generates a compiler error.
If you have an object of class B which extends class A and which overrides f() it is impossible to call f() of A but in methods of B using super.f(). Finding the correct method is called overloading resolution. \\ Final methods cannot be overriden, static methods cannot be overriden but hidden. \\ Abstract methods must be overriden.
Überschriebene synchronized Methoden erben diese Eigenschaft nicht automatisch, sondern müssen ebenfalls als synchronized deklariert werden. Allerdings bleibt die Basisklassen Methode weiterhin synchronisiert.
Static methods are hidden and not overriden e.g.
class Super { static String M() { return "X"; }} class Sub extends Super { static String M() { return "Y"; }}
Super s = new Sub(); System.out.println(s.M()); // will print 'X', because casting to Super is // something like a qualified name It’s no problem to ‘override’ private methods because in reality it is no overriding.
Interfaces
An interface defines a protocol of behavior. A Java interface defines a set of methods but does not implement them. A class that implements the interface agrees to implement all of the methods defined in the interface, thereby agreeing to certain behavior. A class that implements an interface adheres to the protocol defined by that interface. To declare a class that implements an interface, include an implements clause in the class declaration. Your class can implement more than one interface (Java supports multiple interface inheritance), so the implements keyword is followed by a comma-delimited list of the interfaces implemented by the class.
class <ClassName> implements <InterfaceName>,<InterfaceName> { ...}
When a class declares that it implements an interface, it's basically signing a contract to the effect that it will provide at least an empty implementations for all of the methods in the interface .
An interface is defined by
[public] interface <InterfaceName> [extends <SuperInterfaceName> ,<SuperInterfaces>] { <AccessModifier> <ReturnType> <MethodName>(<ParameterList>); ... <AccessModifier> final <Type> <ConstantName> = <Value>; // constants }
Es ist ein Fehler wenn Interfaces sich selbst direkt oder indirekt extenden. A method declaration in an interface body may not include any of the modifiers final, native, static, or synchronized.
Interfaces können Attribute definieren, die aber immer implicit statisch und final sind und explizit initialisiert werden müssen.
Interfaces können auch als Parameter übergeben werden oder als Typ einer lokalen Variablen verwendet werden. Eine andere Verwendung ist folgende:
<InterfaceName> <VariableName> = new <ClassWithInterfaceName>();
Interface with no methods are called marker interfaces, because they mark that the class capable of doing something.
At this point, many programmers wonder how an interface differs from an abstract class. An interface is simply a list of unimplemented, and therefore abstract, methods. Wouldn't the following Sleeper class do the same thing as the Sleeper interface?
abstract class Sleeper { public abstract void wakeUp();}
No. The two are not equivalent. If Sleeper is an abstract class, then all objects that wish to use AlarmClock must be instances of a class inherited from Sleeper. However, many objects that wish to use AlarmClock already have a superclass. For example, the GUIClock is an Applet; it must be an applet to run inside a browser. But Java doesn't support multiple inheritance. So GUIClock can't be both a Sleeper and an Applet. Hence, you use an interface instead. This is the practical explanation of the problem. The conceptual explanation is this: AlarmClock should not force a class relationship on its users. It doesn't matter what their class is. It simply matters that they implement a specific method. Often interfaces are touted as an alternative to multiple class inheritance. While interfaces may solve similar problems, interface and multiple class inheritance are quite different animals, in particular: A class inherits only constants from an interface. A class cannot inherit method implementations from an interface. The interface hierarchy is independent of the class hierarchy. Classes that implement the same interface may or may not be related through the class hierarchy. This is not true for multiple inheritance. Yet, Java does allow multiple interface inheritance. That is, an interface can have multiple superinterfaces. You use an interface to define a protocol of behavior that can be implemented by any class anywhere in the class hierarchy. Interfaces are useful for the following: Capturing similarities between unrelated classes without artificially forcing a class relationship Declaring methods that one or more classes are expected to implement Revealing an object's programming interface without revealing its class. (Objects such as these are called anonymous objects and can be useful when shipping a package of classes to other developers.)
Properties
Java definiert eine Reihe von properties wie z.B. user.home oder java.home. Diese können in Applikationen abgefragt werden, werden andererseits aber auch in den Security Files referenziert und legen fest, welche policy files angezogen werden.