Thinking in Java 12

zhaozj2021-02-11  201

Chapter 11 Operation Type Identification Operation Type Identification (RTTI) The concept of the Type Identification is very simple - when there is only one handle of the basic type, use it to determine the correct type of object. However, the need for RTTI needs exposure to object-oriented design many interesting (and often confusing) issues, and officially put the program's construction problem on the desktop. This chapter will discuss how to use Java to find objects and class information during operation. This mainly takes two forms: one is "traditional" RTTI, which assumes that we have all types we have in compilation and running period; the other is the "reflection" mechanism for Java1.1, and uses it to find independently at runtime Class information. First discuss the "traditional" RTTI and discuss the reflex problem. 11.1 For RTTI needs, consider the following familiar class structure example, which utilizes versatility. The conventional type is the Shape class, and the type of specially derived is Circle, Square, and Triangle. 516 Page Figure This is a typical schematic diagram of a typical class, the base class is located at the top, derived class downward. Object-oriented programming is to use a large number of code control basic types (here you are shape) handle, so if you decide to add a new class (such as rhomboid, from Shape derived), it will not affect the procedure, then it will not affect the original Code. In this example, the dynamic binding method in the Shape interface is DRAW (), so the customer programmer is to call DRAW () through a normal Shape handle. Draw () is overwritten in all derivatives. And because it is a dynamic binding method, even if it is called by a normal Shape handle, it also shows the correct behavior. This is the function of context. So, we generally create a specific object (Circle, Square, or Triangle), trace it back to a shape (special type of object), and then use an anonymous Shape handles in the remainder of the program. As a brief review of velocity and tracetability, it can be encoded as described above (if there is difficulty when performing this program, please refer to Chapter 3 3.1.2 "Assignment"): 516-517 Page Program Foundation The class can be encoded into an interface, an Abstract class or a normal class. Since Shape does not have a real member (that is, a defined member), and does not care we create a pure Shape object, the most suitable and most flexible expression is an interface. And because you don't have to set all the Abstract keywords, the entire code is also more refreshing. Each derived class covers the basic DRAW method, so it has different behaviors. A specific type of Shape is created in Main () and then add it to a vector. Here is the place where the wind is traced, because the vector is only accommodated. Since all things in Java (except for basic data types) are objects, the vector can accommodate the Shape object. But in the process of tracery to Object, any special information will be lost, and even the object is the fact of geometric shape. For Vector, they are just Object. When using NexTelement () to extract an element from the vector, the situation is slightly more complicated. Since the vector is only to accommodate Object, nextelement () will naturally have an Object handle. But we know that it is actually a shape handle and wants to send the Shape message to that object.

Therefore, it is necessary to use a traditional "shape" mode into a shape. This is the most basic form of RTTI, because in Java, all styles are checked during operation to ensure their correctness. That is the meaning of RTTI: at the course of operation, the type of object will be identified. In this case, the RTTI shape only achieves part: Object is shaped, rather than modeling Circle, Square, or Triangle. It is because the only fact that we are currently affirmed is that the vector is full of geometries, instead of their specific categories. During the compilation, our affirmation is based on our own rules; and during compilation, it is definitely this. The current situation will be controlled by polymorphism, and the appropriate method is called for the Shape to determine whether the handle is providing Circle, Square, or is supplied to Triangle. Moreover, in general, a versatile solution must be guaranteed. Because we want your code to know some of the specific types of objects as possible, you only put the attention on a certain type of object (here is Shape). Only in this way, our code is more easy to implement, understand, and modify. Therefore, it is a routine target for object-oriented programming. However, if you encounter a special programming problem, only after knowing the exact type of the regular handle, you can solve this problem easily. What should I do this? For example, we sometimes want your users to make a specific type of geometry (such as triangles) into purple in order to highlight them and quickly find all of this type. In this case, the RTTI technology is used, and it is used to query what the exact type of a Shape handle reference is. 11.1.1 Class object To understand how RTTI works in Java, you must first understand how the type information is expressed in the running period. At this time, you should use a special form of "Class Object", which contain information related to the class (sometimes it is called "class class"). In fact, we have to create all "General" or "General" objects belonging to a class with the Class object. For each class as part of the program, they have a Class object. In other words, each time you write a new class, it will also create a Class object (more appropriately, it is saved in a .class file that is completely the same name). At runtime, once we want to generate an object of that class, the Java Virtual Machine (JVM) for executing the program first checks if the type of Class object is loaded. If it is not loaded, the JVM looks for the same name. Class file and load it. So the Java program is not fully loaded when starting, which is different from many traditional languages. Once the type of Class object enters memory, use it to create all of the types of objects. If this kind of saying makes you have a little confused, or don't really understand it, the following demonstration procedure may provide further help: 519-520 Page programs for each class (Candy, GUM and Cookie), They all have a Static clause that is used to execute when the class is first loaded. The corresponding information will be printed and tell us when loading. In Main (), the creation code of the object is between the print statement in order to detect the load time. Special and interesting lines are: class.Forname ("gum"); this method is a Static member of Class (ie, all Class from all Class).

