the true nature of static. administrivia wed (mar 30): q3 next mon (apr 4): p2 rollout

31
The True Nature of static

Post on 22-Dec-2015

214 views

Category:

Documents


0 download

TRANSCRIPT

The True Nature of static

Administrivia•Wed (Mar 30): Q3

•Next Mon (Apr 4): P2 Rollout

Design tip o’ the day•Orthogonality: isolation of functionality

into simple, non-interacting, complete, universal set of methods

•Simple: each method does a small thing

•Non-interacting: each method affects only its target state, and no other state (no extraneous side effects)

•Complete: all methods, taken together, offer all necessary functionality

•Universal: method is supported for every class (when it makes sense)

Design tip o’ the day•Simple:

•get, put, size, iterator

•Room parseRoom(Lexer)

•double TFIDF(Set)

•boolean evaluate(VarState)

•Not simple:

•putAndGetIterator, sortBackward

•World parseEverything(String fname)

•[double,[] Set] retrievePagesAndScore(String q)

•boolean parseAndEval(VarStrings)

Design tip o’ the day•Non-interacting:

•setDay, setHour, setMin

•JTextArea.setText

•Interacting:

•setTimeAndUpdateViews

Design tip o’ the day•Complete:

•put, get, size, iterator

•Undercomplete:

•put, iterator

•Overcomplete:

•put, add, append, addAndSort

•size, length, nElements

•size, get(int idx), sublist(int start, int end)

•Note: Overcomplete is often useful, but be wary of needless cruft

Design tip o’ the day•Universal:

•java.util: get, put, add, size, iterator

•javax.swing: add, addActionListener, get*, set*, paint

•Non-universal:

•getMyFavoriteIteratorThingy

•addToMiddleOfList

•numElements

E1 Q6 Answers•Question: Design an AndOrLexer that only

constructs _tab once in spite of it being declared protected, non-static in AbstractTableLexer

•Most people had some semi-reasonable idea

•3 basic types of answers

3rd best designpublic class AndOrLexer extends

AbstractTableLexer {public AndOrLexer(Reader in,_LexAct[][] t) {

super(in);_tab=t;

}// other AndOrLexer methods

}

// elsewhereAndOrLexer._LexAct[][] t=new _LexAct...for (...) { // set up t }for (i=0;i<1000;++i) {

Lexer l=new AndOrLexer(in,t);while (l.hasNext()) { ... }

}

Critique of 3rd best•Achieves goal of design

•AndOrLexer’s table only created/initialized once

•Requires external visibility of _LexAct

•Marked protected in AbstractTableLexer

•Exposes internal implementation of Lexer

•Disassociates key class functionality (construction) from the class itself

•Note that construction of table defines the functionality of the lexer

•Requires special-purpose arg to constructor (or accessor) -- less orthogonal

2nd best designpublic class AndOrLexer extends

