org.vishia.java2C
Class Docu.E_Inner_classes

java.lang.Object
  extended by org.vishia.java2C.Docu.E_Inner_classes
Enclosing class:
Docu

public class Docu.E_Inner_classes
extends java.lang.Object

This chapter describes details of translation of inner classes. Inner classes are a essential element of programming. There are seven types:


Constructor Summary
Docu.E_Inner_classes()
           
 
Method Summary
 void e1_anonymousClasses()
          Anonymous classes are a special construct of Java.
 void fieldIdentsOfOuterClassAndSiblings()
          The knowledge of field-identifiers and types of the outer classes and the sibling- inner classes in inner classes and the knowledge of this one of the super classes in the derived classes is necessary.
 void firstPassOfInnerClasses()
          The first pass of the inner classes are running while the first pass of the enclosing class is processed.
 void typeIdentsOfOuterClassAndSiblings()
          The types of the outer class are registered for the inner class running ClassData.completeTypesForInnerClasses() at the end of the first stage of the first pass of the outer class.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

Docu.E_Inner_classes

public Docu.E_Inner_classes()
Method Detail

e1_anonymousClasses

public void e1_anonymousClasses()
Anonymous classes are a special construct of Java. They are written like:
 static RefType name = new BaseType(param){
   //classBody of enhancing.
 };
 
The RefType may be a super- or interface-Type of BaseType or typical the same as BaseType. With this type the anoymous class is used.

The BaseType is the direct super type of the defined instance.

The classBody for enhancing may be overwrite some methods of the BaseType and can contain some variables or inner classes etc. too, all what a class can be have. But it isn't possible to access other than the methods, which are overridden. Only the overridden methods are visible in the RefType.

The constructor which is used is the adequate constructor of the BaseType. The classBody for enhancing may define variable which can be initialized, but an extra constructor is not possible to write.

The methods of the classBody for enhancing can access especially all elements from the outer class, if this class is non-static, without the shown static-keyword. Then a portal for example from an interface to the outer class through the anonymous class is given. This is the most interisting aspect of inner anonymous classes. They implements methods of the interface or overrides methods, but the methods are seperated from the outer class. Not the outer class plays the role of the interface-implementer, but only the anonymous class. That makes the implementing better supervise-able, respectively it allows the usage of method names, which may be in coflicting with other interface implementations. Therefore it is an important concept for programming.

Such an anonymous class can be used whenever a new instance can be created. The anonymous class is bound only to the new Type(param){ }. The suggestion, the declared variable is related immediate to the anonymous class is false. The variable is only the reference to the instance of the anonymous class. A creation of an anonymous class-instance can also be done as part of an expression. If the anonymous class is defined inside a statement block, it is equal to definition it as normal inner class at class level. It means the variables of the outer class body can be accessed, but not the variables of the enclosing statement block.

Translation of inner anoymous classes

The inner anonymous class is translated in its first pass when the new-expression is evaluated. This is inside GenerateClass.createFieldDataNewObject(org.vishia.zbnf.ZbnfParseResultItem, org.vishia.zbnf.ZbnfParseResultItem, LocalIdents, LocalIdents, StatementBlock, String, ClassData, char, char, char, boolean) There the method GenerateClass.gen_AnonymousClass(org.vishia.zbnf.ZbnfParseResultItem, org.vishia.zbnf.ZbnfParseResultItem, LocalIdents, StatementBlock, String, char, GenerateFile) is called. Inside that, the FirstPass#runFirstPassClass(GenerateFile, String, String, String, String, org.vishia.zbnf.ZbnfParseResultItem, String, ClassData, java.util.List, boolean, ClassData) is called with an own instance of FirstPass and the ClassData of the anonymous type are produced.

The Definition of the struct of the inner class is placed in the header file in the same way as for all other innerClasses, if the inner class can be used from outside. The Definition of the struct is placed in the C-file, if the anonymous inner class is detected in the second pass only. But it is placed before the code of the current second path, by using the iWriteContent.writeCdefs(StringBuilder)-method, which writes to GenerateFile.uFileCDefinitions buffer. This is placed before the adequate GenerateFile.uFileCSecondPath for the bodies. The definition of anonymous classes in bodies of methods are never direct access-able outside, only via its base classes. So it shouldn't be defined in Headerfiles. But they are able to reference from outside. Therefore, the reflection information is able to use unconditionally.

