The object-oriented extension Java o of Java c (Java and the Java Virtual Machine ch. 5) PSLab 문세원
1. Static semantics of Java o Definition : Types A, B, C are generated as follows Primitive types are types(see table 3.1) Classes and interfaces are types Null and void are types If A is a type different from Null and void, then A[] is a type
1. Static semantics of Java o Definition : For reference types, the relation ⊆ is the least reflexive and transitive relation satisfying the following conditions If A ⊂ d B, then A ⊆ B. If A is a reference type, then Null ⊆ A and A ⊆ Object A[] ⊆ Cloneable and A[] ⊆ Serializable. If A ⊆ B and A, B are reference types, then A[] ⊆ B[]
1. Static semantics of Java o Example : Although every reference type is a subtype of Object, this is not true for primitive types. Java.lang.Integer ⊆ Object int ⊆ Object (x) Note, that although int is a subtype of long the type array int is not a subtype of array of long. int ⊆ long, but int[] ⊆ long[] is not true.
1.1 Operators for reference types BopOperand typesResult typesOperation +A or B is StringString String concatenation == A ⊆ B or B ⊆ A Boolean Equal (references) != A ⊆ B or B ⊆ A Boolean Not equal (references)
1.2 Syntax of Java o Syntax of Java o Exp :=...| null | this | Exp.Field | super.Field | Exp instanceof Class | (Class) Exp Asgn :=...| Exp.Field = Exp | super.Field = Exp Invk : =...| new Class(Exps) | Exp.Meth(Exps) | super.Meth(Exps)
1.3 Constructor declarations Syntax A(B 1 loc 1, …,B n loc n ) cbody cbody := block | {this(exps); bstm…} | {super(exps); bstm..}
1.3 Constructor declarations Example Class A{ private int x; private int y = 17; static int z = 3; A(int x){ this.x = x; } A(int x){ super(); y = 17; this.x = x; }
1.4 Field access expressions Instance field access expressions are transformed at compile-time into the abstract form exp.C/field Instance fields can be accessed exp.field → exp.C/field super.field → this.C/field field → this.C/field
1.5 Overloaded methods Instance method invocations expressions are transformed at compile-time into the abstract form exp.D/msig(exps) Instance methods can be invoked α ( β exp.meth ν (exps)) → α ( β exp.D/m ν (exps)) α super.meth ν (exps) → α ( β this.D/m ν (exps)) α meth ν (exps) → α ( β this.D/m ν (exps)) first step : Compiler computes a set app(α) next step : A most specific method is selected.
1.5 Overloaded methods Instance method invocations have an additional callKind which is used for method lookup (assume D/m) data Kind = Special | Virtual | Super 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
1.6 Instance creation expressions be treated like ordinary method invocations new C(exps) → (new C).C/msig(exps) Since constructors are not inherited, applicable constructors are always in the same class. The callKind of a constructor invocation is Special
1.7 Type checking of Java o Table 5.2 Type constraints for Java o α nullT(α) = Null α thisT(α) = A, if the position α is in class A α ( β exp intanceof A)T(α) = boolean. A is a reference type. It must be possible that there is a class or array type C with C ⊆ A and C ⊆ T(β) α ((A) β exp)T(α) = A. A is a reference type. It must be possible that there is a class or array type C with C ⊆ A and C ⊆ T(β)
1.7 Type checking of Java o α (exp.C/field)T(α) is the declared type of field in class C α (exp1.C/field = ν exp2)T(α) is the declared type of field in C, field is not final in C, T(ν) ⊆ T(α) α new C.C/msig(exps)T(α) = C. C is a class and C is not abstract. α (exp.C/msig(exps))T(α) is the declared return type of method msig in class or interface C
1.7 Type checking of Java o Table 5.3 Type constraints after introduction of primitive type casts exp 1.C/field = ν exp 2 Let A be the declared type of field in C. If A is primitive, then T(ν) = A exp 0.C/msig ( β1 exp 1,..., βn exp n ) If msig = meth(B 1,…, B n ) and B i is a primitive type, then T(B i ) = B i.
1.8 Vocabulary of Java o The following static functions look up compile- time info. in the environment. instanceFields : class → Powerset(Class/Field) defaultVal : Type → Val type: Class/Field → Type lookup: (Class, Class/Msig) → Class type Val =... | Ref | null data Heap = Object(Class, Map( Class/Field, Val)) heap : Ref → Heap classOf : Ref → Class classOf(ref) = case heap(ref) of Object(c, fields) → c
1.8 Vocabulary of Java o Class A{ private int x; public int y; public static int z; } Class B extends A{ private int x; } instanceFields(B) =[A/x, A/y, B/x] package p; public class A{ String m(){ return “p”;} public String n(){ return this.m();} } package q; public class B extends p.A{ public String m(){ return “q”;} public static void main(String[] _){ B x = new B(); Sytem.out.println(x.n()); } lookup(q.B, p.A/m) → lookup(p.A, p.A/m) → p.A If p.A/m() is declared public, lookup(q.B, p.A/m) → lookup(q.B, p.A/m) → q.B
2. Transition rules for Java o Fig. 5.2 Execution of Java o expressions execJavaExp o = case context(pos) of this → yield(locals(“this”)) new c → if initialized(c) then create ref heap(ref) := Object(c,{(f,defaultVal(type(f))) | f ∈ instanceFields(c)}) yield(ref) else initialize(c)
2. Transition rules for Java o α exp.c/f → pos : = α ► ref.c/f → if ref not null then yieldUp(getField(ref,c/f)) α exp1.c/f = β exp2→ pos : = α ► ref.c/f = β exp → pos : = β α ref.c/f = ► val → if ref not null then setField(ref, c/f, val) yieldUp(val) α exp instanceof c → pos : = α ► ref instanceof c → yieldUp(ref not null ∧ classOf(ref) ⊆ c)
2. Transition rules for Java o (c) α exp → pos : = α (c) ► ref → if ref = null ∨ classOf(ref) ⊆ c then yieldUp(ref) α exp.c/m β (exps) → pos : = α ► ref.c/m β (exps) → pos : = β α ref.c/m ► (vals) → if ref not null then let c´ = case callKind(up(pos)) of Virual → lookup(classOf(ref), c/m) Super → lookup(super(classNm(meth)), c/m) Special → c invokdMethod(up(pos), c´/m, [ref] vals)
2. Transition rules for Java o getField(ref, f) = case heap(ref) of Object(c, fields) → fields(f) setField(ref, f, val) = heap(ref) := Object(c, fields + {(f, val)}) where Object(c, fields) = heap(ref) exitMethod(result)= … elseif methNm(meth) = “ ” ∧ result = Norm then restbody := oldPgm[locals(“this”) / oldPos] …