java面向对象14多态性与instanceof关键字的理解

/*

  • java面向对象三大特性之多态性
  • 1,多态性可以理解为一个事物的多种形态
  • 2,对象的多态性:父类的引用指向子类的对象或者说子类的对象赋给父类的引用。
  • 3,多态的使用:虚拟方法调用
  • 子类中定义了与父类同名同参数的方法,在多态情况下,将此时父类的方法称为虚拟方法,父
  • 类根据赋给它的不同子类对象,动态调用属于子类的该方法。这样的方法调用在编译期是无法
  • 确定的。所以多态性是运行时行为,而非编译时行为。
  • 对象有了多态性以后,在编译期,只能调用父类中声明的方法,在运行时,实际执行的是
  • 子类重写父类的方法,编译看左侧,运行看右侧。
  • 4,多态性使用的前提,1,类有继承关2,子类中有重写的方法,否则没有必要使用多态性。
  • 5,多态性适用于方法,不适用于属性。属性的编译和运行都看左侧。
  • 若子类重写了父类方法,就意味着子类里定义的方法彻底覆盖了父类里的同名方法,系统将不可能把父类里的方法转移到子类中。
  • 对于实例变量则不存在这样的现象,即使子类里定义了与父类完全相同的实例变量,这个实例变量依然不可能覆盖父类中定义的实例变量
  • 6,方法重载与重写:
  • 重载,是指允许存在多个同名方法,而这些方法的参数不同。编译器根据方法不
  • 同的参数表,对同名方法的名称做修饰。对于编译器而言,这些同名方法就成了
  • 不同的方法。它们的调用地址在编译期就绑定了。Java的重载是可以包括父类
  • 和子类的,即子类可以重载父类的同名不同参数的方法。
  • 所以:对于重载而言,在方法调用之前,编译器就已经确定了所要调用的方法,
  • 这称为“早绑定”或“静态绑定”; 而对于多态,只有等到方法调用的那一刻,解释运行器才会确定所要调用的具体
  • 方法,这称为“晚绑定”或“动态绑定”。
  • 7,多态总结:
  • 多态的作用:提高代码通用性,常称作接口重用
  • 多态的前提:需要存在继承或者实现关系,子类中有方法的重写
  • 多态的效果:编译时:要查看引用变量所声明的类(父类)中是否有所调用的方法。运行时:调用实际new的对象所属的类(子类)中的重写方法。
  • 类中的属性:成员变量不具备多态性,只看引用变量所声明的类的属性。
  • 8有了对象的多态性以后,内存中依然加载了子类的属性和方法,由于对象声明为父类类型,导致编译时只能调用父类的属性和方法
  • ,子类特有的属性和方法无法调用。
  • 如果想要调用子类的属性和方法,需要使用向下转型的方式将对象转换为子类对象
  • 类似基本数据类型的强制转换会出现精度损失的问题,向下转型有可能失败(classcastexception)的问题,必须有继承关系才能向下转型。
  • 需要先用 instanceof关键字判断对象是否是类的实例,如实是返回true否则返回false。
  • 注意:多态(向上转型)与强制类型转换(向下转型)不限于直接父类和直接子类,父类对象可以被孙类赋值,使用孙类重写方法。
  • 也可以强制转换为孙类对象,调用孙类特有的属性和方法。
  • 9,类B为类A的父类, 如果对象a instanceof 类A为true,那么a instanceof B也为true。
  • 如果类C为类A的子类,那么对于A类的实例化对象a有a instanceof C为false。

**

个人理解

instanceof关键字判断的是,被判断的类A的结构是否存在于在对象a的内存结构中,如果有则返回true,否则返回false。

类C为类A的子类,包含超出类A的方法和属性,在对象a的内存结构中不存在,a instanceof C就会返回false,
类D与类A类B类C不存在继承关系,其中的结构在对象a的内存中也不存在,a instanceof D也会返回false。

也只有在返回true 的情况下,a才能调用类A的所有结构,强制转换才能成功。

类B为类A的父类, 当向上类型转换(多态性) B b = new A();时,b的内存空间中拥有父类B与子类A的所有结构,所以 b instanceof A 返回true,表示b可以向下转型为A的对象。

在 A a = (A)b;向下转型时,a可以调用类A的结构**

*/

