Original address: http://www.cnblogs.com/wuyuegb2312/p/3858521.html
In the process of Java learning, for the transformation of this operation is more confused, especially summed up this article. Examples refer to "Java Programming ideas".
Directory
Several synonyms
Upward transformation and downward transformation
Example one: Upward transformation, invoking the specified parent class method
Example two: Upward transformation, dynamic binding
Example three: Upward transformation, static binding
Example four: Downward transformation
The misunderstanding of transformation
1. Operational information (RTTI)
2. Array type
3.Java container
several synonyms
First, there are several sets of synonyms. They appear on different books, which is one of the reasons for confusing understanding.
Parent class/Superclass/base class
Subclass/Export class/inheriting class/derived class
static binding/Early binding
Dynamic binding/Late binding/run-time binding
Transitioning to the top and transitioning to the bottomExample One: upward transformation, invoking the specified parent class method
ClassShape {
Staticvoid Draw (Shape s) {System.out.println ("shape draw.") ); }}Class Circle extends Shape {
static void Draw (circle C) {System.out.println ("circle draw.") ); }}public class casttest { public static void main (String args[]) {Circle c = new< c18> Circle (); Shape.draw (c); }}
Output to
Shape draw.
This indicates that the draw (shape s) method was originally designed to accept the shape reference, but the circle reference was passed here. Actually the draw (shape s) method can be used for all the export classes of the Shape class, which is called upward transformation. Behave in a manner consistent with the category in which the method belongs. in other words, because the method of the parent shape is clearly pointed out, its behavior is necessarily the corresponding behavior of the method, without any ambiguity.
The "Move Up" naming comes from the drawing of the class inheritance graph: The root is placed at the top, and then gradually downward, as in the example of two classes in this case, as shown in:
Example Two: upward transformation, dynamic binding
ClassShape {PublicvoidDraw () {System.out.println ("Shape draw.")); }}class Circle extendspublic void draw () {System.out.println ("Circle draw.") ); }}public classpublic static void Drawintest (Shape s) {S.draw ();} public static voidnew Circle (); Drawintest ( c); }}
Output to
Circle draw.
The reason for this is that a drawintest (shape s) can handle all the subclasses of a shape without having to provide its own method for each subclass. However, this method can invoke methods common to both the parent and subclass, and even if they behave in a inconsistent manner, they will only show the behavior of the corresponding subclass method. This is allowed by polymorphism, but is prone to confusion.
example Three: upward transformation, static binding
ClassShape {PublicStaticvoidDraw () {System.out.println ("Shape draw.")); }}Class CircleExtends Shape {public static Span style= "color: #0000ff;" >void draw () {System.out.println ("Circle draw.") ); }}public classpublic static void Drawintest (Shape s) {S.draw ();} public static voidnew Circle (); Drawintest (c); }}
Output to
Shape draw.
What is the difference between example three and example two? A closer look reveals that the method called in the example three-way is modified by static, resulting in a completely different result.
The reasons for these two behavioral differences are thatin addition to the static and final methods in Java, including private methods, other methods are dynamically bound. for an incoming base class reference, late binding correctly identifies the export class to which it belongs. Added to the static, naturally not get this effect.
Once you understand this, you can see why you have to write the example. The code in example one explicitly indicates the invocation of the parent class method, and the example three calls which method is statically bound, not directly indicated, a little bit around.
example four: downward transformation
From the Java Programming thought 8.5.2 section, a slight modification was made to show how to obtain access to the subclass's unique methods through type conversion.
This is equivalent to telling the compiler additional information that the compiler will examine accordingly.
ClassUseful {Publicvoid F () {System.out.println ("f () in useful");}Publicvoid G () {System.out.println ("g () in useful");}}Class MoreusefulExtendsUseful {Publicvoid F () {System.out.println ("f () in Moreuseful");}Publicvoid G () {System.out.println ("G () in Moreuseful");}Publicvoid U () {System.out.println ("U () in moreuseful");}}PublicClassRTTI {public static void< Span style= "color: #000000;" > main (string[] args) {useful[] x = {new useful (), new moreuseful ()}; X[0].F (); X[1].G (); // Compile-time:method not found in useful: //! x[1].u (); ((moreuseful) x[1]). U (); // Downcast/rtti ((moreuseful) x[0]). U (); // Exception thrown}}
Output
Exception in thread "main" java.lang.ClassCastException:Useful cannot is cast to moreuseful
At Rtti.main (rtti.java:44)
f () in useful
g () in moreuseful
U () in moreuseful
Although the parent class useful type x[1] receives a reference to a subclass Moreuseful object, it still cannot directly invoke the U () method in its subclass. If you need to call, you need to do a downward transformation. This usage is very common, such as a common method, the processing of the entry is a parent class, processing, according to the type information into the corresponding subclass using different logical processing.
In addition, the parent object cannot be converted down to a subclass object .
The benefits of downward transformation are evident when learning about interfaces (if you think of implementing interfaces as multiple inheritance). You can refer to the example of section 9.4, which is not detailed here:
InterfaceCanfight {voidFight ();}InterfaceCanswim {voidSwim ();}InterfaceCanfly {voidFly ();}ClassActioncharacter {PublicvoidFight () {}}Class HeroExtends ActioncharacterImplementsCanfight, Canswim, canfly {PublicvoidSwim () {}PublicvoidFly () {}}PublicClassAdventure {StaticvoidT (Canfight x) {x.fight ();}StaticvoidU (canswim x) {x.swim ();}Staticvoid V (canfly x) {x.fly ();} static void W ( Actioncharacter x) {x.fight ();} public static void< Span style= "color: #000000;" > main (string[] args) {Hero i = new Hero (); t (i); // Treat it as a canfight u (i); // Treat it as a canswim V (i); // Treat it as a canfly w (i); // Treat it as an actioncharacter }}
the misunderstanding of transformation
Transformation is convenient, and using transformation can write flexible code. However, if the use of arbitrary and carried away, it will inevitably fall. Here are a few things that appear to be transformational and actually lead to errors.
1. Operational information (RTTI)
/**/int.class
This code is invalid, the compilation does not pass, even if the int to the integer also does not pass. Although the wrapper class for int is the subclass of number, the integer class object is not a subclass of the number class object.
2. Array type
/*The code section overrides the Java Programming thought 15.8.2 section, which is not relevant to generics or not.*/Class generic<t> {}public class Arrayofgeneric {static final int SIZE = 100; static generic<integer>["GIA; @ Suppresswarnings ("Unchecked" public static void main (string[] args) {//! gia = (generic<integer>[]) new object[size]; gia = (generic<integer>[]) new Generic[size];}}
The comment section, which runs after the comment is removed, prompts java.lang.ClassCastException. The confusing part here is that the subclass array type is not a subclass of the parent array type . After the exception prompt, you can see
[Ljava.lang.Object; Cannot is cast to [Lgeneric;
In addition to the exception information that is output through the console, you can use the following code to see what kind of Gia is:
New object[size]; new generic[size]; System.out.println (Obj.getclass (). GetName ()); System.out.println (Gia.getclass (). GetName ()); System.out.println (Obj.getclass (). GetClass (). GetName ()); System.out.println (Gia.getclass (). Getsuperclass (). GetName ());
The console output is:
[Ljava.lang.Object;
[Lgeneric;
Java.lang.Object
Java.lang.Object
As can be seen, GIA and obj, defined by generic<integer>[] gia and object[] obj, do not have any inheritance at all, and naturally cannot type conversions, regardless of whether the object in this array is a subclass. (Subclass object can be obtained by upward transformation, if it is really a subclass object, see example IV)
3.Java Container
/*Code excerpt from "Java Programming thought" section 15.10*/class Fruit {}class Apple extends Fruit {}class Orange extends Fruit {}Public C10>class Test { public static void main (string[] args) { // cannot compile list<fruit> fru Itlist = new arraylist<apple>();}}
Why is the assignment failed when the list of fruit is able to store Apple objects? In fact, this is not an upward transformation. Although it is possible to learn list<fruit> and list<apple> through GetClass (). GetName () The genus Java.util.ArrayList type, however, assumes that it can be compiled here, equivalent to allowing an orange object to be stored to arraylist<apple>, which is obviously unreasonable. Although the generic erase,arraylist<fruit> and arraylist<apple> are the same type at run time, the type of element that can be held is checked at compile time.
[Turn] upward transformation and downward transformation