Notifier's Blog

常遇困境,说明你在进步!
       常有压力,说明你有目标!
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

      多态是一个之前一直搞不清楚的概念,通过这次笔记,对多态的概念及应用有了较全面的认识,同时学习了instanceof关键字以及Object类的特点.

1. Java中类的多态

      所谓类的多态性,是指子类对象和父类对象之间的相互转换. 这里分为两部分做笔记: 

   1.1 子类对象向父类对象转换(向上转换)

      子类对象向父类对象的转换是自动转换.格式为: 父类对象 = 子类对象.

      这里需要注意的一点事: 子类对象转换为父类对象后,所调用的方法一定会是子类复写后的方法而非父类原有方法.

      例如下面的例子:      

class Person
{
	public void fun1()
	{
		System.out.println("Person -------> public void fun1() ");
	}
	public void fun2()
	{
		//fun2()调用的是fun1()的方法
		this.fun1();
	}
}
class Student extends Person
{
	//复写Person类中的fun1()方法
	public void fun1()
	{
		System.out.println("Student -------> public void fun1()");
	}
	public void fun3()
	{
		System.out.println("Student -------> public void fun1()");
	}
}
public class Demo01
{
	public static void main(String args[])
	{
		//声明一个父类对象
		//new Student()是实例化一个子类对象,向父类对象转换
		//子类对象向父类对象转换之后,所调用的方法一定是子类复写后的方法
		Person p = new Student();
		p.fun1();
		p.fun2(); //这里也是通过this.fun2()调用的子类复写后的方法fun1()
	}
}

   1.2 父类对象向子类对象转换(向下转换)

      父类对象向子类对象的转换是强制转换. 格式为: 子类对象 = (子类名称) 父类对象

      在父类对象向子类对象的转换的过程中,需要注意的是: 如果父类对象是实例化的父类对象而不是用子类对象转换过来的对象,则不能在强制转换为子类对象,否则会出现ClassCastException类转换异常. 也就是说,能进行父类对象向子类对象转换的前提是: 之前是使用子类对象的实例来初始化得父类对象. 例如下面例子中,是先使用实例化的子类对象转换为父类对象的.      

class Person
{
	public void fun1()
	{
		System.out.println("Person -------> public void fun1() ");
	}
	public void fun2()
	{
		//fun2()调用的是fun1()的方法
		this.fun1();
	}
}
class Student extends Person
{
	//复写Person类中的fun1()方法
	public void fun1()
	{
		System.out.println("Student -------> public void fun1()");
	}
	public void fun3()
	{
		System.out.println("Student -------> public void fun1()");
	}
}
public class Demo02
{
	public static void main(String args[])
	{
		//声明一个父类对象, new Student()是实例化一个子类对象,该子类实例化对象向父类对象转换
		//父类对象向子类对象的转换,必须经过强制转换.
		/* 注意: 若父类对象是实例化为父类对象而不是下例中用子类对象实例化后转换为父类对象,
		那这时候就不能再强制转换为子类对象了,否则会有ClassCastException类转换异常 */
		Person p = new Student();
		Student s = (Student) p;
		s.fun3();
		s.fun1();
	}
}

   结论:

      在进行向下转换之前,两个对象必须先发生向上转换关系(如上面例子),否则无法转换(出现类转换异常).


2. instanceof关键字

      instanceof用于判断某个对象是否是某个类的实例. 例如: a instanceof B 若a是B的实例,则返回true,否则返回的是false. 

   instanceof的使用时机:

      例如下例,一般情况下, 都是在转型之前使用instanceof进行一下判断,这样可以进行比较安全的类型转换.      

class A
{
	public void fun1()
	{
		System.out.println("A --> public void fun1()") ;
	}
	public void fun2()
	{
		// fun2方法调用的是fun1方法
		this.fun1() ;
	}
}
class B extends A
{
	// 覆写A类中的fun1()方法
	public void fun1()
	{
		System.out.println("B --> public void fun1()") ;
	}
	public void fun3()
	{
		System.out.println("B --> public void fun3()");
	}
}
class C extends A
{
	// 覆写A类中的fun1()方法
	public void fun1()
	{
		System.out.println("C --> public void fun1()") ;
	}
	public void fun5(){
		System.out.println("C --> public void fun5()");
	}
}
public class Demo03{
	public static void main(String args[])
	{
		fun(new C()) ;
	}
	/* 如果传入的是B类的对象,则要求再调用fun3()方法;
	如果传入的是C类的对象,则要求再调用fun5()方法。
	这样,通过instanceof,实现了判别某个对象到底是谁的实例 */
	public static void fun(A a)
	{
		a.fun2() ;
		//如果a是B的实例化对象,则调用fun3()
		if(a instanceof B)
		{
			B b = (B)a;
			b.fun3() ;
		}
		//如果a是B的实例化对象,则调用fun5()
		if(a instanceof C)
		{
			C c = (C)a ;
			c.fun5() ;
		}
	}
}


3. Object类

      所有的类都继承自Object类,这是所有类的一个基类.

      一个比较好的类,需要复写Object类中的三个方法.

   |- public String toString()     

   |- public boolean equals(Object obj)

   |- public int hashCode()

      在下面的例子中,类Student复写了上面的toString()方法和equals()方法,而且使用到了instanceof关键字,算是一个小复习题目了~      

class Student  //任意类都是继承了Object类,最好复写里面的toString()和equals()方法
{
	private String name;
	private int age;
	public Student(String name,int age)
	{
		this.name = name;
		this.age = age;
	}
	
	//复写Object类中的toString()方法,实现自定义toString()
	public String toString()
	{
		return "该学生的姓名是: "+name+",该学生的年龄是: "+age;
	}
	//复写Object类中的equals()方法,注意,Object类中equals()接收的是Object对象
	public boolean equals (Object obj)
	{
		//如果被比较对象和比较对象的内存地址都是一样的,那肯定是同一对象
		//注意: 内存地址的比较使用"=="
		if (this == obj)
		{
			return true;
		}
		else
		{
			//如果obj不是Student的实例,肯定不相等了,返回false;
			if(!(obj instanceof Student))
			{
				return false;
			}
			else
			{	
				//走到这步,说明obj是Student的实例对象,进行类型转换后对比之
				Student stu = (Student) obj;
				if(this.name.equals(stu.name)&&this.age == stu.age)
				{
					return true;
				}
				else
				{
					return false;
				}			
			}
		}
	}
}
public class Demo04
{
	public static void main(String args[])
	{
		Student stu1 = new Student("newsainton",23);
		Student stu2 = new Student("newsainton",23);
		
		//使用toString()方法输出stu1对象
		System.out.println(stu1.toString());
		//使用toString()方法输出stu2对象
		System.out.println(stu2.toString());
		//比较stu1和stu2是否相等
		System.out.println("比较stu1和stu2是否相等: "+ stu1.equals(stu2));
	}
}