Why is metaprogramming not used often



Metaprogramming, what is it?


A higher level (meta) is implemented above "normal" programming (with types, control structures, objects, methods, etc.).


Metaprogramming is the discipline of writing programs that represent or manipulate other programs or yourself.

Other features

  • In many cases the target programs are created or supplemented by metaprograms (term: generative programming).
  • Often stencils as a template for the generation.
  • Partly own language (metalanguage) for metaprograms.
  • Special case reflection:
    • Metaprograms in the same language as the target programs.
    • The language's abstraction mechanisms are also used for the meta information (classes, objects, methods ...)
    • Preservation of the basic structure of a program.

Metaprogramming and Java

"Built-in" support from

  • Language constructs
  • JVM and classloader
  • APIs

The standard mechanisms available

  • Introspection: Providing information about a program structure.
  • Reflection: Dynamic program structure changes: classes, data access and method calls.
  • Annotations: Providing additional declarative information in the code.
  • Generics: Parameterization of types.


The role of the meta-objects


  • (Meta) information about elementary data types, arrays and classes are also available at runtime: Introspection.
  • They are provided by the JVM in the form of instances of classes from the Reflection API: Meta objects.
  • They can also be used for dynamic access: Reflection (see below)

Essential components

  1. The classes of the package,

    especially the classes


The influence of generics on the Reflection API is excluded here (see below).

The most important classes and objects

The central class (1)


  • For each class there is an instance of the class that contains or references all class information (ditto for interfaces, simple data types, arrays,).
    I. E. each Java type is represented in the JVM by an object.
  • This object is instantiated by the.
  • It is obtained from an instance of the represented class with the method (inherited from the class.
  • Alternatively, the object is available as the value of the constant.


The following methods provide basic information about the class and its integration into the class hierarchy:

  • ,
  • // if the class is a member of another class

The central class (2)

Example: source code generation by reflection

The central class (3)

other methods

  • The method can be used to determine the class loader that loaded the class.
    If the standard class loader was used, it is returned.
  • The members contained in the class (constructors, methods, fields, inner classes) or the modifiers of the class can be fetched using methods.
  • The objects for individual members can also be picked up specifically based on name or signature, e.g. B.
  • Additional methods in the class are used for dynamic class loading and instantiation (see below).

The remaining metaclasses

The class

Each method of a class corresponds to an instance of this class (generated by the JVM) with

  • Information methods about the declaring class and the components of the signature
  • A method for calling the represented method (see below).

The class

  • Each field of a class corresponds to an instance of this class (generated by the JVM).
  • It contains methods for reading and setting a member value for a transferred object that has the corresponding field.

The class

Each constructor of a class corresponds to an instance of this class (generated by the JVM)

  • Information methods about the declaring class and the components of the signature,
  • a method for instantiating a new object with this constructor (see below).

The class

  • Modifiers for classes and members are managed as constants.
  • The class contains static constants and static methods for interpreting these int values.

The class

This class contains static methods for the dynamic creation of arbitrary arrays, as well as for setting and reading out field values.

Dynamic class loading

The principle

  • Classes can be loaded based on the class name and then instantiated.
  • The class name does not even need to be known when the instantiating code is compiled.

The relevant methods in the class

  • The method locates, loads and binds the class instance to the passed class name.
    (throws if necessary)
  • The method creates a new instance of a given class that has a default constructor.
    (throws if necessary or)

Example: dynamic class loading


Dynamic method call



  1. Both the class and the method to be called (and their parameters) can be specified at runtime.
  2. Analogous to the dyn. Method call can be a constructor call (for others as a default constructor).

Why introspection and reflection at all?

The Reflection API is immensely important in the context of

  • various frameworks,
  • Serialization,
  • Beans,
  • RMI
  • etc.


Annotations: the bottom line


  • Additional meta information that does not belong to the actual logic of the program.
  • Declarative character: name and possibly attributes


  • Can be placed in front of different program elements: class, method, attribute, ...
  • Own syntax: ...


  • at compile time or before
  • at runtime

A couple of fields of application

  • Compiler control
  • Unit testing: definition of test methods, etc.
  • especially frameworks in the enterprise area, e.g. B. Mapping of objects to database content

Predefined annotations

The guys


    through the compiler


    User-defined annotations (1)

    The usage

    User-defined annotations (2)

    The associated definitions

    User-defined annotations (3)

    Meta annotations (1)

    Intended use

    Annotation of annotation definitions

    The guys

    • Inclusion of the marked annotation in the JavaDoc of the annotated element

    • Marked annotation should be inherited.

    • Specifies the element (s) to which the annotation can be attached (default: all):

    • Defines how long annotations are to be retained (default:):

    Meta annotations (2)


    Processing of annotations

    Reflection API

    for reading out with RetentionPolicy RUNTIME



    Generics: the bottom line


    • Type parameterization of interfaces, classes and independent methods
    • Avoid code duplication: only one source and byte code per family of parameterized elements
    • Ensure type safety (at compile time).


    • Affected interfaces, classes and independent methods receive one (or more) when defining formal type parameters (Syntax, e.g .:)
    • When used, a current parameter is used for the formal parameter (syntax, e.g .:).
    • At the byte code level, the parameterization is resolved by using the class: Type erasure!


    • Container classes (Collection API, see below)
    • generic algorithms (e.g. sorting of ...)
    • and much more m.

    Example: Generic Class (1)

    The definition

    The usage

    Example: Generic Class (2)

    Realization in byte code (after decompilation)

    The Diamond

    For example

    The mechanism

    • The current type when the constructor is called can be determined by the compiler from the context (type inference).
    • That saves paperwork.
    • since Java 7.


    Example: Stand-alone generic methods

    The definition

    The usage

    Generics Roots and Boundaries


    • Example: mainly templates in C ++ (see also C #)
    • Generics were only introduced with Java 5.
    • Hence a partially "superimposed" construct.
    • This has certain consequences.


    • Current type parameters can only be of an object type, not a primitive type (but see autoboxing).
    • A formal type parameter of a class must not be used when defining static variables.
    • No instance can be created from a formal type parameter (via new).
    • It is not possible to create an array object (per new) whose component type is a formal parameter.
    • An array or an array reference with components of the type of a formally or currently parameterized class cannot be generated (unless the parameter is of the unbounded wildcard type?
    • A formal type parameter must not appear as an operand in the operator.

    Limitations: examples

    Generics and Inheritance

    Pattern for allowed derivations

    analog: interfaces


    • A derivation situation (and the associated polymorphism) for current type parameters is not carried over to the classes parameterized as a result.
    • Example:
      is not a base class of, so no upcast is possible.

    Wildcards (1)

    Unbounded wildcards

    • As a type parameter of a reference variable to hold references to any current parameterized generic classes.
    • When creating arrays with parameterized components (see above)

    Wildcards (2)

    Upperbound wildcards

    • Only one class below a fixed class is possible as the current type parameter.
    • The formal parameter can be cast implicitly on this base class.
    • With type erasure, the base class is (not) used for the formal type parameter.
    more complex example

    where a class and, ..., are interfaces.

    Wildcards (3)

    Lowerbound wildcards

    Pattern for restricting a method parameter

    meaningful uses

    see Collection API

    Generics and Reflection (1)

    The influences on the metaclass Class

    • The class Class is parameterized:.
    • The class literal returns the exact type.
    • and only returns a type currently parameterized by wildcard.


    Generics and Reflection (2)

    What survives with type erasure?

    An example: