用一句话概括就是:事物在运行过程中存在不同的状态。
比如:你是儿子,虽然你继承了你爸,但是你也有自己的特点。

多态的存在的三个必要条件:
1.要有继承关系;
2.子类要重写父类的方法;
3.父类引用指向子类对象;

下面给到一个简单的例子来说明:

package luhan;
class A{
	int age=16;
	static int score=100;
	public void eat()
	{
		System.out.println("A chi");
	}
	public static void he()
	{
		System.out.println("A he");
	}
	public void run()//仅父类有
	{
		System.out.println("A run");
	}
}
class B extends A{
	int age=16;
	static int score=100;
	String name="luhan";
	public void eat()
	{
		System.out.println("B chi");
	}
	public static void he()
	{
		System.out.println("B he");
	}
	public void sleep()//仅子类有
	{
		System.out.println("B sleep");
	}
}
public class DuoTai {
	public static void main(String[] args) {
		A a=new B();
		System.out.println(a.age);//普通成员变量
		System.out.println(a.score);//静态成员变量
		a.eat();
		a.he();
		a.run();
		//a.sleep();//连编译都不能成功
		/**运行结果:
		 * 	16
			100
			B chi
			A he
			A run
			可以看出来,只有非静态成员函数,运行时候按照子类对象的来。
		 */
		
	}
}

以上代码可以看出发生了多态:
①B继承A;
②B中重写了父类A的方法;
(B中重写了A中的eat()和he()方法
其中eat()是非静态成员函数,he()是静态成员函数)
③父类引用指向子类对象;(A a=new B())
以上代码的运行结果为:

16
100
B chi
A he
A run
那么我们可以根据以上情况总结出多态成员访问的特点:
成员变量
编译看左边(父类),运行看左边(父类)
成员方法
编译看左边(父类),运行看右边(子类)。动态绑定
静态方法
编译看左边(父类),运行看左边(父类)。
(静态和类相关,算不上重写,所以,访问还是左边的)
只有非静态的成员方法,编译看左边,运行看右边。
那么多态有什么弊端呢?有的,即多态后不能使用子类特有的属性和方法。

a.sleep();//连编译都不能成功
为什么???

原因就是多态的弊端,就是:不能使用子类特有的成员属性和子类特有的成员方法。
如果在代码执行过程中还想使用子类中特有的属性和它特有的成员方法了。怎么办呢?那我们就可以把这个父类引用指向了子类对象的家伙a再强制变回b类型。这样b就是A类型的引用了,指向的也是A对象了,自然也能使用A类的一切属性和一切的成员方法。

虽然它有缺点,但是它确实十分灵活,减少多余对象的创建,不用说为了使用子类的某个方法又去重新再堆内存中开辟一个新的子类对象。