The classloader Class
This code works, but is less desirable than the generic version that took in the array to fill. The main problem is that the above causes an “unchecked” warning from the compiler. As you may have already noticed, the cast to E is a cast involving a type parameter and such casts have a different meaning at runtimethe actual cast will be to Object, which is the erasure of E. Despite this, it is apparent that the code above is type-safe: We ask for an array that has a component type of E and we try to use the returned object as such an array. The existence of the “unchecked” warning is a consequence of a limitation in the Array API and can’t be avoided. The second problem with the above is that it suffers from the same limitation as the original non-generic version of toarrayit will only allow an array of the exact element type to be created, not an array of any supertype. We can address this latter problem by turning the current version into a generic method, as we did previously:
If you invoke the getpackage method on a Class object, you get a Package object that describes the package in which the class lives (the Package class is defined in java.lang). You can also get a Package object by invoking the static method getpackage with the name of the package, or you can use the static getpackages method which returns an array of all known packages in the system. The getname method returns the full name of the package. Package objects are used differently than the other reflective typesyou can’t create or manipulate packages at run time. You use Package objects to obtain information about a package, such as its purpose, who created it, what version it is, and so on. We defer a discussion on this until we look at packages in detail in Chapter 18.
The Proxy Class
The Proxy class lets you create classes at runtime that implement one or more interfaces. This is an advanced, rarely needed feature, but when needed it is quite useful. Suppose, for example, you want to log calls to an object so that when a failure happens you can print the last several methods invoked on the object. You could write such code by hand for a particular class, with a way to turn it on for a particular object. But that requires custom code for each type of object you want to monitor, as well as each object checking on each method invocation to see if calls should be logged. You could instead write a general utility that used a Proxy-created class to log a call history. Objects created by that class would implement the relevant interfaces, interposing code that you provide between the caller’s invocation of a method and the object’s execution of it
The runtime system loads classes when they are needed. Details of loading classes vary between implementations, but most of them use a class path mechanism to search for a class referenced by your code but not yet loaded into the runtime system. The class path is a list of places in which the system looks for class files. This default mechanism works well in many cases, but much of the power of the Java virtual machine is its ability to load classes from places that make sense to your application. To write an application that loads classes in ways different from the default mechanism, you must provide a classloader object that can get the bytecodes for class implementations and load them into the runtime system.
To make this work, you would provide a Player abstract class that players would extend to implement their strategy. When players were ready to try their strategy, they would send the compiled class’s bytecodes to your system. The bytecodes would need to be loaded into the game and the strategy evaluated by playing it against others. The score would then be returned to the player.
At the server, the game program loads each waiting Player class, creates an object of the new type, and runs its strategy against the game algorithm. When the results are known, they are reported to the player who submitted the strategy. The communication mechanism isn’t specified here, but it could be as simple as electronic mail, with players mailing their classes and receiving the results by return mail. The interesting part is how the game program loads the compiled class files into its runtime system. This is the province of a class loader, which must extend the abstract classloader class and override its findclass method: