Static semantics of JavaO - JVM

The return type of a method can be a class or interface, too.

De_nition. Types A, B, C are generated as follows:

  1. Primitive types are types (see Table below).
  2. Classes and interfaces are types.
  3. Null and void are types.
  4. If A is a type di_erent from Null and void, then A[ ] is a type.

The type Null is not allowed to appear explicitly in a program. The type void can only be used as a return type of a method. The type A[ ] is called array of A. Reference types are class types, interface types, array types and the type Null. The default value for all reference types is the constant null.

The subtype relation _ of Def.above is extended to reference types.

De_nition For reference types, the relation _ is the least reexive and transitive relation satisfying the following conditions:

  1. If A _d B, then A _ B.
  2. If A is a reference type, then Null _ A and A _ Object.
  3. A[ ] _ Cloneable and A[ ] _ Serializable.
  4. If A _ B and A, B are reference types, then A[ ] _ B[

Binary operators for references

Binary operators for references

Null is the least reference type and Object is the top element. For classes and interfaces A, B the following is true:

A _ B () A _h B or B = Object:

In terms of the JLS, the relation A _ B for reference types means that there is an identity conversion or a widening reference conversion from A to B.

Example: Although every reference type is a subtype of Object, this is not true for primitive types. For example, int is not considered as a subtype of Object, i.e., int 6_ Object. There exists, however, a standard class Integer which is a subtype of Object, java:lang:Integer _ Object:

Note, that although int is a subtype of long the type array of int is not a subtype of array of long, i.e., we have int _ long, but int[ ] 6_ long[ ].

Operators for reference types

The binary operators +, == and != can be applied to arguments of reference type. The type of the result is indicated in Table below. Note, that to test whether two strings s1 and s2 are equal one has to use s1:equals(s2) and not s1 == s2.

Syntax of JavaO

The syntax of the object-oriented sublanguage JavaO of Java is given in Fig. below. Expressions with this or super are allowed in the following contexts only:

  1. in the body of an instance method,
  2. in the initializer of an instance _eld,
  3. in the body of a constructor.

Expressions with super are not allowed to appear in the class Object.

Syntax of JavaO

Syntax of JavaO

Constructor declarations

A constructor declaration in a class A has the following syntax:

hpublic j protected j privateiA(B1 loc1; : : : ;Bn locn) cbody

The name of the constructor is the simple name of the class, in our case A.

A constructor declaration has no return type. Constructors are not inherited and, therefore, cannot be overridden. Several constructors with di_erent signatures may be de_ned in the same class. The body of a constructor has the following grammar:
cbody := block j fthis(exps); bstm : : :g j fsuper(exps); bstm : : :g

The _rst statement of the constructor body can be an explicit constructor invocation of a constructor of the same class or of a constructor of the direct superclass:

  1. this(exps); [constructor of the same class]
  2. super(exps); [constructor of the direct superclass]

An explicit constructor invocation statement may not refer to any instance variables or instance methods declared in the class or any superclass, or use this or super in any expression. It is not allowed that there is a cycle through explicit constructor invocations.

The compiler does the following:

  1. If cbody does not begin with an explicit constructor invocation, then the constructor invocation `super();' is inserted.
  2. The instance variable initializers of class A are inserted in textual order as assignments immediately after the explicit invocation of a superclass constructor.
  3. If the class A does not have a constructor, then the following default constructor is inserted:

The default constructor is public, if the class A is public. The default constructor of the class Object is: Object() fg. The object-oriented extension JavaO of JavaC

Example (; CD) 5.1.2. Consider the following class A:

The compiler replaces the constructor A(int) by the following code:

The static _eld A=z is initialized when the class A is initialized, not when a constructor is invoked.

Field access expressions

Instance _eld access expressions are transformed at compile-time into the abstract form exp:C=_eld, where _eld is an instance _eld declared in class C.

Instance _elds can be accessed in three di_erent ways:

  1. exp:_eld
  2. super:_eld
  3. _eld

Assume that the expressions are in class A. Then they are transformed in the following way:

  1. Let B be the type of exp in the expression exp:_eld. Then _eld denotes an instance _eld of B or of one of B's superclasses. The expression exp:_eld is replaced by exp:C=_eld, if the class C is unique with the property that C=_eld is visible in B and accessible from A with respect to B (Def. below), and if _eld is not static in C. If there exists no such class C, a syntax error occurs.
  2. An expression super:_eld in class A denotes an instance _eld of the direct superclass B of A or of one of B's superclasses. The expression super:_eld is replaced by this:C=_eld, if the class C is unique with the property that C=_eld is visible in B and accessible from A (Def. below), and if _eld is not static in C.
  3. If a simple expression _eld in class A is not in the scope of a local variable declaration or formal parameter with the same name, then it denotes a _eld of A or of one of A's superclasses. The simple expression _eld is replaced by the expression this:C=_eld, if the class C is unique with the property that C=_eld is visible in A, and if _eld is not static in C.

The simple _eld access expression _eld must be in a context where this is allowed.

The type of an abstract _eld access expression exp:C=_eld is the declared type of _eld in class C (see Table below).

Overloaded methods

As a result of the parsing and elaboration phase instance method invocations are attributed as speci_ed in [18, x15.11.1{3]. They are transformed at compile-time into the abstract form exp:D=msig(exps), where msig is a method signature of an instance method declared in class or interface D.

Instance method invocations have an additional callKind which is used for method lookup.

data Kind = Virtual j Special j Super

The invocation kind Static is not needed here, since it is already handled by class methods. Instance methods can be invoked in three di_erent ways:

  1. _(_exp:meth(exps))
  2. _super:meth(exps)
  3. _meth(exps)

Assume that _ is in class A and that (exps) is (_1exp1; : : : ; _n expn). Let msig be the method signature meth(T (_1); : : : ; T (_n)). In a _rst step the compiler computes a set app(_) of applicable and accessible methods as follows:

  • Let C = T (_). Then app(_) is the set of all D=m such that

a) C=msig is more speci_c than D=m,
b) D=m is visible in C and accessible from A with respect to C,
c) if D is an interface, then C does not implement m.1

  • Let C be the direct superclass of A, i.e., A _d C. Then app(_) is the set of all methods D=m such that

a) C=msig is more speci_c than D=m,
b) D=m is visible in C and accessible from A,
c) if D is an interface, then C does not implement m.

  • Let app(_) be the set of all methods D=m such that

a) A=msig is more speci_c than D=m,
b) D=m is visible in A, 1 The last condition is not contained in the JLS [18, x15.11]. In [19, x15.12.2.2] the problem is solved in a slightly more general way.
c) if D is an interface, then A does not implement m.

In a next step a most speci_c method is selected, if there exists one, and an invocation mode is determined. Assume that app(_) contains a most speci_c element D=m. Assume that m is not static in D. Then D=m is the method chosen by the compiler and the invocation mode is determined as follows:

  • The method invocation expression is replaced by

_(_exp:D=m(exps)):
If the method m is private in D, then callKind(_) = Special , otherwise callKind(_) = Virtual.

  • The method invocation expression is replaced by

_(_this:D=m(exps)):
The invocation mode is callKind(_) = Super. In this case it is not allowed that m is abstract in D.

  • The method invocation expression is replaced by _(_this:D=m(exps)):

If the method m is private in D, then callKind(_) = Special , otherwise callKind(_) = Virtual.

The method chosen during compile-time determines the type of a method invocation expression: T (_) is the return type of method m in D (see Table below). The compile-time information associated with the method invocation is later used at run-time. If the invocation mode is { Special , overriding is not allowed and the instance method m in class D is called directly { Virtual, then the instance method m is looked up dynamically starting at the class of the target reference { Super, the instance method m in class D is called directly Example (; CD) 5.1.3. In the following example the method A=m(int) is applicable at the method invocation m(i) in the method test in class B.

The method I=m(int) is not applicable, because it is implemented by B.

Example (; CD) . In the body of method test in the following class A, the JDK 1.2 compiler accepts the _rst two invocations of m(x) and rejects the third one as ambiguous. In all three cases, however, both methods I=m(J) and J=m(I) are applicable, hence all three method invocations are ambiguous.

If we use abstract classes instead of interfaces, then the JDK 1.2 compiler correctly reports all three method invocations as ambiguous.

Instance creation expressions

Instance creation expressions are treated like ordinary method invocations.

An instance creation expression new C(exps) is transformed at compile-time into the abstract form (new C):C=msig(exps);

where msig is a signature of a constructor of class C with name <init>. The abstract expression new C creates a new reference to an instance of class C which is the target reference of the invoked constructor. Since constructors

Type constraints for JavaO

Type constraints for JavaO

Type constraints after introduction of primitive type casts

Type constraints after introduction of primitive type casts

are not inherited, applicable constructors are always in the same class. The callKind of a constructor invocation is Special .

Type checking of JavaO

The type constraints for JavaO are listed in Table below. Some casts can be proven incorrect at compile-time; such casts result in a compile-time error. Consider a cast expression `(A) exp'. Assume that exp has type B. At runtime the value of exp will belong to a class or array type C _ B. The cast will be allowed at run-time only if C _ A. Hence, if the compiler is able to prove that there exists no class or array type C such that C _ A and C _ B, the cast is not allowed.


All rights reserved © 2018 Wisdom IT Services India Pvt. Ltd DMCA.com Protection Status

JVM Topics