Is Java partially object-oriented

1 The object-oriented paradigm

Motivation: Objects and the orientation on them
The basis of the object-oriented view is literally the orientation towards the objects. These Objects represent real or imaginary objects (also: concepts or entities) of reality (or what we think they are).
There is nothing fundamentally new about this point of view; people have always applied it spontaneously and intuitively, starting with early childhood, as has been confirmed by recent educational experiments (see Frankfurter Allgemeine Zeitung, Aug. 18, 1999, No. 190, p. N3).

What is new, however, is the transfer of this "natural" worldview to technology, specifically as paradigm on the programming process.


Basic concepts

The object-oriented (abbreviation OO) paradigm does not form a closed, theoretically sound basis (such as the relational theory for relational databases), but only a - and fuzzy - summary of individual principles.

These principles are commonly associated with the terms

occupied. However, depending on the author, this list is supplemented by further terms or some of the specified ones are omitted entirely. In addition, these buzzwords of object orientation are sometimes defined differently.
In the context of the lecture, however, the definitions given below are binding.

Excursus: The concept of Paradigms(see separate handout)


The idea of ​​object orientation is more than 25 years old. Likewise, the first attempts to develop object-oriented programming languages ​​(abbreviation OOP).


Despite the "development ballast" (not to forget the always threatening second system syndrome) has succeeded in creating a small (i.e., basic concepts manageable) but nevertheless powerful language with Java.


The OO paradigm provides a framework for philosophy, but not a guide to technical implementation.
However, it is obvious to completely redefine an OOP, the concrete manifestation of the paradigm, without relying on existing realizations of other paradigms (as was done with C ++) in order to obtain a "purely" object-oriented language.
However, what all OOPs have in common is the underlying paradigm, i.e. the language-independent basic concepts. For a better - and above all OOP-independent - description of object-oriented facts, so-called description languages ​​have emerged over the course of time. They reproduce object-oriented concepts in a language-neutral manner. The graphic description languages ​​are of particular importance because they add clarity and thus easy comprehensibility to the desired abstraction from the concrete syntax. In the following we will consider the Unified Modeling Language (UML), standardized by the Object Management Group (abbr. OMG>).

3.1 Visualization of object-oriented facts with the Unified Modeling Language

While there have been publications on object-oriented programming for 25 years, books on object-oriented analysis and design methods have only existed since the early 1990s.
These include those of Booch, Coad and Yourdan, Rumbaugh et al., Wirfs-Brock and Johnson, Shlaer and Mellor, Martin and Odell, Henderson-Sellers and Firesmith. Many of the methods are not the result of a targeted development, but rather the abstract essence of practically implemented OO projects, primarily in the US industry. An example of this is the Object Modeling Technique (abbreviation OMT) developed in the context of specific projects at General Electric.


The graphic shows some object-oriented modeling methods and their origins.

The aspect of the integration of existing methods in the UML as well as the absorption of competing approaches such as the Object Modeling Language (abbreviation OML) clearly emerges.

Note:
to distinguish between terms method vs. notation:
A method [grch. method "way"] describes a procedure, i.e. a dynamic process that leads to a result under certain input data. In the present case, the question to be solved (the problem) forms the input data, which are mapped into a modeling language using a specific process (the modeling method).
A notation is a graphic description language for the representation of certain (in our case: object-oriented) facts.

The methods and notations of Booch and Rumbaugh, which were developed independently of one another and were very competitive on the market, became the most popular in the early 1990s (measured by the actual degree of use in industrial projects).
The second generation of OO design methods is very much characterized by the attempt to integrate good approaches, which have established themselves as quasi-standards, into competing methods.
While Rumbaugh's OMT is very much based on the classic structured methods for static data modeling through to the design of relational database structures and supports the analysis process in a variety of ways, the Booch method (Object Oriented Design (abbreviation OOD)) covers the areas of commercial, technical and also time-critical applications, especially target language implementation. What is remarkable about the terminology is the relation of the actual activity type - the process of object-oriented design - to the concrete method, which represents a clear break in abstraction.
In terms of content, the two methods do not differ significantly in terms of terminology or the underlying analysis and design method. However, the mainly graphical differences (the notation) led to a real "method controversy" - even from one method was was read.

