thinking injava习题答.docx
thinking injava习题答这是第5章的答案: Chapter 5 Note that many of these exercises simply take you through the steps of discovering issues with packages. This is why so many of them are left to the reader. Exercise 1 /: c05:E01_ImplicitImports.java /+M java E01_ImplicitImports /* Exercise 1 * * Write a program that creates an ArrayList * object without explicitly importing * java.util.*. */ public class E01_ImplicitImports public static void main(String args) java.util.ArrayList al = new java.util.ArrayList; /: To do this, any references to the object must be made using its full package name. Exercise 2 /: c05:E02_LeftToReader.java /+M java E02_LeftToReader /* Exercise 2 * * In the section labeled "package: the library * unit," turn the code fragments concerning * mypackage into a compiling and running set of * Java files. */ public class E02_LeftToReader public static void main(String args) System.out.println("Exercise left to reader"); /: Exercise 3 /: c05:E03_LeftToReader.java /+M java E03_LeftToReader /* Exercise 3 * * In the section labeled "Collisions," take the * code fragments and turn them into a program, * and verify that collisions do in fact occur. */ public class E03_LeftToReader public static void main(String args) System.out.println("Exercise left to reader"); /: Exercise 4 /: c05:E04_LeftToReader.java /+M java E04_LeftToReader /* Exercise 4 * * Generalize the class P defined in this chapter * by adding all the overloaded versions of * rint and rintln necessary to handle all * the different basic Java types. */ public class E04_LeftToReader public static void main(String args) System.out.println("Exercise left to reader"); /: Exercise 5 /: c05:E05_LeftToReader.java /+M java E05_LeftToReader /* Exercise 5 * * Change the import statement in TestAssert.java * to enable and disable the assertion mechanism. */ public class E05_LeftToReader public static void main(String args) System.out.println("Exercise left to reader"); /: Exercise 6 /: c05:E06_AccessControl.java /+M java c05.E06_AccessControl /* Exercise 6 * * Create a class with public, private, * protected, and "friendly" data members and * method members. Create an object of this class * and see what kind of compiler messages you get * when you try to access all the class members. * Be aware that classes in the same directory * are part of the "default" package. */ package c05; public class E06_AccessControl public int a; private int b; protected int c; int d; / "Friendly" public void f1 private void f2 protected void f3 void f4 / "Friendly" public static void main(String args) E06_AccessControl test = new E06_AccessControl; / No problem accessing everything inside / of main for this class, since main / is a member and therefore has access: test.a = 1; test.b = 2; test.c = 3; test.d = 4; test.f1; test.f2; test.f3; test.f4; /: You can see that main( ) has access to everything because its a member. If you create a separate class within the same package, that class cannot access the private members: /: c05:E06_Other.java / A separate class in the same package cannot / access private elements: package c05; public class E06_Other public E06_Other E06_AccessControl test = new E06_AccessControl; test.a = 1; /! test.b = 2; / Can't access: private test.c = 3; test.d = 4; test.f1; /! test.f2; / Can't access: private test.f3; test.f4; /: If you create a class in a separate package (which you can do either by explicitly giving a package statement, or by simply putting it in a different directory) then it is unable to access anything but public members: /: c05:other2:E06_Other2.java / A separate class in the same package cannot / access private elements: package c05.other2; public class E06_Other2 public E06_Other2 c05.E06_AccessControl test = new c05.E06_AccessControl; test.a = 1; /! test.b = 2; / Can't access: private /! test.c = 3; / Can't access: protected /! test.d = 4; / Can't access: friendly test.f1; /! test.f2; / Can't access: private /! test.f3; / Can't access: protected /! test.f4; / Can't access: friendly /: Exercise 7 /: c05:E07_ProtectedManipulation.java /+M java E07_ProtectedManipulation /* Exercise 7 * * Create a class with protected data. Create a * second class in the same file with a method * that manipulates the protected data in the * first class. */ class WithProtected protected int i; public class E07_ProtectedManipulation public static void main(String args) WithProtected wp = new WithProtected; wp.i = 47; System.out.println("wp.i = " + wp.i); /: The point of this exercise is to show that protected also means “package access” (aka “friendly”). That is, you can access protected fields within the same package. Just to be sure, try adding a protected method to WithProtected and accessing it from within E07_ProtectedManipulation. Exercise 8 /: c05:E08_LeftToReader.java /+M java E08_LeftToReader /* Exercise 8 * * Change the class Cookie as specified in the * section labeled "protected: 'sort of * friendly.'" Verify that bite is not public. */ public class E08_LeftToReader public static void main(String args) System.out.println("Exercise left to reader"); /: Just follow the instructions in the book. Exercise 9 /: c05:E09_Widget.java /+M java E09_Widget /* Exercise 9 * * In the section titled "Class access" you'll * find code fragments describing mylib and * Widget. Create this library, then create a * Widget in a class that is not part of the * mylib package. */ import mylib.Widget; public class E09_Widget public static void main(String args) new Widget; /: /: c05:mylib:Widget.java package mylib; public class Widget public Widget System.out.println("Making a Widget"); /: Exercise 10 /: c05:E10_LeftToReader.java /+M java E10_LeftToReader /* Exercise 10 * * Create a new directory and edit your CLASSPATH * to include that new directory. Copy the * P.class file (produced by compiling * com.bruceeckel.tools.P.java) to your new * directory and then change the names of the * file, the P class inside and the method names. * (You might also want to add additional output * to watch how it works.) Create another program * in a different directory that uses your new * class. */ public class E10_LeftToReader public static void main(String args) System.out.println("Exercise left to reader"); /: Exercise 11 /: c05:E11_ConnectionManager.java /+M java E11_ConnectionManager /* Exercise 11 * * Following the form of the example Lunch.java, * create a class called ConnectionManager that * manages a fixed array of Connection objects. * The client programmer must not be able to * explicitly create Connection objects, but can * only get them via a static method in * ConnectionManager. When the ConnectionManager * runs out of objects, it returns a null * reference. Test the classes in main. */ import c05.connection.*; public class E11_ConnectionManager public static void main(String args) Connection c = ConnectionManager.getConnection; while(c != null) System.out.println(c); c.doSomething; c = ConnectionManager.getConnection; /: /: c05:connection:Connection.java package c05.connection; public class Connection private static int counter = 0; private int id = counter+; Connection public String toString return "Connection " + id; public void doSomething /: /: c05:connection:ConnectionManager.java package c05.connection; public class ConnectionManager private static Connection pool = new Connection10; private static int counter = 0; static for(int i = 0; i < pool.length; i+) pooli = new Connection; / Very simple - just hands out each one once: public static Connection getConnection if(counter < pool.length) return poolcounter+; return null; /: The Connection class uses a static int called counter to automatically give each Connection object an identifier, which it will produce as part of its toString( ) representation. Connection also has a doSomething( ) method, which is presumably the useful work that motivates you to use the Connection object. Note that the constructor for Connection is “friendly,” so it is unavailable outside of this package. Thus, the client programmer is unable to access that constructor and cannot make instances of Connection directly. The only way to get Connection objects is through the ConnectionManager. In the ConnectionManager, a static array of objects is initialized inside the static clause, which is only called once when the class is loaded (you can look up further details on static clauses in the book). In this version of the solution, the connection manager is trivial, since it only produces each Connection object in the array once. You might want to create a slightly more sophisticated connection manager by allowing a connection to be checked back in when the client programmer is finished with it. Heres one way to accomplish this: /: c05:E11_ConnectionManager2.java /+M java E11_ConnectionManager2 / Connections that can be checked in. import c05.connection2.*; public class E11_ConnectionManager2 public static void main(String args) Connection ca = new Connection10; / Use up all the connections for(int i = 0; i < 10; i+) cai = ConnectionManager.getConnection; / Should produce "null" since there are no / more connections: System.out.println( ConnectionManager.getConnection); / Return connections, then get them out: for(int i = 0; i < 5; i+) cai.checkIn; Connection c = ConnectionManager.getConnection; System.out.println(c); c.doSomething; c.checkIn; /: /: c05:connection2:Connection.java package c05.connection2; public class Connection private static int counter = 0; private int id = counter+; Connection public String toString return "Connection " + id; public void doSomething public void checkIn ConnectionManager.checkIn(this); /: /: c05:connection2:ConnectionManager.java package c05.connection2; public class ConnectionManager private static Connection pool = new Connection10; static for(int i = 0; i < pool.length; i+) pooli = new Connection; / Produce the first available connection: public static Connection getConnection for(int i = 0; i < pool.length; i+) if(pooli != null) Connection c = pooli; pooli = null; / Indicates "in use" return c; return null; / None left public static void checkIn(Connection c) for(int i = 0; i < pool.length; i+) if(pooli = null) pooli = c; / Check it back in return; /: When a Connection is checked out, its slot in pool is set to null. When the client programmer is done with the connection, checkIn( ) will return it to the connection pool by finding a null slot in pool and assigning it there. Of course, there are all kinds of problems with this approach. What if a client checks a Connection in and then continues to use it? What if they check it in more than once? The book Thinking in Patterns (available from www.BruceE) has a more thorough coverage of the problem of the connection pool. Exercise 12 Create the following file in the c05/local directory (presumably in your CLASSPATH): /: c05:local:PackagedClass.java /=M echo compile by hand to see results package c05.local; class PackagedClass public PackagedClass System.out.println( "Creating a packaged class"); /: Then create the following file in a directory other than c05: /: c05:foreign:Foreign.java /=M echo compile by hand to see results package c05.foreign; import c05.local.*; public class Foreign public static void main (String args) PackagedClass pc = new PackagedClass; /: Explain why the compiler generates an error. Would making the Foreign class part of the c05.local package change anything? Solution: PackagedClass is in its own package, and it is not a public class so it is unavailable outside of package c05.local. If Foreign was also part of c05.local, then it would have access to PackagedClass, since they would then both be in the same package.