A adequate contruct of a
 { //inside method body
   struct { data x; } stackVariable;
 
which may be usual in C, it is not used in Java2C-translated codes.The machine code effort is not lesser which such an construct against the extra definition of the struct with a internal-build-name und use it with its name. But the representation of a extra definition is better. It is necessary for reflection and others. The anonymous class in Java has more capability as the anonymous struct in C like shown above.

The constructor in an anonymous class is a overridden form of one of the constructors from the BaseType, selected by the actual parameters. It is overridden, because the own local variables should be intialized too.

The anonymous classes are named in C. The name is built with a C_NameOfVariableSuffixOuterClass for all anonymous classes of variable initialization. if a new(..){...} outside of an variable is translated, then CNr_NameOfMethodSuffixOuterClass is used to build the name, where Nr is the current number of anonymous class in the method, started with 1 and mostly 1. This names mustn't be used as class-names by the user for other elements. But there are specialized so that isn't suggest to do so.


firstPassOfInnerClasses

public void firstPassOfInnerClasses()
The first pass of the inner classes are running while the first pass of the enclosing class is processed. The inner classes are processed first, because there content may be known while the first pass of the outer class runs. At all events the ClassData of the inner classes may necessary to know, the ClassData are created as result of running its first pass.

On the other hand, all elements of the outer class are used only in the second pass of the inner class. Inside the firstPass of the inner class, only types of other inner classes may be necessary to know. TODO test complex constructs.


fieldIdentsOfOuterClassAndSiblings

public void fieldIdentsOfOuterClassAndSiblings()
The knowledge of field-identifiers and types of the outer classes and the sibling- inner classes in inner classes and the knowledge of this one of the super classes in the derived classes is necessary. But additionally the field-idents should be designated as outer or super ones. That designation is contained in the fields FieldData.nClassLevel and FieldData.nOuterLevel. See Docu.E_Inner_classes The field-identifier of the outer class are registered for the inner class running ClassData.completeFieldIdentsForInnerClasses() at the end of the first pass. That is necessary because all idents are known only at the end of the first pass of the outer class, but the first pass of the inner class is finished already, without knowledge of the outer idents. All idents should be known while running the second pass only.

The method ClassData#completeFieldIdentsFromOuterClass(LocalIdents) is called unlike if a class is generated in the second pass inside a block statement. In this case the first pass of this class is running only in the second pass of the environment.

The situation of same identifier in the outer and inner class is detected in that complete-methods. The inner identifier covers the outer one.


typeIdentsOfOuterClassAndSiblings

public void typeIdentsOfOuterClassAndSiblings()
The types of the outer class are registered for the inner class running ClassData.completeTypesForInnerClasses() at the end of the first stage of the first pass of the outer class. This is done after calling FirstPass.buildType(StringBuilder, String, GenerateFile, String, String, String, String, org.vishia.zbnf.ZbnfParseResultItem, boolean, String, ClassData, java.util.List, boolean, ClassData, char) in the GenerateFile.runFirstPassFile(org.vishia.zbnf.ZbnfParseResultItem, String, String, String) -routine respectively in ReadStructure.postPrepare(org.vishia.java2C.ReadStructure.ZbnfToplevel) for creation of ClassData from the stc-file. That is necessary because all types are known only at the end of the first stage of the first pass of the outer class, but the first passes of the inner classes are finished already, without knowledge of the outer idents. All idents should be known while running the second stage of first pass (FirstPass.runFirstPass2(StringBuilder)) and the second pass only.

For anonymous inner classes the types of the outer class are copied always in the GenerateClass.gen_AnonymousClass(org.vishia.zbnf.ZbnfParseResultItem, org.vishia.zbnf.ZbnfParseResultItem, LocalIdents, StatementBlock, String, char, GenerateFile) -routine after processing the FirstPass.buildType(StringBuilder, String, GenerateFile, String, String, String, String, org.vishia.zbnf.ZbnfParseResultItem, boolean, String, ClassData, java.util.List, boolean, ClassData, char) of the anonymous class. In that time all types are known already, because the first stage of the outer class is running already and all types except the anonymous are known.

The ClassData of the anonymous classes shouldn't be known as types, because there are anonymous. It pertains to all class-level anonymous class and statement-block anonymous classes.

The ClassData of statement-block-level classes shouldn't be known as types, because there are visible only at that statement-block level.