Only inner classes can be private.
Regular classes always have either package or public visibility.
inner class:If an inner class has constructors, the compiler modifies them,
adding a parameter for the outer class reference.
An inner class method gets to access both its own data fields
and those of the outer object creating it.
inner class -> local inner class -> anonymous inner class
Whenever you would use a function pointer in C++,
you should consider using an interface in Java.
we suggest that you use Method objects in your own programs
only when absolutely necessary. Using interfaces and inner
classes is almost always a better idea. In particular, we echo
the developers of Java and suggest not using Method objects
for callback functions. Using interfaces for the callbacks
leads to code that runs faster and is a lot more maintainable.
=====================================
Using Reflection to Analyze the Capabilities of Classes
Example 5-5. ReflectionTest.java
1. import java.util.*;
2. import java.lang.reflect.*;
3.
4. public class ReflectionTest
5. {
6. public static void main(String[] args)
7. {
8. // read class name from command-line args or user input
9. String name;
10. if (args.length > 0)
11. name = args[0];
12. else
13. {
14. Scanner in = new Scanner(System.in);
15. System.out.println("Enter class name (e.g. java.util.Date): ");
16. name = in.next();
17. }
18.
19. try
20. {
21. // print class name and superclass name (if != Object)
22. Class cl = Class.forName(name);
23. Class supercl = cl.getSuperclass();
24. System.out.print("class " + name);
25. if (supercl != null && supercl != Object.class)
26. System.out.print(" extends " + supercl.getName());
27.
28. System.out.print("{");
29. printConstructors(cl);
30. System.out.println();
31. printMethods(cl);
32. System.out.println();
33. printFields(cl);
34. System.out.println("}");
35. }
36. catch(ClassNotFoundException e) { e.printStackTrace(); }
37. System.exit(0);
38. }
39.
40.
44. public static void printConstructors(Class cl)
45. {
46. Constructor[] constructors = cl.getDeclaredConstructors();
47.
48. for (Constructor c : constructors)
49. {
50. String name = c.getName();
51. System.out.print(" " + Modifier.toString(c.getModifiers()));
52. System.out.print(" " + name + "(");
53.
54. // print parameter types
55. Class[] paramTypes = c.getParameterTypes();
56. for (int j = 0; j < paramTypes.length; j++)
57. {
58. if (j > 0) System.out.print(", ");
59. System.out.print(paramTypes[j].getName());
60. }
61. System.out.println(");");
62. }
63. }
64.
65.
69. public static void printMethods(Class cl)
70. {
71. Method[] methods = cl.getDeclaredMethods();
72.
73. for (Method m : methods)
74. {
75. Class retType = m.getReturnType();
76. String name = m.getName();
77.
78. // print modifiers, return type and method name
79. System.out.print(" " + Modifier.toString(m.getModifiers()));
80. System.out.print(" " + retType.getName() + " " + name + "(");
81.
82. // print parameter types
83. Class[] paramTypes = m.getParameterTypes();
84. for (int j = 0; j < paramTypes.length; j++)
85. {
86. if (j > 0) System.out.print(", ");
87. System.out.print(paramTypes[j].getName());
88. }
89. System.out.println(");");
90. }
91. }
92.
93.
97. public static void printFields(Class cl)
98. {
99. Field[] fields = cl.getDeclaredFields();
100.
101. for (Field f : fields)
102. {
103. Class type = f.getType();
104. String name = f.getName();
105. System.out.print(" " + Modifier.toString(f.getModifiers()));
106. System.out.println(" " + type.getName() + " " + name + ";");
107. }
108. }
109. }
---------------------------------------
Using Reflection to Analyze Objects at Run Time
Example 5-6. ObjectAnalyzerTest.java
1. import java.lang.reflect.*;
2. import java.util.*;
3. import java.text.*;
4.
5. public class ObjectAnalyzerTest
6. {
7. public static void main(String[] args)
8. {
9. ArrayList
10. for (int i = 1; i <= 5; i++) squares.add(i * i);
11. System.out.println(new ObjectAnalyzer().toString(squares));
12. }
13. }
14.
15. class ObjectAnalyzer
16. {
17.
24. public String toString(Object obj)
25. {
26. if (obj == null) return "null";
27. if (visited.contains(obj)) return "...";
28. visited.add(obj);
29. Class cl = obj.getClass();
30. if (cl == String.class) return (String) obj;
31. if (cl.isArray())
32. {
33. String r = cl.getComponentType() + "[]{";
34. for (int i = 0; i < Array.getLength(obj); i++)
35. {
36. if (i > 0) r += ",";
37. Object val = Array.get(obj, i);
38. if (cl.getComponentType().isPrimitive()) r += val;
39. else r += toString(val);
40. }
41. return r + "}";
42. }
43.
44. String r = cl.getName();
45. // inspect the fields of this class and all superclasses
46. do
47. {
48. r += "[";
49. Field[] fields = cl.getDeclaredFields();
50. AccessibleObject.setAccessible(fields, true);
51. // get the names and values of all fields
52. for (Field f : fields)
53. {
54. if (!Modifier.isStatic(f.getModifiers()))
55. {
56. if (!r.endsWith("[")) r += ",";
57. r += f.getName() + "=";
58. try
59. {
60. Class t = f.getType();
61. Object val = f.get(obj);
62. if (t.isPrimitive()) r += val;
63. else r += toString(val);
64. }
65. catch (Exception e) { e.printStackTrace(); }
66. }
67. }
68. r += "]";
69. cl = cl.getSuperclass();
70. }
71. while (cl != null);
72.
73. return r;
74. }
75.
76. private ArrayList
----------------------------------------------------------------------
Using Reflection to Write Generic Array Code
a Java array remembers the type of its entries, that is, the element
type used in the new expression that created it. It is legal to cast
an Employee[] temporarily to an Object[] array and then cast it
back, but an array that started its life as an Object[] array can never
be cast into an Employee[] array. To write this kind of generic
array code, we need to be able to make a new array of the same
type as the original array. For this, we need the methods of the
Array class in the java.lang.reflect package. The key is the static
newInstance method of the Array class that constructs a new array.
You must supply the type for the entries and the desired length
as parameters to this method.
Example 5-7. ArrayGrowTest.java
1. import java.lang.reflect.*;
2. import java.util.*;
3.
4. public class ArrayGrowTest
5. {
6. public static void main(String[] args)
7. {
8. int[] a = { 1, 2, 3 };
9. a = (int[]) goodArrayGrow(a);
10. arrayPrint(a);
11.
12. String[] b = { "Tom", "Dick", "Harry" };
13. b = (String[]) goodArrayGrow(b);
14. arrayPrint(b);
15.
16. System.out.println("The following call will generate an exception.");
17. b = (String[]) badArrayGrow(b);
18. }
19.
20.
28. static Object[] badArrayGrow(Object[] a)
29. {
30. int newLength = a.length * 11 / 10 + 10;
31. Object[] newArray = new Object[newLength];
32. System.arraycopy(a, 0, newArray, 0, a.length);
33. return newArray;
34. }
35.
36.
44. static Object goodArrayGrow(Object a)
45. {
46. Class cl = a.getClass();
47. if (!cl.isArray()) return null;
48. Class componentType = cl.getComponentType();
49. int length = Array.getLength(a);
50. int newLength = length * 11 / 10 + 10;
51.
52. Object newArray = Array.newInstance(componentType, newLength);
53. System.arraycopy(a, 0, newArray, 0, length);
54. return newArray;
55. }
56.
57.
62. static void arrayPrint(Object a)
63. {
64. Class cl = a.getClass();
65. if (!cl.isArray()) return;
66. Class componentType = cl.getComponentType();
67. int length = Array.getLength(a);
68. System.out.print(componentType.getName()
69. + "[" + length + "] = { ");
70. for (int i = 0; i < Array.getLength(a); i++)
71. System.out.print(Array.get(a, i) + " ");
72. System.out.println("}");
73. }
74. }
---------------------------------------------------------------
Method Pointers!
On the surface, Java does not have method pointers—
ways of giving the location of a method to another
method so that the second method can invoke it later.
In fact, the designers of Java have said that method
pointers are dangerous and error prone and that Java
interfaces (discussed in the next chapter) are a superior
solution. However, it turns out that, as of JDK 1.1,
Java does have method pointers, as a
(perhaps accidental) by-product of the reflection package.
Example 5-8. MethodPointerTest.java
1. import java.lang.reflect.*;
2.
3. public class MethodPointerTest
4. {
5. public static void main(String[] args) throws Exception
6. {
7. // get method pointers to the square and sqrt methods
8. Method square = MethodPointerTest.class.getMethod("square",
9. double.class);
10. Method sqrt = Math.class.getMethod("sqrt", double.class);
11.
12. // print tables of x- and y-values
13.
14. printTable(1, 10, 10, square);
15. printTable(1, 10, 10, sqrt);
16. }
17.
18.
23. public static double square(double x)
24. {
25. return x * x;
26. }
27.
28.
36. public static void printTable(double from, double to,
37. int n, Method f)
38. {
39. // print out the method as table header
40. System.out.println(f);
41.
42. // construct formatter to print with 4 digits precision
43.
44. double dx = (to - from) / (n - 1);
45.
46. for (double x = from; x <= to; x += dx)
47. {
48. try
49. {
50. double y = (Double) f.invoke(null, x);
51. System.out.printf("%10.4f | %10.4f%n", x, y);
52. }
53. catch (Exception e) { e.printStackTrace(); }
54. }
55. }
56. }