package object_chapter2;

import java.util.Random;

public class Object_Polymorphism {
  public static void main(String[] args) {
	
	Person p = new Person();
	p.eat();
	System.out.println(p.number);
	p = new Man();//多态的形式,父类的引用指向子类的对象
	p.eat();//多态的使用,执行的是子类重写的方法,称作虚拟方法调用
	//p.work();//子类特有的方法无法调用
	System.out.println(p instanceof Man);//使用instanceof判断p的结构是否存在于Man类中
 	Man m = (Man)p;//使用向下转型的方式调用子类的方法
//	Women w = (Women)p;//可以编译过,但运行出错,p的结构中有Man类的结构,但Man类的部分结构与Women不同,无法强转到Women。
//	w.investigate();
	System.out.println(p instanceof Women);
	m.work();
	p = new Women();
	p.eat();
	System.out.println(p.number);//输出的依然是父类属性的值
	//p.investigate();
	Object_Polymorphism o = new Object_Polymorphism();
	o.function(new Person());//正常调用
	o.function(new Man());//参数使用子类对象赋值,执行子类重写方法
	o.function(new Women());
    int value = new Random().nextInt(2);//输出随机数,0或1
    System.out.println(value);
    Person p1 = o.getInstance(value);
    p1.eat();//输出结果根据随机数确定,说明多态性是运行时行为
    
    Base base = new Sub();//多态性,子类对象赋值
	base.add(1, 2, 3);//调用的是子类中的重写的方法,没有重写则调用父类中的方法

	Sub s = (Sub)base;//强制类型转换为sub类型的对象
	s.add(1,2,3);//先调用确定形参的方法,没有再调用可变形参的方法,都没有再调用父类方法
}
  public Person getInstance(int value) {
	  switch (value) {
	  case 0:
		return new Man();
	  default:
		return new Women();
	}
  }
  
  public void function(Person p) {//方法中参数声明的是父类person的对象
	  p.eat();//方法体中执行父类的方法
	   if(p instanceof Man) {
		  Man m = (Man)p;
		  m.game();
	  }else if(p instanceof Women) {
		  Women w = (Women)p;
		  w.shopping();
	  }
  }
//  public void function(Man m) {//使用多态性可以省略这些重载的方法
//	  m.eat();
//  }
//  public void function(Women w) {
//	  w.eat();
//  }
  public void method(Object obj) {//因为Object类是所有类的父类,此处可以用任意类的对象赋值
	
  }
  
}

class Person{
   String name;
   int age;
   int number = 2;
   void move() {
	   System.out.println("运动是放电");
   }
   void eat() {
	   System.out.println("进食是充电");
   }
   void talk(){
	   System.out.println("通话基本靠吼");
   }
   void walk() {
	   System.out.println("交通基本靠走");
   }
   
}

class Man extends Person{
	int number = 1;
	void eat() {
		System.out.println("吃得多,干的多");
	}
	void work() {
		System.out.println("努力工作赚钱");
	}
}

class Women extends Person{
	int number = 0;
	void eat() {
		System.out.println("吃的少,身材好");
	}
	void investigate() {
		System.out.println("收集信息,坐镇指挥");
	}
}

class Base {
	public void add(int a, int... arr) {
		System.out.println("base");
	}
}

class Sub extends Base {

	public void add(int a, int[] arr) {//可变形参与数组相同,构成方法的重写
		System.out.println("sub_1");
	}

    public void add(int a, int b, int c) {//不构成方法 的重写,构成重载
		System.out.println("sub_2");
	}

}
发布了47 篇原创文章 · 获赞 1 · 访问量 1059

猜你喜欢

转载自blog.csdn.net/wisdomcodeinside/article/details/104132920