The trigger for the attempt to unite the different, already increasingly confluent, noations into a single one was a Request for proposals the Object Management Group. For the first time, there was an opportunity for an object-oriented analysis and design standard that creates a uniform concept and notation basis.
The development of the - later - Unified Modeling Language began in 1995 after Jim Rumbaugh switched to Rational Software Corp., where Grady Booch was already active, with the authors' attempt to combine their two methods and notations. The main focus here was the methodical approach within the analysis and design phases. A draft version of the (Grand) Unified Method Version 0.8, which was limited to the purely static modeling, was presented to the public in October 1995. At the OOPSLA conference in '95, the official end of the method dispute was announced in a striking way.
In late autumn of the same year, the two were in their endeavors after taking over the company Objectory supplemented by Rational, by Ivar Jacobson. This opened up the possibility of expanding the modeling language developed with dynamic elements for modeling processes. In particular, those described by Jacobson should Use cases be integrated into the common procedure and notation. The team of authors has since been known in the professional world as the three amigos designated.

In view of the difficulties in combining the various development methods, this was postponed indefinitely in favor of standardizing the graphic elements. Outwardly, this can be seen in the renaming of the Unified Method in Unified Modeling Language.
The declared goal, however, remains the uniformly defined semantics of all graphic elements.


At the beginning of the unification efforts, the authors postulated four application goals for the emerging UML:

  • Enabling the modeling of large systems (not only in the software area) using object-oriented technologies
  • Support of both conceptual and implementation-related constructs
  • Support of large, complex and critical for the company's success (so-called. mission critical) Systems
  • Creating a modeling language that can be understood by both humans and machines

For this purpose, the UML comprises three basic elements:

  • model elements: Basic modeling concepts described in the metamodel (this does not mean modeling methods, but conceptual elements such as class and their semantics)
  • notation: graphic description of the model elements
  • Guidelines: Modeling rules, the syntax of the modeling language

The result, the modeling language, should meet the following requirements, among others:

  1. Easily usable, expressive modeling language for exchanging high-quality models
  2. Starting points for semantics-compliant expansions of the basic concepts (e.g. Stereotypes)
  3. Language and development process independence
  4. Formal basis for understanding the modeling language
  5. Support of the OO tool market
  6. Support for high-level development concepts such as frameworks, patterns and component-based development
  7. Integration of the best existing approaches (so-called. best practices)

This makes it clear that the UML was developed and designed for a much broader range of applications for the system description than will be used in this lecture.
Our main focus is on the implementation-related use for the documentation of the programming language Java code.

3.2 Object-oriented concepts in the Java programming language

The Java source code is made up of various elements:

  • Identifier or identifier
  • Keywords (so-called. Terminals)
  • Literals
  • Operators
  • delimiter

The grammar of the Java language is defined from these elements, which a source program must comply with (i.e. it must be recognized as being syntactically correct) in order to be able to be translated and executed.
The programming language itself is - as usual in logic - as Object language regarding a Metalanguagewhich formally describes the syntactic conditions. The metalanguage itself is a language again. The notation is an extension of the known Backus-Naur-Notation (abbreviation EBNF) used.

The metalanguage is defined as follows:

is defined by
(in the example: y is defined by x)
Selection, selection from equivalent alternatives
(in the example: a or b)
Optionality
(in the example: x can occur zero or once)
quantity
(in the example: x can occur any number of times, including zero times)
keyword
(in the example: x must appear in the source code as specified (a distinction is also made between upper and lower case))
Brackets are used to combine partial expressions

Note:
The characters [] are part of both the meta and the object language. If the usage is possibly confusing, this will be pointed out separately.

3.2.1 The concept of class

semantics:
A class is the description of a set of objects that share the same attributes, operations, methods, relationships and semantics1 share.
A class defines the data structure of an object, but there are also classes from which no objects can be created - so-called. abstract classes; they mainly serve as structuring agents to reduce complexity in connection with inheritance.
synonym: Type (not completely congruent, but often used synonymously)

Graphic notation in UML:


Representation of a class in UML.
The class name is shown in bold.
It has become common practice to indicate class names in the usual spelling, i.e. starting with a capital letter.


Abstract classes are represented in the same way as "normal" ones.
The class name is shown in bold italic type. Alternatively, the notation described above can be used, but supplemented by the designation in curly brackets below the class name. This variant is suitable for handwritten drawings and in environments that do not support italic writing.


Two more can optionally be placed below the rectangle for the class name. The first is used to record the attributes and the second to specify the operations.

Java syntax:
The class definition is introduced by the keyword. This is followed by the class name; each class has a system-wide unique name.
It defines certain characteristics of the class. First of all, whether it is an instantiable class, i.e. whether objects can be created from it, or otherwise a abstract class by specifying the corresponding keyword. defines a class as generally visible, also for other program units. The definition becomes interesting with regard to inheritance, there it defines that the class declared in this way is the end of an inheritance hierarchy (so-called leaf node). By default, a class is considered. The optional specification of the super class is also inheritance-related.
The interface declaration specifies which interfaces are implemented by the class.

Important:
Java is case-sensitive, which means that a distinction is made between upper and lower case. This can lead to confusion due to supposed ambiguity, especially with identifiers, which is why a consistent naming convention is advisable.

