对象的创建
对象在创建时,会调用该类的构造方法,如果不显示地写出,则Java会提供一个隐式构造方法。如果显示的定义了,将不再提供隐式构造方法。
子类中未显示调用父类的构造方法时,Java会隐式调用父类的无参构造方法。
注意:当父类定义了带参数的构造方法并且未定义无参的构造方法时,子类会自动定义一个构造方法隐式或显示地调用父类的无参的构造方法,此时就会报错。
上转与下转
向上转型——父类引用指向子类类型实例。
格式:父类类型 变量名 = new 子类类型();
向下转型——把子类创建实例赋值给父类引用,然后把父类引用向下强转给子类引用。
格式:父类类型 变量名 = new 子类类型();
子类类型 变量名2 = (子类类型) 变量名;
上转类型对象可以访问——父类成员变量 & 父类特有成员方法、子类重写的成员方法
下转类型对象可以访问——子类成员变量、父类特有成员变量 & 子类成员方法、父类特有成员方法
实际上使用上转类型对象时,调用成员方法是动态的绑定到了子类重写的成员方法上。——这是Java中多态(运行时多态)的本质。
下转类型对象在强制类型转换时可能会抛出ClassCastException异常外和一般的直接创建的子类在使用时没有区别。
注意:对于静态成员来说,不存在多态,子类并不会重写父类的静态方法。
父类
1 public class SuperClass { 2 /* private */ public String id = "SuperClass"; 3 public String superU = "SuperClassU"; 4 5 public static void staticMethod() { 6 System.out.println("SuperClass staticMethod"); 7 } 8 9 public SuperClass() { 10 super(); 11 System.out.print("父类无参构造方法 "); 12 } 13 14 public SuperClass(String id) { 15 this.id = id; 16 System.out.print("父类带参构造方法 "); 17 } 18 19 public void method() { 20 System.out.println("父类method()方法"); 21 } 22 23 public void superClassMethod() { 24 System.out.println("父类SuperClassMethod()方法"); 25 } 26 }
子类
1 public class SubClass extends SuperClass { 2 /* private */ public String id = "SubClass"; 3 public String subU = "SubClassU"; 4 5 public static void staticMethod() { 6 System.out.println("SubClass staticMethod"); 7 } 8 9 // Implicit super constructor SuperClass() is undefined for default constructor. 10 // Must define an explicit constructor 11 /* 12 * 当父类定义了带参数的构造方法并且未定义无参的构造方法时,子类会自动定义一个无参的构造方法调用父类的无参的构造方法,此时就会报错 13 */ 14 15 public SubClass() { 16 // super(); 17 /* 18 * 即使不加super()也默认调用 19 */ 20 System.out.println("子类无参构造方法"); 21 } 22 23 public SubClass(String id) { 24 // super(); 25 this(); 26 // super("SubClass->SuperClass"); 27 this.id = id; 28 System.out.println("子类带参构造方法"); 29 // super(); 30 // Constructor call must be the first statement in a constructor 31 /* 32 * 1.调用父类或子类的构造方法必须写在最前面,且只能有一个, 33 * 34 * 2.无论子类的构造方法是否带参数,只要不显示调用父类的构造方法,默认都会调用父类的无参构造方法 35 */ 36 37 } 38 39 /* 40 * Recursive constructor invocation SubClass(String, int) 41 * 42 * 构造器中出现了递归调用。 这是不被允许的。 重载的构造器之间彼此互相调用、构造器调用自身,都会出现此编译错误。 43 */ 44 // public SubClass(String id,int i) { 45 // this(id,i); 46 // this.id = id; 47 // } 48 49 /* 50 * 有关方法重写,当返回值类型、方法名。参数都一样时,这时已经是重写了父类的方法了,不能通过改变权限修饰符来改变子类已经重写父类方法的这种状态 51 */ 52 public void method() { 53 System.out.println("子类method()方法"); 54 } 55 56 public void subClassMethod() { 57 System.out.println("子类SubClassMethod()方法"); 58 } 59 }
测试类
1 public class Test { 2 public static void main(String[] args) { 3 SubClass tex1 = new SubClass(); 4 SuperClass tex2 = new SubClass(); 5 6 System.out.println(tex1.id); 7 System.out.println(tex2.id); 8 /* 9 * 对于上转类型对象来说,当子类不会覆盖父类的成员变量 10 * 11 * 使用 对象.成员名 这种方法时,即便是父类成员变量使用private指定,.出来的上转类型对象的成员变量仍是父类的,且无法访问 12 * 13 * The field SuperClass.id is not visible 14 * 15 * 非上转类型对象,子类会覆盖父类的成员变量 16 */ 17 18 SubClass tex3 = new SubClass("SubClass_SubClassText"); 19 SuperClass tex4 = new SubClass("SuperClass_SubClassText"); 20 21 System.out.println(tex3.id); 22 System.out.println(tex4.id); 23 24 tex1.method(); 25 tex2.method(); 26 tex1.superClassMethod(); 27 tex2.superClassMethod(); 28 // tex2.SubClassMethod(); 29 // The method SubClassMethod() is undefined for the type SuperClass 30 /* 31 * 上转类型对象具有父类成员变量、父类特有的方法以及子类重写的方法 32 * 33 * 若想调用子类特有的变量及方法需要进行下转 34 */ 35 SubClass tex5 = (SubClass) tex2; 36 tex5.subClassMethod(); 37 System.out.println(tex2.id); 38 System.out.println(tex5.id);// 子类的id 39 System.out.println(tex2.superU); 40 // System.out.println(tex2.subU);//subU cannot be resolved or is not a field 41 System.out.println(tex5.subU); 42 System.out.println(tex5.superU); 43 // tex2.subClassMethod();//The method subClassMethod() is undefined for the type SuperClass 44 tex5.superClassMethod(); 45 /* 46 * 下转类型对象具有子类成员变量、父类特有的成员变量以及子类成员方法以及父类特有的成员方法。 47 * 48 * 下转类型对象与子类的对象没有差别。 49 */ 50 tex1.superClassMethod(); 51 System.out.println(tex1.superU); 52 tex2.staticMethod();// 父类的 53 tex5.staticMethod();// 子类的 54 } 55 }
参考