Class objects and any other objects are similar, so a handle that can be obtained and controlled (the loading module is dry). In order to obtain a handle of Class, one means use forname (). Its role is to obtain a string containing the name of the target class text (note spelling and case). The last returned is a CLASS handle. The program is in a JVM as follows: 520 Page Program You can see that each class will only be loaded when it needs, and Static initialization is performed when it is loaded. Very interesting, the other JVM output becomes another: 520 Up program seems to jvm By checking the code in main (), it has predicted the need for Candy and Cookie, but can not see gum, Because it is created by a call to the forname () instead of more typical NEW calls. Although this JVM has also achieved our hopes, because it will be loaded into those classes before we need, but it is not certain that the behavior of the display is 100%. 1. Class tags In Java 1.1, you can use a second way to generate a handle of a Class object: Use "class tag". For the above programs, it looks like this: gum.class; this is not only simpler, but also safer because it will be checked during compilation. Since it cancels the need to call the method, the efficiency of the execution will be higher. Class tags can not only be applied to ordinary classes, but also applicable to interfaces, arrays, and basic data types. In addition, there is a standard field called Type for each basic data type package. The role of the TYPE field is to generate a handle of the Class object for the relevant basic data type, as shown below: ... Wait for ... 521 Page Table Skelips 11.1.2 Check before the shape, we know the RTTI form of the RTTI : (1) Classic modeling, such as "" ", use RTTI to ensure the correctness of the shape, and generate a ClassCastException violation after encountering a failure. (2) Represents the Class object of the object type. You can query the Class object to get useful running period. In C , the classic "Shape" is not executed in RTTI. It simply tells the compiler to treat objects as new types. Java wants to perform type checks, which is typically called "Type Security". The reason why it is called "discontinuation" is caused by historical arrangements of class layered structures. If a Circle is stamped into a Shape (geometric shape), it is called the traceable shape because the circle is just a subset of geometric shapes. Conversely, if Shape is molded to Circle, it is called a discontinuation. However, although we clearly know that Circle is also a Shape, the compiler can automatically trace the shape, but it cannot guarantee that a shape is definitely a Circle. Therefore, the compiler does not allow automatic discontinuation, unless the model is clearly specified. RTTI has three forms in Java. Keyword InstanceOf tells us that the object is not a specific type of instance (instance "instance"). It returns a Boolean value to use in the form of a problem, like this: if (x instanceof dog) ((DOG) x) .bark (); before the X-style to a Dog, the above IF statement will check Whether the object X is dependent on the DOG class.

Before you make a shape, if you don't have other information, you can tell your own object, then instanceof is very important - otherwise a ClassCastException violation. Our most general approach is to find a type (such as a triangle to be a purple), but the following program demonstrates how to mark all objects with instanceof. 522-524 Program In Java 1.0, there is a relatively small restriction on InstanceOf: only compare it with a named type, you cannot compare with the Class object. In the above example, everyone may think that all those instanceOf expressions are very troublesome. This is the case. But in Java 1.0, there is no way to let this work automatically - can't create a Vector of Class, and compare it to it. Everyone will eventually realize that such as a number of instanceOf expressions, the entire design may have problems. Of course, this example is just an idea - it is best to add a Static data member in each type, and then make it value in the builder to track counts. When writing a program, everyone may imagine the source control of the class and can freely change it. However, since the actual situation is not always, RTTI is particularly convenient. 1. Use the class tag petcount.java example to rewrite the class tag of Java 1.1. The results obtained are more clearly understood: 524-526 Page Program Here, the TypenAmes array has been deleted, and the type name is changed from the Class object. Note that this additional work is made: for example, the class name is not getBil, but C11.PetCount2.getbil, which contains the name of the package. It is also important to pay attention to the system to be able to classify and interface. It can also be seen that PETTYPES's creation module does not need to be surrounded by a try block because it will be checked in the compile period, and no violation is like class.Forname (). After PET is dynamically created, you can see that the random number has been restricted, between 1 and PETTYPES.LENGTH, and does not include zero. It is because zero represents PET.CLASS, and a normal PET object may not be interested. However, since PET.CLASS is part of PETTYPES, all PETs will be counted in a count. 2. Dynamic instanceOfjava 1.1 adds an IsInstance method to the Class class. Use it to dynamically call the InstanceOf operator. In Java 1.0, it can only be static (like the previous aspects). Therefore, all of those annoying instanceof statements can be deleted from the Petcount example. As shown below: 526-528 Program can be seen that the isinstance () method of Java 1.1 has canceled the need to instanceOf expression. In addition, this also means that once the new type of pets are required, simply change the PETTYPES array; do not need to change the remaining parts of the program (but it is required when instanceof is used). 11.2 RTTI syntax Java implements its own RTTI function with Class objects - even if we are going to do, only some of the work like styles. The Class class also provides a large number of ways to facilitate our use of RTTI. First, you must get a handle to the appropriate Class object. As in the pre-example demonstration, a way is to use a string and a class.forname () method. This is very convenient, because one of the types of objects do not require the Class handle.