Examples:

3.2.2 The concept of Object

Semantics:
An object is the concrete expression of a class. A class serves like one template for object creation. For all attributes with minimum multiplicity 1, each object of this class always contains a value.
Synonyms: Instance (mistranslation of the English instance), Expression

Graphic representation in UML:


Objects are represented in a similar way to classes. They are also symbolized by labeled rectangles. However, instead of the class name, they have the underlined designation of the specific expression. A colon can be placed in front of the object name for better differentiation. This variant abbreviates the full specification, consisting of the object name and class name separated by a colon. Here, too, all components are underlined.


The mechanism known from the class display is also used to visualize the actual value assignment of the specific expression. The set values ​​are noted directly after the relevant attribute after an equal sign.
Between the objects and the generating class, a directed edge (graphically represented by a broken arrow) with the inscription enclosed in angle brackets ("instance of") - a UML stereotype that concretizes the relationship shown - can be added.

Java syntax:
The object is generated dynamically in the Java program flow and generally has the following structure:

Note:
That was already defined when discussing the attribute.
The same applies here: both that and the round brackets are part of the object language, not the metalanguage.

3.2.3 The concept of Attribute

Semantics:
An attribute is a named storage space. slot) in a class that describes a set of valid value assignments within the objects.
The quantities of valid value assignments are saved as Type of attribute labeled and shown in the model.
In the normal case, i.e. unless otherwise specified, the specific value of an attribute can vary from object to object as well as over time. Since no two objects refer to the same storage space with regard to an attribute, value changes within an attribute do not affect other attributes of the same type. If this is explicitly desired, i.e. all objects have their own attribute, but they share the underlying storage space (so-called. Class attribute) this must be defined explicitly.
It must also be explicitly specified that an attribute should be treated as an unchangeable constant after initialization.
Each attribute can also have a Visibility specification restricted access.
Derived attributes (engl. derived attributesStrictly speaking, they do not necessarily represent "real" attributes with regard to the allocated storage space. They are usually calculated dynamically from existing data at runtime using methods. However, its information content, which can be derived from other information (e.g. because of its calculation effort), can also be kept redundant. In this case, additional effort must be provided for the necessary synchronization of output data and derived data.
Synonym: Member variable.

Graphic representation in UML:


Each attribute is shown as a separate line in the second rectangle of the class symbol. Each attribute is given a name that is unique for this class, i.e. there are no two attributes with the same name within a class.
Each attribute must have a type. This is specified after the class name - separated by a colon.
In front of the attribute name, the so-called. Multiplicity be entered. It describes the multiplicity of the attribute. Specifically, this means that an attribute can contain several characteristics of a type (so-called. set-valued attributes). The two interval limits can have any positive integer values, but subject to the following restrictions:

In addition, a default value can optionally be specified with which the attribute is automatically assigned by the system at the time the object is created (the so-called. initial value). The general rule is: Attributes are defined immediately after the object has been created (i.e. the necessary storage space is provided), but still provided with a value (initialized). Access before the value is set results in an error.
The visibility (engl. visiblity), which is noted symbolically in front of the attribute name, specifies how program units outside the current class are allowed to access this attribute. Here (in the symbol:) specifies that only objects of this class are allowed to access the attribute. Similarly, (in the symbol:) defines an access option for any object. (), on the other hand, has the same effect in connection with inheritance as with any other object. However, this attribute is visible and accessible in all subclasses of the defining class as well as via type-correct references. If nothing is specified, the default value is used.
An attribute can also be of the type; this should (initially) be defined as the possibility that an attribute can also contain an entire object as a value.
Class attributes are indicated by underlining. Constant attributes get the Property valuefrozen after in curly brackets.
For the sake of clarity, it is common practice to start attribute names with lowercase letters. In addition, Boolean attributes are often introduced with an "is ...".
Derived attributes are indicated by a leading slash (). In addition, the calculation formula should be specified as a property value (in curly brackets).

Java syntax:
Attributes are in body specified in the class declaration.
For constants the FieldModifier set to, i.e. the mandatory value that is also specified is set when it is generated and can then no longer be changed during the entire runtime.
"Normal", i.e. commonly used definitions, completely dispense with this, which means that it is set as the default value and the attribute is declared as changeable at any time.
The specification of only gains in the interaction of several simultaneously active program parts (so-called. Threads) in importance; In doing so, it specifies that a variable can be accessed simultaneously (i.e. unsynchronized) by several threads with write access.
With, the compiler is instructed to allocate the same memory space for this attribute to all objects that have this attribute - it is therefore a class attribute.
Derived attributes can only be converted directly into a Java attribute if a conscious decision was made in favor of redundant storage. Otherwise they are usually implemented as methods.

All classes defined by the user are also permitted as data types.

Note:
The is the character string not an empty optional specification. [] are part of the object language, not the metalanguage. Likewise that as part of the meta-symbol.
is any - according to the type restriction - valid default value.

Example:
The following Java equivalent corresponds to the UML class diagram shown above:

Note:
Contrary to the order in the UML representation, in Java the data type is shown first and then the attribute name. The multiplicity of an attribute is determined using so-called Vectors (also English: Arrays) shown.

The Java programming language offers the following primary data types as standard:

Unicode 0 - Unicode 216-1

The explicit non-type void is naturally not available for defining attributes. In addition, it should be noted that Java does not support unsigned types.
The Wrapper types encapsulate the primitive types in corresponding objects, i.e. every instance of a wrapper type is an object; For a more detailed discussion of the distinction between objects and values, please refer to the section on objects.

In-depth study: options for implementing derived attributes


The UML class diagram shows a class with a derived attribute whose information can be calculated from the attribute of the same class. The calculation formula for the extraction of is given as a guarantee in curly brackets. In addition - according to our convention - a get and a set method for setting or reading out the respective attribute value are specified.
The following alternatives are available for Java implementation:
a) Conversion of the derived attribute into a "normal" attribute. In addition, the calculation formula must be executed every time the independent attribute is accessed (in our example).
b) No implementation of the derived attribute, only programming of the specified access methods. The access methods implement the specified formula in the case of reading out or the inversion in the case of writing access. For the user of this class, the public interface (represented by the public methods) remains unchanged.

