1.1 可以理解为事物存在的多种体现形态
1.2 多态的体现
父类引用指向子类对象
例:动物中猫,狗。
猫这个对象对应的类型是猫类型:猫 x = new 猫();
同时猫也是动物中的一种,也可以把猫称为动物:动物 y = new 猫();
动物是猫和狗具体事物中抽取出来的父类型。
当父类型引用指向了子类对象的时候,就产生了多态。
1.3 多态的前提
必须是类与类有关系,继承或者实现。
通常还有一个前提:子类覆盖父类方法。
1.4 示例
public class H_0802Duotai
{
public static void main(String[] args)
{
function(new Dog());
function(new Cat());
function(new Pig());
Animal a=new Cat();
a.eat();
//System.out.println(a.x);
}
public static void function(Animal a)
{
a.eat();
}
}
abstract class Animal
{
int x=3;
abstract void eat();//抽象方法
}
class Cat extends Animal
{
int x=5;
public void eat()
{
System.out.println("吃鱼");//复写
}
public void catchMouse()
{
System.out.println("抓老鼠");//特有方法
}
}
class Dog extends Animal
{
public void eat()
{
System.out.println("吃骨头");
}
public void kanJia()
{
System.out.println("看家");
}
}
class Pig extends Animal
{
public void eat()
{
System.out.println("吃饲料");
}
public void gongDi()
{
System.out.println("拱地");
}
}
结果:
吃骨头
吃鱼
吃饲料
吃鱼
1.5 多态的局限性
只能使用父类的引用访问父类中的成员
1.6 多态的好处
提高了代码的扩展性,前期定义的代码可以使用后期的内容。
2. 多态的转型
2.1 Animal a=new Cat();
转型时使用子类方法
属性还是父类属性。
2.2 向上转型。要调用猫的特有方法(catchMouse),强制转型
Cat c=(Cat)a;//a本身必须是猫
可以将父类引用进行转换,不可以将父类对象转换成子类对象
注意:多态自始至终都是子类对象在做变化。
2.3 判断类型是否符合用instanceof关键字
格式:<对象 instanceof类型> ,判断一个对象是否所属于指定的类型。
If(a instanceof Cat){}
3. 多态时成员的特点
3.1 成员变量
编译时:参考引用型变量所属的类中的是否有调用的成员变量。有,编译通过,没有,编译失败。
运行时:参考引用型变量所属的类中的是否有调用的成员变量,并运行该所属类中的成员变量。
简单说:编译和运行都参考等号的左边(父类)。
3.2 成员函数
编译时:参考引用型变量所属的类中是否有调用的函数。有,编译通过。没有,编译失败。
运行时:参考的是对象所属的类中是否有调用的函数。
简单说:编译看左边(父类有没有),运行看右边(子类复写后)。
3.3 静态函数
编译时:参考的是对象所属的类中是否有调用的函数。
运行时:参考的是对象所属的类中是否有调用的函数。
简单说:编译和运行看左边。
示例
public class H_0805Duotai
{
public static void main(String[] args)
{
Fu f=new Zi();
f.method1();
f.method2();
//f.method3(); 编译失败,编译时先找f类型中的方法,如果没有,编译失败。
//运行时,是看newZi() 对象中的方法,没有的时候调用父类(继承)
//方法:编译看左边 运行看右边
System.out.println(f.x);//结果是5,看父类
// 成员属性:多态过程中,无论编译和运行,都是参考左边。
//静态函数不会重写,谁调用谁使用。
Zi z=new Zi();
z.method1();//zi method 1
z.method2();//fu method 2 子类没有,调用父类
z.method3();//zi method 3
}
}
class Fu
{
int x=5;
void method1()
{
System.out.println("fu method 1");
}
void method2()
{
System.out.println("fu method 2");
}
}
class Zi extends Fu
{
int x=3;
void method1()
{
System.out.println("zi method 1");
}
void method3()
{
System.out.println("zi method 3");
}
}
结果:
zi method 1
fu method 2
5
zi method 1
fu method 2
zi method 3
Object类:所有类的直接或者间接父类。Java认为所有的对象都具备一些基本的共性内容,这些内容可以不断的向上抽取,最终就抽取到了一个最顶层的类中的,该类中定义的就是所有对象都具备的功能。
重要方法:
1、 boolean equals(Object obj):
用于比较两个对象是否相等,其实内部比较的就是两个对象地址。
而根据对象的属性不同,判断对象是否相同的具体内容也不一样。所以在定义类时,一般都会复写equals方法,建立本类特有的判断对象是否相同的依据。
public class ObjectTest
{
public static void main(String[] args){
Person p1 = new Person(20);
Person p2 = new Person(20);
System. out.println(p1.equals(p2));
}
}
class Person
{
private int age ;
Person( int age)
{
this.age =age;
}
//比较Person的年龄,是否是同龄人
//一般都会覆盖此方法,根据对象的特有内容,建立判断对象是否相同的依据。
public boolean equals(Object obj)
{
if(!(objinstanceof Person))
throw new ClassCastException("类型错误");
Person p = (Person)obj;
return this .age == p.age;
}
}
结果: true
2、 String toString():
将对象变成字符串;默认返回的格式:类名@哈希值 = getClass().getName() + '@' + Integer.toHexString(hashCode())
为了对象对应的字符串内容有意义,可以通过复写,建立该类对象自己特有的字符串表现形式。
public String toString(){
return "person :"+age;
}
3、Class getClass():获取任意对象运行时的所属字节码文件对象。
4、int hashCode():返回该对象的哈希码值。