However, for the type of interest, if there is an object, then in order to get the Class handle, one method that belongs to the root root class: getClass (). Its role is to return a specific Class handle to indicate the actual type of object. Class provides a few interesting and useful methods that you can see from the following example: 528-529 Page can be seen from it, Class Fancytoy is quite complicated because it inherits from Toy and implements Hasbatteries, WaterProof, and Shootsthings. Interface. A Class handle is created in Main () and initializes Forntoy with Forname () located within the corresponding TRY block. The Class.GetInterfaces method returns an array of Class objects to indicate an interface included in the Class object. If there is a Class object, you can also query the direct basic class of the object with GetSuperClass (). Of course, this will return a Class handle that can be used for further queries. This means that there is a complete hierarchy of the object to be investigated at the time of the running period. If viewed from the surface, the Class's newInstance () method seems to be a clone (Clone ()) another means of an object. But both are different. With newInstance (), we can create new objects without "clone" without ready-to-see objects. As with the program above, there is no Toy object at the time, only a handle of CY-ie y's Class object. Use it to implement the Virtual Builder. In other words, we express: "Although I don't know what your exact type is, please create yourself," In the above example, CY is just a Class handle, and there is no further type information during compilation. Once a new instance is created, the Object handle can be obtained. But that handle points to a Toy object. Of course, if you want any any messages that Object can receive, some survey studies must be carried out, and the shape is required. In addition, the class created with newinstance () must have a default builder. There is no way to create objects with non-default builders with newinstance (), so there may be some restrictions in Java 1.0. However, Java 1.1 "Reflection" API (next section discussion) allows us to dynamically use any builder in the class. The last way in the program is PrintInfo (), which gets a Class handle, get its name by getName (), and use interface () to investigate it. Is it an interface. The output of the program is as follows: 530 Page programs So use the Class object, and we can invest almost the 18th generation of an object. 11.3 Reflection: Running class information If you don't know the exact type of an object, RTTI will help us investigate. But there is a restriction: The type must be known during compilation, otherwise it cannot be investigated in RTTI, which in turn cannot expand the next step. In other words, the compiler must explicitly know all classes to be processed by RTTI. From the surface, it seems not a big limit, but if you get a handle of an object that is not in your own program space, what will happen? In fact, the object's class cannot be used by our program even during compilation. For example, suppose we get a series of bytes from a disk or network and is informed of those bytes represent a class. Since the compiler does not know the situation when compiling the code, how can I use this class smoothly? In traditional programming environments, this situation has probabilistic probability may be small.