Implementation as a "real" attribute

Please note: In all methods that write to the derived attribute or its output attributes, additional effort must be provided for maintaining consistency. Specifically, in all set methods of the independent attributes involved, the calculation formula must be implemented in accordance with the specification in the UML class diagram. While the inversion of the specified calculation formula must be implemented in the writing method of the dependent attribute (better: should).
Note: It is not always possible to clearly indicate the inversion of the calculation formula to obtain the derived attribute. Example: (with ,, whole numbers) it is clearly from and, but not and from the specification of a calculable (concrete numerical example: with, but also:, or, or).

In general, it makes more sense, and is less prone to errors, not to convert to an attribute. According to our convention, all attributes are not directly accessible to third parties, i.e. they are defined with the visibility type or. All access to the internal attributes of a class is handled using special write and read operations.
It is therefore possible to dispense with the reservation of a separate storage space for derived attributes, since their information can also be made available dynamically at any time from the existing ones.

Implementation as a pure method implementation

Please note: A set method for derived attributes such as should generally be avoided, since the necessary inversion of the calculation formula does not always clearly exist. Specifically, it does this if and only if the calculation formula is a bijective mapping between the input values ​​and the calculated value.

As a result, the following can be stated: For the respective application context, the frequency of read versus write access to the derived and independent attributes must be considered.
If the independent input values ​​of the derived attribute are changed frequently and the derived attribute is converted into a "real" attribute, this also results in changes to the derived attribute that consume computing time. However, read accesses to the derived attribute take place without loss of time. This variant is particularly suitable for frequent reading out of the derived attribute with preferably seldom changes in value.
If, on the other hand, the derived attribute is only read out comparatively seldom, its value can also be recalculated every time - with negligible loss of time. This method is characterized by its storage space economy. In addition, no effort has to be made for updating the dependent attribute when the value of the input values ​​changes.

3.2.4 The concept of (Object) identity

Identity is a property that distinguishes one object from all others. However, this property is not codified in the form of an attribute.
This term is often confused with addressability, equality of attributes, or a unique name or key.
However, such keys are only suitable to a limited extent for identifying an object, because the identity of an object generally does not depend on its attributes. Names can change; different objects can have the same name (at least temporarily).
In order to avoid the problem of the inadequate suitability of attribute values ​​- or combinations thereof - for unambiguous identification, artificial keys (so-called. Surrogate key) that have no content-related relationship to the properties of the objects and do not change their value over time.
Typically, this object identifier is object identifier (OID)) generated transparently by the system and neither visible nor accessible to the user.

Java syntax:
In Java, the OID is generated and controlled by the system. There is neither the need nor the possibility of user intervention.

Example:

Result / output:


The two objects of the type are unequal despite identical value initialization.
The same applies to the two integer numbers that were generated from the wrapper type um. Although it is intuitively surprising at first, the two objects - although provided with the same internal value - are different. However, the operation defined on the class, just like the expected interpretation, delivers value equality

Objects vs. values:

Characteristics must be created explicitly
Characteristics made available by the system
more complex handling for primitive operations
easier handling for primary operations

3.2.5 The concepts Message, operation and method

