JAVA多态
概念
多态主要指同一种事物表现出来的多种形态。如:
• 饮料:可乐、雪碧、红牛、脉动、...
• 宠物:猫、狗、鸟、小强、鱼、...
• 人:学生、教师、工人、保安、...
• 图形:矩形、圆形、梯形、三角形、...
语法格式
父类类型 引用变量名 = new 子类类型(); 如:
Shape sr = new Rect();
sr.show();
特点
1.当父类类型的引用指向子类类型的对象时,父类类型的引用可以直接调 用父类独有的方法。
2.当父类类型的引用指向子类类型的对象时,父类类型的引用不可以直接 调用子类独有的方法。
3.对于父子类都有的非静态方法来说,编译阶段调用父类版本,运行阶段 调用子类重写的版本(动态绑定)。
4.对于父子类都有的静态方法来说,编译和运行阶段都调用父类版本。
demo code:
public class Shape {
private int x;
private int y;
public Shape() {
}
public Shape(int x, int y) {
setX(x);
setY(y);
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public void show() {
System.out.println("横坐标:" + getX() + ",纵坐标:" + getY());
}
// 自定义静态方法
public static void test() {
System.out.println("Shape类中的静态方法!");
}
}
public class Rect extends Shape { private int len; private int wid; public Rect() { } public Rect(int x, int y, int len, int wid) { super(x, y); setLen(len); setWid(wid); } public int getLen() { return len; } public void setLen(int len) { if(len > 0) { this.len = len; } else { System.out.println("长度不合理哦!!!"); } } public int getWid() { return wid; } public void setWid(int wid) { if (wid > 0) { this.wid = wid; } else { System.out.println("宽度不合理哦!!!"); } } @Override public void show() { super.show(); System.out.println("长度是:" + getLen() + ",宽度是:" + getWid()); } // 自定义静态方法 public static void test() { System.out.println("---Rect类中的静态方法!"); } }
public class ShapeRectTest { public static void main(String[] args) { Shape sr = new Rect(7, 8, 9, 10); // 当Rect类中没有重写show方法时,下面调用Shape类中的show方法 // 当Rect类中重写show方法后,下面的代码在编译阶段调用Shape类的方法,在运行阶段调用Rect类中的show方法 sr.show(); // 7 8 9 10 System.out.println("1.当父类类型的引用指向子类类型的对象时,父类类型的引用可以直接调 用父类独有的方法。2.当父类类型的引用指向子类类型的对象时,父类类型的引用不可以直接 调用子类独有的方法。");
int ia = sr.getX();
System.out.println("获取到的横坐标是:" + ia); // 7 //sr.getLen(); //error Shape类中找不到getLen方法,也就是还在Shape类中查找
// 使用父类类型的引用调用子类独有方法的方式
// 相当于从Shape类型到Rect类型的转换,也就是父类到子类的转换 大到小的转换 强制类型转换
int ib = ((Rect) sr).getLen();
System.out.println("获取到的长度是:" + ib); // 9
// 希望将Shape类型强制转换为Circle类型,下面没有报错
// Circle c1 = (Circle)sr; // 编译ok,但运行阶段发生 ClassCastException类型转换异常,Rect类无Circle
// 在强制类型转换之前应该使用instanceof进行类型的判断
// 判断sr指向堆区内存中的对象是否为Circle类型,若是则返回true,否则返回false
if(sr instanceof Circle) {
System.out.println("可以放心地转换了!");
Circle c1 = (Circle)sr;
} else {
System.out.println("强转有风险,操作需谨慎!");
}
}
}
引用数据类型之间的转换
1.引用数据类型之间的转换方式有两种:自动类型转换 和 强制类型转换。
2.自动类型转换主要指小类型向大类型的转换,也就是子类转为父类,也叫做向上转型。
3.强制类型转换主要指大类型向小类型的转换,也就是父类转为子类,也 叫做向下转型或显式类型转换。
4.引用数据类型之间的转换必须发生在父子类之间,否则编译报错。
5.若强转的目标类型并不是该引用真正指向的数据类型时则编译通过,运行阶段发生类型转换异常。
6.为了避免上述错误的发生,应该在强转之前进行判断,格式如下: if(引用变量 instanceof 数据类型) 判断引用变量指向的对象是否为后面的数据类型