But when we transferred to a larger programming world, we must attach this issue. The first thing to note is the component-based programming. In this environment, we use the "Rapid Application Development" (RAD) model to build a program project. RAD is typically built in the application build tool. This is a visual approach to the program (appearing on the screen). The icon representing the different components can be dragged into the form. Subsequently, the correct configuration is performed by setting the properties or values ​​of these components. The configuration during the design requires that any components can be "exemplified" (ie, they can be free to obtain them). These components also reveal some of their own content, allowing programmers to read and set various values. In addition, components for controlling the GUI event must reveal information related to the corresponding method so that the RAD environment helps programmers override these ways to drive these events. "Reflection" provides a special mechanism that detects available methods and generates method names. With Java Beans (Chapter 13, the Java 1.1 provides an infrastructure for this component-based programming. Another original power in the runtime query information is to create and execute an object on a remote system over a network. This is called "Remote Method Call" (RMI) that allows the Java program (version 1.1 or more) to use objects published or distributed by multiple machines. The distribution of this object may be caused by many reasons: I may have to make a calculated intensive job, want to split it, allowing other machines in an idle state to share some work, thus speeding up the progress. In some cases, you may need to control specific type tasks (such as "Operational Rules" in the multi-layer client / server architecture) placed on a special machine, so that this machine is described for those actions. A universal storage office. And it is convenient to modify this site to make it an impact on all aspects within the system (this is a particularly useful design idea because the machine is independent, so it can easily modify the software!). Distributed computing can also make further play certain dedicated hardware, which is particularly good at implementing some specific tasks - such as matrix reversal - but is too exaggerated for routine programming. In Java 1.1, the class class (detailed discussion above this chapter) has been extended to support the concept of "reflection". For the Field, Method, and the Constructor class (each implementation of the MemberInterface - member interface), they have added a library: java.lang.reflect. These types of objects are created by JVM at runtime, which is used to represent members of the unknown class. This will create a new object with the builder, read and modify the field associated with the Field object with the GET () and set () methods, and the method associated with the Method object with the Invoke () method. In addition, we can call methods getFields (), getMethods (), getConstructors (), return to an object array for representing fields, methods, and builders, respectively (in online documents, more information related to Class classes ). Therefore, the class information of anonymous objects can be completely revealed in the running period, and there is no need to know anything during compilation. Everyone should understand that "reflection" is not a magical place. When dealing with the same unknown type of object, JVM simply checks that object and investigates which particular class belongs to which particular class (like the previous RTTI). But after this, the Class object must be loaded before we do anything else.

Therefore, it is necessary for the specific type of .class file must be called by JVM (either in the local machine, you can get through the network). So the only difference between RTTI and "Reflection" is to turn on the RTTI, the compiler will open and check the .class file in the compile period. In other words, we can call all the methods of an object in a "normal" manner; but for "reflection", the .CLASS file is not available during compilation, but is turned on and checked by the runtime environment. 11.3.1 A class method extractor requires little need to directly use the reflection tool; the reason why they provide them in the language, just to support other Java features, such as object serialization (Chapter 10, Introduction), Java Beans, and RMI (behind this chapter) Introduction). However, we still need to dynamically extract information related to a class. A particularly useful tool is a class method extractor. As mentioned earlier, if you find a source code or online document, you can only see the method that is defined or covered in that class definition. There is still a lot of information in the base class. Fortunately, "Reflection" has done this, and it is available to write a simple tool to automatically display the entire interface. The following is a specific program: 533-534 Program Class method getMethods () and getConstructors () can return an array of Method and Constructors, respectively. Each class provides a further approach to resolve the names, parameters, and return values ​​of the methods they represent. But you can also use TOString () like this to generate a string containing a complete method. The residual part is only used to extract the command line information, and it is determined whether the specific signature is consistent with our target string (using indexof ()) and print out. The "reflection" technology is used here because the results generated by class.Forname () cannot be known during compilation, so all method signatures are extracted during operation. If you study the part of the "reflection" in the online document, it will find that it has provided sufficient support to actually set a fully unknown object, and a method call. Similarly, this also belongs to a step in which we worry about - Java will use this support, so the program design environment can control Java Beans, but it is very interesting. A fun test is to run Java Showmehods ShowMethods. Doing this gives a list, including a public default builder, although we don't define a builder in the code. We see the builder that is automatically synthesized by the compiler. If ShowMethods are set to a non-PUBLIC class (ie, replacing "friendly" classes), the synthetic default builder will not appear in the output result. The synthesized default builder automatically obtains the same access rights as class. SHOWMETHODS's output is still "uncomfortable". For example, the following is part of the output results obtained by calling Java ShowMethods Java.lang.String: 534-535 Program If you can go out of a qualified word like java.lang, the results will be more satisfactory. In view of this, it can be introduced into the StreamTokenizer class introduced in the previous chapter. Solve this problem: 535-537 Page program showMethodSclean method is very close to the previous showMethods, just it gains the Method and Constructor arrays and convert them into a single String array. Subsequently, each such String object is "over" in stripqualifiers.strip (), deletes all methods qualified words.

转载请注明原文地址:https://www.9cbs.com/read-4698.html

New Post(0)