Semantics: The necessary inter- and intra-object communication takes place at runtime by means of so-called. news (engl. messages), which are exchanged among objects.
Specifically, this conceptual model is implemented by calling operations on the respective object. This means that an object interacts with another (but also with itself) by calling the operation.
A method implements an operation and thereby represents the dynamic behavior available to the class. Operations are made by specifying their signature specified in the lower rectangle of the class display. A signature consists of the name of the operation and its input and output parameters (also: Return values) together.
Analogous to the attributes, an operation has a visibility with the same definition and semantics. An operation can also be used as a Class operation To be defined. Based on the semantics of the static class attribute, this operation can be carried out on the class itself - without the simultaneous existence of an associated object.
Synonym: Service.

In principle, the signature of an operation can be specified as desired, with two exceptions: the Constructor and the Destructor.
Definition: A constructor is an operation that is automatically called by this class when an object is created.
Definition: A destructur is an operation that is automatically called when an object is destroyed.
Annotation: If there is no explicit constructor or destructor, a Default constructor or. -destructor called which essentially takes over the (expected) tasks (i.e., memory allocation when an object is created, or its release when it is destroyed).

Graphic representation in UML:


Operations are shown in the lower rectangle of the class definition. The same syntactic rules apply to the symbolization of visibility as to attributes. The operation is clearly named after the visibility symbol. Input parameters are introduced by their data type and shown in brackets. The optional return value is only specified by its type after a colon. Due to the limitation of the return parameters to exactly one, it is not possible to specify multiple returns after the colon. For this purpose, the input parameters can be modified accordingly (this also reflects the usual procedure in the programming language implementation). Each input parameter can optionally be preceded by a, or a mixed form; depending on whether the parameters in the operation are only read, only written or changed based on the input.
Constructors and destructors are treated graphically like "normal" operations.
Class operations are indicated by underlining in the same way as the class attributes.

Java syntax:
The constructor is necessarily an operation on the name of the class; i.e. signature: without (!) (explicit) return value. An explicit constructor call on a created object is not possible.
Note: Constructors do not have an explicit return value (not even!) But, by definition, implicitly return the created object.
Constructors should - if object creation is allowed - be of the visibility type or. In the case of, an object could never be created, except through an already existing object (contradiction!) - therefore the Java compiler rejects the translation with private constructors. If a class is a child class, the constructor of the parent class is executed before the actual child class constructor is executed. In general, the following sequence of execution applies when creating objects:
1. Calling the constructor of the parent class
2. Initialization of the attributes using default values
3. Execution of the constructor

The destructur is the analogue of the constructor at the end of the object life cycle. If an object is destroyed, i.e. the allocated storage space is released, a specially defined method can be executed.
Just like the cascaded constructor call, the destructurecall is first executed on any parent classes and then on the class to be destroyed itself. The (mandatory) syntax of a structure is:. Typically, destructors are implemented using at least one of the following methods:. This ensures that not only the current object but also the parent class instances are properly deleted.

Java also allows the overwriting of a method in subclasses to be explicitly forbidden by specifying the keyword before the operation declaration. The same applies to the specification of the same keyword within the class declaration for the entire class.

Note:
The opening and closing parentheses in the expression are part of the Java syntax and are part of the object language and not of the metalanguage.


example (Implementation of the UML class diagram in Java):


Example: (ConstructorTest.java)

Output of the program:

Annotation: The manual call of the garbage collectors is absolutely necessary in this example, we will deal with the topic in more detail when looking at memory management.

Interaction between objects:

Graphic representation in UML:
The dynamic exchange of messages between runtime objects can be made possible by the UML diagram type of the Sequence diagrams (engl. sequence diagram) can be mapped.
Objects are represented by broken vertical lines. The symbol of the interacting component (typically an object) is displayed above it.
Messages are shown as horizontal arrows between the object lines. The message and any response that may have been received will appear on them in the form message (argument) written down.
The superimposition of the dashed lifelines by wide, unfilled vertical bars symbolizes the Tax focus. It indicates which objects are active at the time in question.


Call by Reference vs. Call by Value - Reference Types in Java

The parameter values ​​are passed in methods in Java Transfer of value (engl. call by value). This means that the values ​​of parameter variables in a method are copies of the values ​​specified by the caller.
It follows from this: a method can internally change the transferred values ​​locally, but this change is not propagated to the value-providing (calling) environment.
In order to get changing access from the method to the calling environment, the parameter must be saved as Reference type be handed over.

Example:

The operation could be called as follows:

What is the value?
According to the previously presented result, the transfer parameter is not overwritten with the addition result, as desired, but the initial value is retained.
The result is calculated internally in the operation, but is discarded after leaving the method.

