Thinking in Java Chapter 14

Source: Internet
Author: User
Tags drjava

From thinking in Java 4th Edition

RTTI (run-time type information), run-time type information that allows you to discover and use type information while the program is running. The need for Rtti reveals many interesting (and complex) problems in object-oriented design, and also raises the question of how to organize the program.

How Java lets us identify objects and classes at run time. There are two main ways of doing this:

1. "Traditional" RTTI, which assumes that we already know all the types at compile time

2. "Reflection" mechanism, which allows us to discover and use type information at runtime

Typically a specific object (Circle, Square, or Triangle) is created, it is transformed upward into shape (ignoring the object's specific type), and anonymous shape references are used in later programs:

Import Java.util.*;abstract class Shape {void Draw () {System.out.println (this + ". Draw ()"); Abstract public String toString ();} Class Circle extends Shape {public String toString () {return ' Circle ';}} Class Square extends Shape {public String toString () {return "Square";}} Class Triangle extends Shape {public String toString () {return "Triangle";}} public class Shapes {public static void main (string[] args) {list<shape> shapelist = arrays.aslist (New Circle (), New Square (), New Triangle ()); for (Shape shape:shapelist) Shape.draw ();}} /* Output:Circle.draw () Square.draw () Triangle.draw () */

When an element is removed from an array, the container-in fact it holds everything as an object-automatically converts the result to Shap. This is the most basic form of use of rtti, and all type conversions are properly checked at run time. This is also the meaning of the Rtti name: At run time, identify the type of an object.

In this example, the conversion of Rtti is not exhaustive: object is transformed into shape, not circle, Square, or Triangle. This is because the only thing we know from List<shape> is Shape, which is enforced by the container and Java generics at compile time, and is ensured by the type conversion operation at run time.

The next step is the polymorphic mechanism, which is what the Shape object actually executes, which is determined by the specific object circle that the reference refers to, Square o triangle.

With Rtti, you can query the exact type of the object to which a shape reference is pointing, and then select or reject the Special column.

Class object

To understand how Rtti works in Java, you must first know how the type information is represented at run time. This work is done by a special object called a Class object, which contains information about the classes.

A class is part of a program, and each class has an object of class. Whenever a new class is written and compiled, it produces a class object (more appropriately, it is stored in a. class file of the same name). In order to generate objects of this class, the Java virtual machine running in this program will use a subsystem called the ClassLoader.

The ClassLoader subsystem can actually contain a class loader chain, but there is only one native ClassLoader, which is part of the JVM implementation.

All classes are dynamically loaded into the JVM when they are used for the first time. This class is loaded when the program creates the first reference to a static member of a class.

Once a class object is loaded into memory, it is used to create all objects of the class:

Examination of the the-the-class loader works.import static Net.mindview.util.print.*;class Candy {static {Print ("Load ing Candy "); }}class Gum {static {print ("Loading Gum");}} Class Cookie {static {print ("Loading cookie");}} public class Sweetshop {public static void main (string[] args) {print ("inside main"), New Candy ();p rint ("After creating Can Dy "), try {class.forname (" Gum "),} catch (ClassNotFoundException e) {print (" couldn ' t find Gum ");} Print ("After Class.forName (\" gum\ ")"), New Cookie ();p rint ("After creating Cookie");}} /* Output:inside mainloading candyafter creating candyloading gumafter class.forname ("Gum") Loading Cookieafter creating cookie*/

Forname () is a way to obtain a reference to a class object. It is an input parameter by a string containing the text name of the target class, and returns a reference to a class object . The call to Forname () is for its "side effects": If the class gum has not yet been loaded, load it. During the loading process, the static clause of gum is executed.

Whenever you want to use type information at run time , you must first obtain a reference to the appropriate class object . Class.forName () is a convenient way to do this because you do not need to hold objects of that type in order to obtain a class reference .

However, if you already have an object of the type of interest, you can get the class reference by calling the GetClass () method, which is part of the root class object, which returns a class reference that represents the actual type of the object:

Testing Class class.package leetcode.drjava;import static net.mindview.util.print.*;interface HasBatteries {} Interface Waterproof {}interface Shoots {}class Toy {//Comment out of the following default constructor//to see Nosuchmetho Derror from (*1*) Toy () {}toy (int i) {}}class Fancytoy extends Toy implements Hasbatteries, waterproof, Shoots {Fancytoy () {super (1);}} public class Toytest {static void Printinfo (class cc) {print (' Class name: ' + cc.getname () + ' is interface? ["+ cc.isinterface () +"] ");p rint (" Simple name: "+ cc.getsimplename ());p rint (" Canonical name: "+ cc.getcanonicalname ()) ;} public static void Main (string[] args) {Class C = null;//Get the reference of a Class try {c = class.forname ("Leetcode.drj Ava. Fancytoy ");} catch (ClassNotFoundException e) {print ("Can ' t find Fancytoy"); System.exit (1);} Printinfo (c);//Return the interfaces in "C" Class.for (Class face:c.getinterfaces ()) printinfo (face);//Return the SUPERC Lass of the "C" classclass up = C.getsuperclass (); Object obj = null;try {//Requires default constructorobj = Up.newinstance ();} catch (Instantiationexception e) {print ("Cannot Instan Tiate "); System.exit (1);} catch (Illegalaccessexception e) {print ("Can ' t access"); System.exit (1);} Printinfo (Obj.getclass ());}} /* Output:class Name:Leetcode.DrJava.FancyToy is interface? [FALSE] Simple name:fancytoycanonical name:Leetcode.DrJava.FancyToyClass name:Leetcode.DrJava.HasBatteries is interface? [True] Simple name:hasbatteriescanonical Name:Leetcode.DrJava.HasBatteriesClass Name:Leetcode.DrJava.Waterproof is Interface? [True] Simple name:waterproofcanonical name:Leetcode.DrJava.WaterproofClass name:Leetcode.DrJava.Shoots is interface? [True] Simple name:shootscanonical name:Leetcode.DrJava.ShootsClass Name:Leetcode.DrJava.Toy is interface? [FALSE] Simple Name:toycanonical name:leetcode.drjava.toy*/

1. In main (), use the forname () method to create a class reference in the appropriate try statement block and initialize it to a class that points to Fancytoy. (The parameters in Forname are fully qualified, that is, the package name is included).

2. Printinfo () uses getname () to generate the class name of the permission, using Getsimplename () to generate a class name that does not contain the package name, and using Getcanonicalname () to produce the fully qualified class name.

(GetName () returns the representation of the class in the virtual machine, and Getcanonicalname () returns a more understandable representation)

3. The Class.getinterfaces () method returns a Class object that represents the interface contained in the class object of interest

4. If you have a class object, you can also use the Getsuperclass () method to query its direct base class.

5. The newinstance () method of class is a way to implement a "virtual constructor": "I don't know your specific type, but you should create yourself correctly anyway."

Classes that are created by using the Newinstance () method must have a default constructor. We will then see how to use the Java Reflection API to dynamically create objects of the class with arbitrary constructors.

Type literal constants

Java provides another way to generate a reference to a class object, which is to use type literal constants. The above procedure can be written like this:

Fancytoy.class

This is simpler, more secure, and will be checked at compile time.

When you use ". Class" To create a reference to a class object, the class object is not automatically initialized. The preparation to use the class actually consists of three steps:

1. Load, this is performed by the ClassLoader, check the bytecode, and create the class object

2. Links. Verify the bytecode in the class and allocate space for the static domain

3. Initialize. Executes static initializers and static initialization blocks.

Initialization is deferred until the first reference to a static method or a very static domain is performed:

Import Java.util.*;class initable {static final int staticfinal = 47;static final int staticFinal2 = CLASSINITIALIZATION.R And.nextint (+), static {System.out.println ("Initializing initable");}} Class Initable2 {static int staticnonfinal = 147;static {System.out.println ("Initializing Initable2");}} Class Initable3 {static int staticnonfinal = 74;static {System.out.println ("Initializing Initable3");}}  public class Classinitialization {public static Random rand = new random;p ublic static void Main (string[] args) throws Exception {Class initable = Initable.class; System.out.println ("After creating initable ref");//Does not trigger initialization:System.out.println ( initable.staticfinal);//Does not trigger initialization:System.out.println (INITABLE.STATICFINAL2);//Does not Trigger Initialization:System.out.println (initable2.staticnonfinal); Class initable3 = Class.forName ("Initable3"); System.out.println ("After creating Initable3 ref"); System.out.println (initable3.staticnonfinal);}} /* outPut:after creating initable ref47initializing initable258initializing initable2147initializing Initable3After Creating Initable3 ref74*/

1. As you can see from the creation of initable references, using only the. class syntax to get a reference to a class does not throw initialization.

2. However, as can be seen from the creation of the Initable3 Reference, Class.forName () is initialized immediately.

3. If a static final value is a "compile-time constant", as in initable.staticfinal, then this value does not require initialization of the Initable class to read

4. However, if a domain is only static and final, it is not enough to ensure that 3 of the behavior, such as access to INITABLE.STATICFINAL2, will force the initialization of the class because it is not a compile-time constant

5. If a static domain is not final, access to it requires linking (allocating storage space for the domain) and initializing (initializing the storage space) before access, just like access to initable2.statinonfinal.

Thinking in Java Chapter 14

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.