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
Move up and down transformation Example one: Move up, invoke the specified parent class method
Class Shape {
static void 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 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
Class Shape {public void Draw () { System.out.println ("Shape draw.");} } Class Circle extends Shape {public void Draw () { System.out.println ("Circle draw.");} } public class Casttest {public static void Drawintest (Shape s) { s.draw (); } public static void Main (String args[]) { Circle c = new 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
Class Shape {public static void Draw () { System.out.println ("Shape draw.");} } Class Circle extends Shape {public static void Draw () { System.out.println ("Circle draw.");} } public class Casttest {public static void Drawintest (Shape s) { s.draw (); } public static void Main (String args[]) { Circle c = new 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.
Class Useful {public void F () {System.out.println ("f () in useful");} public void G () {System.out.println ("g () in useful");}} Class Moreuseful extends useful {public void F () {System.out.println ("f () in Moreuseful");} public void G () {System.out.println ("G () in Moreuseful");} public void U () {System.out.println ("U () in moreuseful");}} public class RTTI {public static void 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:
Interface Canfight { void Fight ();} Interface Canswim { void Swim ();} Interface Canfly { void Fly (); Class Actioncharacter {public void fight () {}}class Hero extends Actioncharacter implements Canfight, Canswim, Canfly {Public void swim () {} public void Fly () {}}public class Adventure { static void T (Canfight x) {x.fight (); } static void U (Canswim x) {x.swim ();} static void V (Canfly x) {x.fly ();} static void W (Actioncharacter x) {x.fight ();} public static void 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)
/* This example code excerpt from the Java Programming thought 14.2.2 section */class<number> Genericnumberclass = 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 =; 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:
object[] obj = new Object[size]; Gia = (generic<integer>[]) 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 ideas" 15.10 */class Fruit {}class Apple extends Fruit {}class Orange extends Fruit {}public class Test { p Ublic static void Main (string[] args) { //cannot compile list<fruit> fruitlist = new arraylist<apple> ();} }
Source: http://www.cnblogs.com/wuyuegb2312/p/3858521.html
Java up, down transformation