1 / 55

Visibilities and Static-ness

Visibilities and Static-ness. Aaron Bloomfield CS 101-E. Our Circle class. We are going to write a Circle class Somebody else is going to use it. public class Circle { double radius; double Pi = 3.1415926536; }. Note the radius field is not initialized. Remember that a

stroia
Télécharger la présentation

Visibilities and Static-ness

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Visibilities and Static-ness Aaron Bloomfield CS 101-E

  2. Our Circle class • We are going to write a Circle class • Somebody else is going to use it public class Circle { double radius; double Pi = 3.1415926536; } Note the radius field is not initialized Remember that a variable of a class is called a field Note the fields are not static We’re ignoring the public for now

  3. Using our Circle class Note it’s a different class public class CircleTest { public static void main (String[] args) { int x = 5; Circle c = new Circle(); } } public class CircleTest { public static void main (String[] args) { int x = 5; Circle c = new Circle(); } } Remember that a variable of a method is just called a variable Circle is the class c is the object Note the new

  4. Accessing our Circle object • Any field or method in an object can be accessed by using a period • Example: System.in • Example: c.radius = 10; • Example: c.Pi = 4; This is bad – Pi should have been declared final (this will be done later)

  5. What’s the output? public class Circle { double radius; double Pi = 3.1415926536; } public class CircleTest { public static void main (String[] args) { int x; Circle c = new Circle(); System.out.println (x); } } Java will give a “variable not initialized” error

  6. What’s the output now? public class Circle { double radius; double Pi = 3.1415926536; } public class CircleTest { public static void main (String[] args) { int x; Circle c = new Circle(); System.out.println (c.radius); } } Java outputs 0.0!

  7. What’s going on? • A (method) variable needs to be initialized before it is used • A field (class variable) is automatically initialized by Java • All doubles are initialized to 0.0, ints to 0, etc. • This is a bit counter-intuitive…

  8. radius = 0.0 Pi = 3.1415926536 Circle c What happens in memory • Consider: Circle c = new Circle() • A double takes up 8 bytes in memory • Thus, a Circle object takes up 16 bytes of memory • As it contains two doubles

  9. Consider the following code public class CircleTest { public static void main (String[] args) { Circle c1 = new Circle(); Circle c2 = new Circle(); Circle c3 = new Circle(); Circle c4 = new Circle(); } }

  10. radius = 0.0 radius = 0.0 radius = 0.0 radius = 0.0 Pi = 3.1415926536 Pi = 3.1415926536 Pi = 3.1415926536 Pi = 3.1415926536 Circle c1 Circle c2 Circle c3 Circle c4 What happens in memory • There are 4 Circle objects in memory • Taking up a total of 4*16 = 64 bytes of memory

  11. Consider the following code public class CircleTest { public static void main (String[] args) { Circle c1 = new Circle(); //... Circle c1000000 = new Circle(); } } This program creates 1 million Circle objects!

  12. radius = 0.0 radius = 0.0 radius = 0.0 Pi = 3.1415926536 Pi = 3.1415926536 Pi = 3.1415926536 Circle c1 Circle c2 Circle c1000000 What happens in memory • There are 1 million Circle objects in memory • Taking up a total of 1,000,000*16 = 16 Mb of memory … Note that the final Pi field is repeated 1 million times

  13. Circle c Circle c1000000 Circle c1 Circle c1 Circle c2 Circle c2 Circle c3 Circle c4 radius = 0.0 radius = 0.0 radius = 0.0 radius = 0.0 radius = 0.0 radius = 0.0 radius = 0.0 radius = 0.0 Pi = 3.1415926536 Pi = 3.1415926536 Pi = 3.1415926536 The use of static for fields • If a field is static, then there is only ONE of that field for ALL the objects Total memory usage: 16 bytes (1+1=2 doubles) Total memory usage: 8 Mb + 8 bytes (1,000,000+1=1,000,001 doubles) Total memory usage: 40 bytes (4+1=5 doubles)

  14. More on static fields • What does the following print • Note that Pi is not final Circle c1 = new Circle(); Circle c2 = new Circle(); Circle c3 = new Circle(); Circle c4 = new Circle(); c1.Pi = 4.3; System.out.println (c2.Pi); Note you can refer to static fields by object.field

  15. Even more on static fields • There is only one copy of a static field no matter how many objects are declared in memory • Even if there are zero objects declared! • The one field is “common” to all the objects • Thus, you can refer to a static field by using the class name: • Circle.Pi

  16. Even even more on static fields • This program also prints 4.3: Circle c1 = new Circle(); Circle c2 = new Circle(); Circle c3 = new Circle(); Circle c4 = new Circle(); Circle.Pi = 4.3; System.out.println (c2.Pi);

  17. Even even even more on static fields • We’ve seen static fields used with their class names: • System.in (type: InputStream) • System.out (type: OutputStream) • Math.PI (type: double) • Integer.MAX_VALUE (type: int) • Non-static fields are generally not called dynamic fields • Just “non-static”, or no qualifier at all

  18. A bit of humor…

  19. Back to our Circle class public class Circle { double radius; final static double Pi = 3.1415926536; } • But it doesn’t do much! Note that Pi is now final and static

  20. Adding a method public class Circle { double radius; final static double Pi = 3.1415926536; double computeArea () { return Pi*radius*radius; } } Note that a (non-static) method can use all the fields

  21. Using that method public class CircleTest { public static void main (String[] args) { Circle c = new Circle(); c.radius = 2.0; System.out.println (c.computeArea()); } } Prints 12.566370614356

  22. Adding another method double oneOverRadius() { return 1.0/radius; } • I couldn’t think of a good reason to divide something by the radius…

  23. What happens now? • Code in class CircleTest’s main() method Circle c = new Circle(); // c.radius = 0.0 System.out.println (c.oneOverRadius()); • Java won’t crash, but many other programming languages (C and C++, especially) will • Java prints “Infinity” • Not what we wanted, though!

  24. One way to fix this… Note that the radius field is now initialized to 1.0 public class Circle { double radius = 1.0; final static double Pi = 3.1415926536; double computeArea () { return Pi*radius*radius; } double oneOverRadius() { return 1.0/radius; } }

  25. Back to our program… • This code will now run properly: Circle c = new Circle(); // c.radius = 1.0 System.out.println (c.oneOverRadius()); • But this code will “crash”: Circle c = new Circle(); // c.radius = 1.0 c.radius = 0.0; System.out.println (c.oneOverRadius());

  26. Where the “crash” occurs public class CircleTest { public static void main (String[] args) { Circle c = new Circle(); // c.radius = 1.0 c.radius = 0.0; System.out.println (c.oneOverRadius()); } } public class Circle { double radius = 1.0; final static double Pi = 3.1415926536; double computeArea () { return Pi*radius*radius; } double oneOverRadius() { return 1.0/radius; } Here is the badly written code Here is where the “crash” occurs

  27. Motivation for private fields • Problem: We do not want people using our Circle class to be able to modify the fields on their own • Solution: Don’t allow other code to modify the radius field • Give it private visibility • private means that only code within the class can modify the field

  28. One way to fix this… Note that the radius field is now private public class Circle { private double radius = 1.0; final static double Pi = 3.1415926536; double computeArea () { return Pi*radius*radius; } double oneOverRadius() { return 1.0/radius; } }

  29. Back to our program… • This code will now not compile: Circle c = new Circle(); // c.radius = 1.0 c.radius = 0.0; System.out.println (c.oneOverRadius()); • Java will give a compile-time error: • radius has private access in Circle

  30. Back to our program… • This code will also not compile: Circle c = new Circle(); // c.radius = 1.0 System.out.println (c.radius); • Java will give the same compile-time error: • radius has private access in Circle

  31. The problem now… • But now you can’t have a Circle with a radius other than 1.0! • Solution: Use a get/set methods in Circle: void setRadius (double r) { radius = r; } double getRadius () { return radius; }

  32. Our Circle class so far public class Circle { double radius = 1.0; final static double Pi = 3.1415926536; double computeArea () { return Pi*radius*radius; } double oneOverRadius() { return 1.0/radius; } void setRadius (double r) { radius = r; } double getRadius () { return radius; } }

  33. Using the get/set methods public class CircleTest { public static void main (String[] args) { Circle c = new Circle(); c.setRadius (1.0); System.out.println (c.computeArea()); System.out.println (c.getRadius()); } } public class Circle { private double radius = 1.0; final static double Pi = 3.1415926536; double computeArea () { return Pi*radius*radius; } double oneOverRadius() { return 1.0/radius; } void setRadius (double r) { radius = r; } double getRadius () { return radius; } } Here a method is invoked Here the change to radius occurs

  34. Wait! Another problem! public class CircleTest { public static void main (String[] args) { Circle c = new Circle(); c.setRadius (0.0); System.out.println (c.oneOverRadius()); } } Here is the problem now…

  35. This problem is easily fixed • Change the setRadius method to the following void setRadius (double r) { if ( r > 0.0 ) radius = r; } • Now there is no way for code outside the Circle class to change the radius to zero

  36. Visibilities in Java • There are four visibilities: • private: Only code within the same class can access the field or method • Note: “access” means reading or writing the field, or invoking the method • public: Any code, anywhere, can access the field or method • protected: Used with inheritance • We won’t get to that this semester • package: Almost the same as public • This is the default • Note that it can’t be specified like the others

  37. A few notes on visibilities • You can NOT specify visibilities for method variables • Any method variable can only be accessed within that method • Think of it as public within the method (after it’s defined) and private outside the method • You can also specify visibilities for methods and classes • More on that later in the course (or next course)

  38. Constructors • When you create a object, you often have to do some initialization • You have to “construct” the object public class Circle { String name; public Circle() { Scanner scanner = new Scanner(System.in); System.out.println (“Enter the Circle’s name:”); name = scanner.next(); } //... } Note the different method declaration

  39. Constructors, take 2 • Now when a Circle is created: Circle c = new Circle(); • Java will ask for the Circle’s name, and put it in the name field • Okay, so this isn’t the greatest example…

  40. Constructors, take 3 • More useful constructors for our Circle class: public Circle() { radius = 1.0; } public Circle (double r) { radius = r; } Note there is no return type for constructors Note that the constructor name is the EXACT same as the class name Note that there are two “methods” with the same name!

  41. Overriding methods (and constructors) • Consider the following code: Circle c1 = new Circle (); Circle c2 = new Circle (2.0); • Java knows which constructor to call by the list of parameters • This is called “overloading” Creates a Circle of radius 1.0 Creates a Circle of radius 2.0

  42. Overriding methods (and constructors), take 2 • The following Circle constructors would not be allowed: • We are assuming Pi is not final for this example public Circle() { radius = 1.0; } public Circle (double r) { radius = r; } public Circle (double p) { Pi = p; } When Circle(1.0) is called, which one is meant?

  43. Constructors, take 4 • Our second constructor has a problem: public Circle (double r) { radius = r; } • Consider the following code: Circle c = new Circle (0.0); System.out.println (c.oneOverRadius()); The method is dividing 1 by zero (again)

  44. Constructors, take 5 • Our revised constructors: public Circle() { radius = 1.0; } public Circle (double r) { if ( r <= 0.0 ) radius = 1.0; else radius = r; }

  45. A bit of humor…

  46. Back to the static discussion • Remember that there is one (and only one) static Pi field, regardless of how many objects are declared • Consider the following method: double getPi() { return Pi; }

  47. The getPi() method • It doesn’t read or modify the “state” of any object • In this example, it doesn’t read/write the radius • In fact, that particular method doesn’t care anything about the objects declared • It’s only accessing a static field

  48. Make getPi() static • Consider the following: static double getPi() { return Pi; } • As the method is static, it can ONLY access static fields • A static method does not care about the “state” of an object • Examples: Math.sin(), Math.tan(), Math.cos() • They don’t care about the state of the Math class • They only perform the computation

  49. Invoking static methods • As with static fields, they can be called using either an object or the class name: Circle c = new Circle(); System.out.println (c.getPi()); System.out.println (Circle.getPi());

  50. static methods and non-static fields • Consider the following (illegal) Circle method: static double getRadius() { return radius; } • And the code to invoke it: public static void main (String[] args) { Circle c1 = new Circle(); Circle c2 = new Circle(); Circle c3 = new Circle(); Circle c4 = new Circle(); System.out.println (Circle.getRadius()); }

More Related