In order to be able to change parameters passed in the method and to return them changed, the formal parameter for reference be passed - this facial expression is accordingly called call by reference designated.
Example:

Output of the program:
before: 1
after: 2

3.2.6 Packaging

Semantics:
The pacting - the grouping of classes too Packages (engl. package) Strictly speaking, it is not an element of the object-oriented paradigm, but a further development of the various concepts for modularization that exist in the area of ​​classic structured programming languages.
By our definition, a package is a collection of classes. By forming more highly aggregated units, an overall model is broken down into smaller, more manageable units.
Another important aspect is the involuntary similarity of names of individual classes in larger projects and the resulting conflicts. Each package is its own Namespace, i.e. a unit of closed terms. From a technical point of view, in addition to the class name, the name of the surrounding (i.e. containing) package (and of course the names of the packages surrounding this package ...) is used for the clear identification - and determination of any name conflicts. The resulting Path expressions fully characterize any class by exploring its location in the package hierarchy. E.g. a class that is defined in a package that is contained in a package is referred to as.
Each class is defined in a maximum of one package (the home package), but can be referenced from any package. If a class is not contained in any package (i.e. if the associated source code file does not contain a package declaration), it is automatically assigned to an unnamed package.
On the system side, the package hierarchy is implemented by a corresponding file system catalog hierarchy.
In order to get unambiguous package names on the Internet, it has become common practice (without a compulsory syntactic background) to proceed similarly to URLs, but with the difference to interpret them from right to left. For example, a package that was created at the Augsburg University of Applied Sciences would be identified as follows:.

Graphic representation in UML:


