190 likes | 307 Vues
Exploring the different contexts of static in Java, covering fields, methods, and nested classes, along with the true definition, consequences, and subtleties of static in programming.
E N D
Administrivia • Example of good documentation on class web page now (under P1 bullet point) • Not perfect, but very good • Includes my critique on how could be made stronger • Check it out...
Reminder • P3 starts next week • Pick teams now! • First phase is design phase -- plan to meet early! (First afternoon, if possible)
Many faces of static • Java seems to have (at least) 3 different contexts for static: • Data members: private static int x=3; • Methods: public static double mogrify(int a); • Inner (nested) classes: private static class _myInner { // ... }
A myriad of meanings... • Each context seems to have its own meaning • static fields: only one of that variable per program; not one per object • static methods: call by class name; can only touch static fields • static nested classes: nested class can’t access its parent class’s non-static fields
A myriad of meanings... • Each context seems to have its own meaning • static fields: only one of that variable per program; not one per object • static methods: call by class name; can only touch static fields • static nested classes: nested class can’t access its parent class’s non-static fields • Really just one meaning!
The true meaning of static • The real definition of static: • “A thing marked static is attached to the entire class, not to any specific object of that class.” • Corollary 1: Can get to a static thing without an instance of an object • System.out.println() -- you never have an instance of class System! • Corollary 2: Static things can only touch other static things • public static getS() { return _myStaticF; }
Consequences... • All 3 meanings of static are consequences of the One True definition • Fields: static data items attached to whole class; not specific object can be only one per class can be only one per program (Java main() thread) • Methods: Attached to class, not objects can’t access object-specific things can only access classwide things (i.e., other static members) • Nested classes: Not glued to a specific parent object can’t access parent’s non-static members
static fields public class foo { public foo(int a) { _a=a; } public int getA() { return _a; } public static int getX() { return _x; } private int _a; private static int _x=37; } foo fA=new foo(3), fB=new foo(7), fC=new foo(-9); class foo fB fA _a: 7 _a: 3 fC _a: -9 _x: 37
Nice pix, but how does that happen? fC._a heap (dynamic mem) fA._a fB._a memory “data” (static mem) foo._x
Nice pix, but how does that happen? fC.getA() fC._a heap (dynamic mem) fA._a fB._a memory “data” (static mem) foo._x
Nice pix, but how does that happen? fC.getA() { return _a; } fC.getA(this) { this._a; } fC._a heap (dynamic mem) fA._a fB._a memory “data” (static mem) foo._x
Nice pix, but how does that happen? fC.getA() { return _a; } fC.getA(this) { this._a; } fC._a heap (dynamic mem) fA._a fB._a memory fC.getX() { return _x; } “data” (static mem) foo._x
Nice pix, but how does that happen? fC.getA() { return _a; } fC.getA(this) { this._a; } fC._a heap (dynamic mem) fA._a fB._a memory fC.getX() { return _x; } fC.getX() { return fooPtr._x; } “data” (static mem) foo._x
static and “this” • Result: static things don’t need a “this” pointer. • A static data item can be dereferenced at compile time -- the compiler knows where it lives & provides appropriate “fooPtr” pointer. • A static member function isn’t linked to a specific instance -- doesn’t get a this pointer • static member fn can’t access non-static data
static data subtleties • Unexpected corollary: • static accesses are assigned at compile time, not runtime • Compiler uses declared type of instance, not runtime type to figure out where var/method lives • static members don’t override the same way as non-static • Consequence: always best to access static vars/methods through class name, not member var -- avoids confusion
Overriding (hiding) static methods public class foo { public void printMe() { System.out.println("Hi, I'm a foo"); } public static void sPrintMe() { System.out.println("Hi, I'm a foo, from a static context"); } } public class bar extends foo { public void printMe() { System.out.println("Hi, I'm a bar"); } public static void sPrintMe() { System.out.println("Hi, I'm a bar, from a static context"); } } public static void main(String[] args) { foo f1=new foo(); bar b1=new bar(); foo f2=new bar(); f1.printMe(); f1.sPrintMe(); b1.printMe(); b1.sPrintMe(); f2.printMe(); f2.sPrintMe(); }
What about static nested classes? • Same idea applies: • Instances of a static nested class aren’t associated with (“glued to”) a particular instance of their enclosing class • Essentially, static nested classes work a lot like top-level classes -- they pay homage to no class • Non-static inner classes are glued to a specific instance • Corollary: if B is inner to A, you have to have an A instance available to create a B
Static nested classes public class MyOuter { public class myInnerA {} public static class myInnerB {} } MyOuter v1=new MyOuter(); myInnerA v2=v1.new myInnerA(); myInnerB v3=new MyOuter.myInnerB(); myInnerB v4=new MyOuter.myInnerB(); class MyOuter v2 v1 v3 v4