AbstractTableLexer {private static _LexAct[][] singleTab;private static boolean beenSet=false;public AndOrLexer(Reader in) {

super(in);if (beenSet) {

_tab=singleTab;}else {

buildTable();_tab=singleTab;beenSet=true;

}}

Critique of 2nd best•Does the right thing

•Does not expose internal implementation to outer world

•Just a little awkward

•Needs extra boolean; special test on each construction

•Have to double-check logic

•Java provides a language mechanism to do exactly what you want...

Best designpublic class AndOrLexer extends ... {

private static _LexAct[][] singleTab;static {

// do complete allocation and initialization// of singleTab here

}public AndOrLexer(Reader in) {

super(in);_tab=singleTab;

}// other AndOrLexer methods here...

}

The Truth about Static

The common view•The 251-level view of static:

•“If a member is declared static, then there’s only one of that member for the whole program”

•E.g.,public class SDemo0 {

private int x;private static int y;

}

•Each SDemo0 object has its own x member, but there’s only a single y member for whole program

Problem w/ basic view•static actually has (at least) 4 diff

contexts in Java

•member variables

•methods

•initialization blocks

•inner classes

•(synchronization blocks)

Down the garden pathpublic static class SingleTable {

private _LexAct[][] _sTab;public SingleTable() {

// allocate and initialize _sTab}public _LexAct get(int state,char c) { ... }

}

public class AndOrLexer extends ... {public AndOrLexer(Reader in) {

super(in);_tab=new SingleTable();

}}

Now that we’re in 351...•More accurate picture:

•static means “associated with the class” rather than “associated with the object”

•In practice, same result for member fields

•Makes big diff in other cases

•E.g., can’t have a static top-level class b/c there’s no outer class for it to be associated with...

The static picture, take 1

Implementation of static•For access to static and non-static

members

•In principle:public SDemo0 s=new SDemo0();System.out.println(s.x);System.out.println(s.y);

•Means:System.out.println(s.x);System.out.println(s.classptr.y);

•In reality:System.out.println(s.x);System.out.println(SDemo0Ptr.y);

Static methods•Simple view: A static method can only

access static member variables (and other static methods)

•Better view: A static method is one associated with the class object, not the instance object

The static picture, take 2

Static mthd accesses this context

Non-static accesses this...

Static method callspublic class SDemo1 {

private int x;private static int y;public int getSum() { return x+y; }public static int getSq() { return y*y; }

}

• translated to:public class SDemo1 {

private int x;private int y (stored in SDemo1 class struct)public int getSum(SDemo1 this) {

return this.x+SDemo1Ptr.y;}public static int getSq(SDemo1 SDemo1Ptr) {

return SDemo1Ptr.y*SDemo1Ptr.y; } }

Static initialization•B/c static member is assoc w/ class and

not object, you don’t want to re-initialize it every time you create a new object

•Don’t initialize static things in constructor!

•Java provides “static initialization blocks”:static int y=3;static {

// do some complex stuff here}

•Can have >1 static init block, but they get merged

Static initialization•Axiom: static things associated with class

•Corollary 1: static things initialized when class is loaded

•Corollary 2: static initialization happens only once per program

•In principle: first time you reference a class

•When possible, JVM optimizes and runs all static initializers for all known classes before running main()

•Sometimes, has to defer to actual class load (e.g., for deserialization

Best designpublic class AndOrLexer extends ... {

private static _LexAct[][] singleTab;static {

// do complete allocation and initialization// of singleTab here

}public AndOrLexer(Reader in) {

super(in);_tab=singleTab;

}// other AndOrLexer methods here...

}

Static inner classes•Recall our picture of “basic” inner classes:

• _Iter._accessCount==_Iter.outer._accessCount

Static inner•A static inner class (w/ a name) is basically

just like any other class, but defined in scope of its parent class

•Unlike basic inner class, though, it does not have a hidden pointer to its outer object

•Can be “free floating”

•Can create one w/o an instance of its outer class

•Can’t do direct access to outer class’s members

•Can do direct access to its outer class’s static members (why?)

Map.Entry examplepublic class MondoHashMap implements Map {

// stuff...private static class _MHMEntry implements

Entry {private Object _key;private Object _value;public Object getKey() { return _key; }public Object getVal() { return _value; }public int bogus() {

return size(); // error Will Robinson!}

}}

Map.Entry translationpublic class MondoHashMap implements Map {

// stuff...private static class _MHMEntry implements

Entry {private Object _key;private Object _value;public Object getKey(_MHMEntry this) {

return this._key; }public Object getVal(_MHMEntry this) {

return this._value; }public int bogus(_MHMEntry this) {

return this.size();// error Will Robinson!

}}

}

Coolness of static inner•Usefulness of static inner classes:

•Don’t have an extraneous pointer that you won’t use

•Can save a lot of space (e.g., for big Maps)

•Provides better conceptual separation

•_MHMEntry isn’t an element of MondoHashMap; MHM just uses it to store stuff

•Won’t accidentally muck w/ outer class

•Bogusness:

•static is a rotten name for the distinction they’re making... :-P