Packages are represented in the UML as stylized hanging folders.
The indicated tab at the top contains the unique name of the package.
The following predefined dependency relationships can be explained between packages. In addition to the reference relationship (UML stereotype), there is also the import relationship (which completely includes the independent package (= tip of the directed dependency relationship) in the dependent one (= output of the dependency relationship).

Classes contained in a package and other packages can be displayed within the lower rectangle.

Java syntax:
A maximum of one package can be defined per Java source code file. A package can contain classes and interface declarations. The package definition must be in the first line of code (previous comment lines may be ignored) the source text file; i.e. before any class or interface definition. The package definition applies to all subsequent Java declarations; i.e. all classes and interfaces written after a package declaration belong to the specified package.
The import of classes from a package is done with the keyword followed by the full name of the class or an asterisk (*) for all classes in this package.

If other packages are to be imported into a package, the package is first declared, then the desired imports are carried out.
Elements declared in a package are only visible and accessible outside of this package if they are marked with the visibility restriction.

All definitions following a package statement are interpreted as belonging to this package; i.e. a package can be opened explicitly, but not closed!
By default, the Java runtime system imports three packages: the empty default package, the package (which is why the wrapper types and simple complex types (such as) defined therein can also be addressed without an explicit import), and the package to which the main class is assigned (this may be . also nameless).
Note: The simple text output method is not defined in a package, but is a class in which there is a class variable whose type the method supports.

If the classes of a package are divided into different source code files, then all source code files of the package together to be translated. This is done by passing several files to the Java compiler. Example:.
In memory of: If several classes of a package are to be accessible from the outside, the division into several source code files is inevitable, since Java only allows exactly one declared class per file!

Example:
Definition of a package P1 within a package P2 Import of class C1 from package P1 that is contained in package P2:

Import of all classes of package P3:

3.2.7 The concept of the Polymorphism

Semantics:
Under Polymorphism (Greek: diversity) is understood (for us) as being able to define elements of the same name (= objects, classes, variables, operations, attributes) in different areas of validity.
We want to understand (initially) the scope of validity as the directly comprehensive program unit.
For example, the directly encompassing unit is the containing class for an attribute, as is the operations defined on this class. For the classes themselves, the package in which the class is defined (not imported!) Forms the surrounding unit. Further packages can be defined within a package hierarchy, with each package forming its own area of ​​validity.

The implementation of the concept of polymorphism in the Java programming language ensures the possibility of defining and differentiating elements of the same name in different areas of validity.
Note: In the case of operations, as is known, it is not the name of the operation alone that counts as an identifying feature, but the entire signature.

3.2.8 The concept of Inheritance

Semantics:
Inheritance Inheritance is a concept that allows further specifications to be made on the basis of existing information. Mostly it is between one Upper class (also: Supertype, Great guy, Super great, Parent class) and one Subclass (analogous also: Subtype, Subtype, Subclass, Child class) defines a relationship. These Inheritance relationship This relation defines the transfer of the superclass structure (attributes and operations) to the subclass.
This mimicry of structural propagation is called Inheritance designated. The subclass inherits from the super class.
If a class inherits from several classes (i.e. it owns several superclasses) this is with the term Multiple inheritance (engl. multiple inheritance) occupied. Otherwise (exactly one super class) the term simple inheritance second hand.
Every attribute, like every operation of the superclass, is automatically defined by the inheritance relationship in the subclass. This means that the method implemented in the superclass can also appear polymorphically as the dynamic behavior of the subclasses.
If an attribute with the same name or an operation with the same signature is explicitly specified in a subclass, the inherited definition becomes overwritten (engl. overriding).

Graphic representation in UML:


In UML, the inheritance relationship between classes is represented as a directed, with a hollow arrow, edge starting from the inheriting class (the subclass) to the inheriting class (the superclass).
Optionally, the reason for inheritance - the so-called. Discriminator as a property value (in curly brackets) on the edge. This facial expression is shown on the right in the figure (the abstract class is inherited by the subclasses and.
By convention, only structural components defined directly in the class, i.e. not inherited - unless they are overwritten - are shown in UML.
The class model at the bottom right illustrates a typical situation in which multiple inheritance occurs.

Problems with multiple inheritance:

The graphic illustrates a typical problem situation that inevitably occurs with multiple inheritance (sooner or later): the so-called deadly diamond of death (also: diamond inheritance). The phenomenon is characterized by the fact that the source of inherited characteristics (i.e. the attribute or operation inheriting superclass) cannot be clearly identified. In the example, in addition to the attribute defined there, the class would also contain the attribute inherited from and the inherited from.
and in turn inherit from the attribute. The problem described results from this. Actually, the subclass should inherit both from and the attributes defined there and inherited there. This leads to a double definition of which is inherited via the inheritance path C1-> C2-> C4 as well as C1-> C3-> C4.
To do this, the object-oriented paradigm would have to allow several attributes of the same name and type (identical entries in the UML attribute area of ​​the UML class representation) - which it does not!

Because of this problem, the programming language supports Java no multiple inheritance!

Java syntax:
If an operation is overwritten in an inheriting class, the operation of the parent class with the same signature is no longer accessed by default, but if this behavior is explicitly desired, this can be forced with the keyword. Example: calls the superclass with the same name in an operation. If the superclass constructor is called before the current class, this call must be specified as the first statement in an overwritten method

Declaration Syntax: The Concept of Class.
The optional shown there allows the specification of a maximum of one parent class for each user-defined class.
The body statement is as follows: class name parent class name

In Java, every class that does not have an explicit parent class is implicitly derived from the class. This ensures that any application object can be converted to.
If there is an explicit parent class, this overwrites the default inheritance.
The Java compiler implements this facial expression during the bytecode generation. This means: it is not the runtime system that accepts all non-derived classes as the parent class, but rather the compiler changes the transferred source code accordingly before it is compiled. This reduces the implementation effort of the virtual machine, since parts of the standard behavior are shifted to the explicit language level.

Example:
The default inheritance for classes without an explicitly specified parent class is easy to check with the Java diassembler (known from Chapter I).
Call:
The diassembler provides the following output for the HelloWorld program:

Annotation: The specification of the transfer parameters shows the declaration of the string as an element of the package which is imported by default. In addition, it can be seen from the definition that the selected name of the transfer parameter (in our examples mostly or no role plays a role. Only the operation name and the types of transfer and return parameters are used to form the signature.

In addition to the implicit type conversion by the runtime system when a subtype instance is transferred to a program unit (operation or attribute) that expects a supertype instance, the required conversion can also be carried out by the programmer.
Java provides an explicit procedure for this.

In general, it should be noted that only types that are linked to one another in an inheritance hierarchy (regardless of whether there is a sub-super or super-sub relationship) can be converted into one another.
As safe conversion the type extension always possible according to the LSP applies. widening or casting up). Here an object of a subclass is placed instead of one of the superclass; this conversion is always permissible and does not require any further examination.
However, it is more problematic in the opposite case; the attempt to convert a superclass expression into a more specialized subclass expression. Important information may be missing here (specifically: the extension of the subclass compared to the superclass).

Java syntax:
The instruction:

Converts an object (read: an object of any type), if possible according to the type restriction, into an expression of the. In case of impossibility, one is triggered.
If a conversion is generally not possible (see the following example), the Java compiler already refuses the translation.

Example:
The translation of the following source code is rejected due to the obvious impossibility of type conversion by the compiler:

The Class affiliation of an object (or a reference to an object) can be determined,

To Determination of the class membership of an object the programming language Java offers the instanceOf operator at.

Java syntax:

Where is the name of a defined object, and the name of an existing class.
The operation returns the truth value as the result if the object to be checked belongs to the specified class or to one of the superclasses.
The possibility of a type conversion is thus implicitly checked. This is also the most common use of the InstanceOf operator.

Example: (Source code file: InstanceOfTest.java)

Example: (InheritanceTest.java)


Result / output:
The call of the inherited operation transparently executes the method of the same name implemented in the (inheriting) parent fund.

In-depth study: Liskov's substitution principle (abbr.LSP)

Although Java, like other available object-oriented programming languages, offers the option of inheritance, the programming language does not define any further restrictions on its use. In concrete terms, this means that unclean inheritance with the aim of - conveniently - reducing the amount of writing required is technically possible.
What is desired, however, is a catchy formulation for the (correct) formation of subtypes; this is provided by Barbara Liskov in 1988[2] Postulated substitution principle:

definition (after Liskov): If for each object or similar1 of a type S an object or similar2 of a type T exists, so that for all programs P the behavior of P after substitution of o1 by o2 is unchanged, then S is a subtype of T.
Alternatively (and more simply): Then (and only then) a class is a (meaningful) subclass of another if there can be an object of the subclass at every point in the program where an expression of the superclass is expected (see example).

example (File name: LSPTest.java)

Output of the program:

First of all, an object of the parent class is transparently generated by the runtime system during the (specifically: before) generation of an object of the class, without the programmer having to do anything (cf. outputs of the two constructors).
Another woman object is created in the same way, but it is assigned to an attribute of the type. In the implementation of the LSP, the specialized expression of the class derived from person is also accepted here.
Then the operation inherited from person to woman is called in the main method. The result is the first zero.
The implementation of Liskov's substitution principle in Java (i.e. the assumption of its semantics in the type formation) becomes clear from the following lines of code: The operation which is defined on the main class. It expects an object of the class (synonym: of the type) as the transfer parameter (called). However, an object of the specialized subclass is transferred to the operation in the example program. Nevertheless, this object is considered valid (according to Liskov's type restriction).

3.2.9 The concept of relationship

Semantics:
As a relation between classes, a relationship describes the common semantics and structure of a set of object connections.
Synonym: Association.

Graphic representation in UML:


The figure shows the visualization of a relationship between classes. So far, too, we have (implicitly) operated with relationships. Each attribute has a relationship to the class it contains, and vice versa, each class has a relationship to the encapsulated attributes.
What is new is the relationship on the class level shown in the graphic, which is specifically entered at runtime between two objects of the participating classes (or their subclasses).
Structurally, a relationship consists of the following components:

  • at least two classes involved
    This is why this relationship type is also two-digit or binary Called relationship.
  • the named relationship itself (shown as an undirected edge).
    The relationship name is noted in the middle of the edge in italic font.
  • The roles of the classes involved.
    These are presented as text to the role-playing class
  • The multiplicity of these roles.
    These are offered at the end of the relationship to the class to which the role played relates.

The same syntactic rules apply to the multiplicities as in the known application at the attribute level.

For our further application, however, this undirected bidirectional relationship type does not play a major role. Rather, we will focus on the programming language implementation more directed Specialize in one-way relationships.
The representation in UML is slightly modified compared to the known for bidirectional relationships:


As the figure shows, it is easily possible to convert one bidirectional relationship into two unidirectional ones without any loss of information.
To express the reading direction, an open arrow is noted at the end of the relationship edge. The rules for specifying the role and multiplicity remain unchanged.

Java syntax:
The Java programming language does not provide an explicit language construct for defining a relationship between objects.
However, the necessary semantics can be simulated with the object reference. It is only necessary to orientate yourself towards the specified multiplicities:
0..1 The relationship is represented by exactly one reference attribute of the target class type. This attribute can be empty in some objects.
1..1 The relationship is represented by exactly one reference attribute of the target class type. Appropriate operations must be used to ensure that the quantity is never empty. This attribute must not be empty in any object. This must be ensured by suitable operations that guarantee consistency.
1..* The relationship is represented by exactly one quantity-valued attribute. The type of this attribute should be specified as (see), since the multiple definition of identical relationships between identical objects rarely makes sense.
0..* The relationship is represented by exactly one quantity-valued attribute. This set can be empty. The type of this attribute should be specified as (see), since the multiple definition of identical relationships between identical objects rarely makes sense.
m..n The relationship is represented by exactly one quantity-valued attribute. A suitable operation must ensure that at least but at most elements are always included in the set.

UML diagram of a 0 .. * relationship:


Implementation of a 0 .. * relationship:
(File original classBez1.java)

UML diagram of a 1 .. * relationship:


Implementation of a 1 .. * relationship:

UML diagram of a 0..1 relationship:


Implementation of a 0..1 relationship:

UML diagram of a 1..1 relationship:


Implementation of a 1..1 relationship:


Implementation of a m..n relationship (Here the case of a 2..5 relationship)