文章目录
(一)多态的概念
1.多态,是面向对象的程序设计语言最核心的特征。按字面的意思就是“多种状态”。是允许将子类类型的对象定义成父类类型的一种技术。多态是通过子类重写父类的方法来实现的。
例如:Parent object = new Child();
2.多态是通过子类重写父类的方法来实现的。
3.多态性使得能够利用同一类(基类)类型来引用不同类的对象,以及根据所引用对象的不同,以不同的方式执行相同的操作。
4.虽然子类被定义成父类类型,但是通过“父类对象.方法()”的方式,实际调用的还是子类的代码。这也说明了“父类类型”只是一个“傀儡”,真正发号施令还是子类。
5.如果子类,没有重写父类的方法,默认调用父类中的方法。
前提:有继承关系,且有方法的重写。
多态的作用:把不同的子类对象都当作父类来看,可以屏蔽不同子类对象之间的差异,写出通用的代码,做出通用的编程,以适应需求的不断变化。
补充:
- 多态后的对象不能调用父类中私有的方法。
- 多态后的对象会屏蔽掉子类独有的属性。
- 多态后的对象会屏蔽子类独有的方法。
(二)多态的例子
这里书写两种例子,简便的和一种便于深入理解的。
(1)第一种
//子类
public class Dog extends Animal {
// 构造方法
public Dog() {
}
}
//父类
public class Animal {
public int age;
public Animal() {
}
public void run(){
}
}
public class DogTest {
public static void main(String[] args) {
Animal dog=new Dog();//声明Animal类对象,可调用Animal的方法
Dog.run();
}
}
(2)第二种
class Super {
public void test() {
System.out.println("super is calling!");
}
}
class Sub1 extends Super {
public void test() {
System.out.println("sub1 is calling!");
}
}
class Sub2 extends Super {
public void test() {
System.out.println("sub2 is calling!");
}
}
class Sub3 extends Super {
public void test() {
System.out.println("sub3 is calling!");
}
}
public class SamplePolymorphism {
public static void main(String[] args) {
test1(); // 未使用多態
System.out.println("------華麗的-----------------------分割線-----");
test2(); // 使用多態
System.out.println("------華麗的-----------------------分割線-----");
}
private static void test1() {
Super s = new Super();
Sub1 s1 = new Sub1();
Sub2 s2 = new Sub2();
Sub3 s3 = new Sub3();
s.test();
s1.test();
s2.test();
s3.test();
}
private static void test2() {
Super s = new Super();
Super s1 = new Sub1();
Super s2 = new Sub2();
Super s3 = new Sub3();
s.test();
s1.test();
s2.test();
s3.test();
}
private static void test3() {
for (int i = 0; i < 9; i++) {
Super s = rand();
s.test();
}
}
}
运行结果:
super is calling!
sub1 is calling!
sub2 is calling!
sub3 is calling!
------華麗的-----------------------分割線-----
super is calling!
sub1 is calling!
sub2 is calling!
sub3 is calling!
test()方法设置为static,运行结果有什么不同?
super is calling!
sub1 is calling!
sub2 is calling!
sub3 is calling!
------華麗的-----------------------分割線-----
super is calling!
super is calling!
super is calling!
super is calling!
出现这种结果有多态中方法的静态和非静态的原因导致下文有说明。
public class Animal {
public static String name;
// public String name;
public int age;
}
public class Dog{
public static String name;
public int age ;
}
public class DogTest {
public static void main(String[] args) {
Animal.name="hello";
Dog.name="world";
Animal ani = new Dog();
ani.name="tom";
System.out.println(ani.name);
System.out.println(Animal.name);
System.out.println(Dog.name);
}
}
}
输出结果:
tom
tom
null
此时ani为Animal类型绑定。
屏蔽Dog中的 public static String name;结果:
tom
tom
tom
如果子类父类中都用非静态声明,此时需要new新对象来调用,此时三个变量皆为独立的。
输出结果:
tom Animal ani = new Dog();
jerry Animal ani1 = new Animal();
null Dog ani2 = new Dog();
(三)多态确定对象的类型
(1)通过instanceof运算符来确定对象是否属于这个类型
/*
* instanceof:判断对象是否是某个类(包括继承的父类)的实例
* 缺点:不能准确的判断该对象是Dog的实例,如果该对象是类的子类对象也会返回true
*/
public static void main(String[] args) {
Animal ani1= new Dog();
Animal ani2 = new Cat();
Animal ani3 = new Husky();
System.out.println(isDog(ani1));
}
//判断ani1是否是Dog类型
public static boolean isDog(Animal ani) {
if (ani instanceof Dog) {
return true;
}
return false;
}
(2)通过getClass().getName()取得该类真正的类名
//通过对象.getClass().getName()获取对象的实例类名
public static boolean isDog1(Animal ani) {
// 对象.getClass():返回该对象对应的Class对象
// 对象.getClass().getName():该对象对应的class对象的全类名
// String str = ani.getClass().getName();
// System.out.println(str);
if(ani.getClass().getName().equals(Dog.class.getName())) {
return true;
}else {
return false;
}
}
(四)静态和非静态的区别
1.多态是通过子类重写父类的方法来实现的。但是如果该方法是静态的,多态就不起作用。(或者是final的也不行)。对于父类子类中具有相同名字的静态变量,也会遵从这个结果,就是此时子类静态成员变量并不能覆盖掉父类静态成员变量,因为此时成员变量被绑定。
2.通过new关键字创建的对象数据存放在堆内存中,创建之后才能通过“对象名.方法名()”的方式使用。
3.Java的内存中,除了栈和堆以外,还有一个称为方法区(或称为持久代)的区域,用来存放静态数据。一个类只会存在一份数据,而且不需要创建对象就可以使用,可以直接使用“类名.方法名()”或“类名.变量名”的方式调用。
(五)静态变量和静态方法
1.静态变量:
- 既可以直接使用“类名.静态变量名”的方式使用,也可以使用“对象名.静态变量名”的方式使用。
- 因为一个类的静态数据在方法区中只有一份,因此同一种类型的对象共用同一份数据。即“对象名1.静态变量名”和“对象名2.静态变量名”和“类名.静态变量名”得到的数据是相同的。
2.静态方法:
- 在静态方法里只能直接调用同类中其它的静态成员(包括变量和方法),而不能直接访问类中的非静态成员。
- 静态方法也不能使用this和super关键字。因为在this和super是在实例化之后。
(六)方法绑定
1.Java允许在类中声明两种方法:类(静态)方法和实例方法。类方法称为静态方法,实例方法称为非静态方法。
2.将方法的调用绑定到类称为“静态方法绑定”,绑定到对象是称为“动态方法绑定”。
3.多态就是应用了“动态方法绑定”,因此只有非静态方法才能使用多态。故如果该方法是静态的,多态就不起作用。(或者是final的也不行) 。