本系列博客汇总在这里:Java系列_汇总
目录
- 一、继承多态
- 二、接口多态
一、继承多态
我们通常使用抽象类来抽象要使用多态的方法。
1、继承多态特点
- 必须要有继承关系,在抽象类中可以定义多态的抽象方法,通过子类来继承这个抽象然后复写抽象类中的抽象方法已达到多态的效果。
- 多态子类的实例可以赋给父类的引用。
- 示例
abstract class Teacher
{
String name;
public abstract void TeachLesson();
}
class JavaTeacher extends Teacher
{
public void TeachLesson()
{
System.out.println(name+"老师在上Java");
}
}
class PHPTeacher extends Teacher
{
public void TeachLesson()
{
System.out.println(name+"老师在上PHP");
}
}
class Leader
{
public void CheckTeacher(Teacher ja)
{
String teacher = "";
//instanceof可以判断我们多态的引用变量到底是什么类型,提前知道那个老师来了
if(ja instanceof JavaTeacher)
{
teacher = "java老师";
}
else if(ja instanceof PHPTeacher)
{
teacher = "PHP老师";
}
System.out.println("开始考察"+teacher);
//System.out.println(name+"接受检查");
ja.TeachLesson();
System.out.println("结束");
}
}
class Welcome
{
public static void main(String[] args)
{
//多态子类的实例可以赋给父类引用,父类不能调用子类里独有的方法
Teacher jt = new JavaTeacher();
jt.name = "张三";
jt.TeachLesson();
Teacher pt = new PHPTeacher();
pt.name = "李四";
pt.TeachLesson();
Leader ld = new Leader();
ld.CheckTeacher(jt);
ld.CheckTeacher(pt);
}
}
2、继承多态的内存结构
- 示意图
首先类 Test 进栈,随之 main() 方法就会放在方法区之中,再往下走到 Teacher 这个定义,发现他是一个父类,这个父类就会加载到虚拟机当中,当中的方法就会进入到方法区(包括 TeachLesson() 等方法,一 new 的时候就进入了),抽象的方法进入方法区没有意义,但是其他的方法会进入方法区 ;在实例化类Javateacher之后就会在堆内存当中开辟一个空间(Javateacher)来存放这个类的数据,如这个类拥有的属性 name,此处给一个假定的地址 0x999,这个地址就表示 Javateacher 这个类在堆内存当中所存放的地址,同时,在栈内存当中也会有一个相应的地址 来引用堆内存当中的地址,栈中的这个地址有一个名字,那就是 jt,同理,类 Leader 也是一样的。
Main() 方法先进栈,存在于栈底,TeachLesson(),CheckTeacher(Teacher ja) 的位置如图所示,子类的实例赋给父类引用,从代码以及内存图上容易理解,传到方法 CheckTeacher() 当中的是哪个栈内存地址的名字,那么传过去的就是此地址在堆内存中所指向的对象地址。
3、Instanceof 运算符
java 中的 instanceof 运算符是用来在运行时指出对象是否是特定类的一个实例。
instanceof 通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例。
用法:
result = object instanceof class
参数
(1)Result:布尔类型。
(2)Object:必选项。任意对象表达式。
(3)Class:必选项。任意已定义的对象类。说明:
如果 object 是 class 的一个实例,则 instanceof 运算符返回 true。如果 object 不是指定类的一个实例,或者object 是 null,则返回 false。
二、接口多态
- 接口的多态基本上和类的继承多态一致,不同的是类的继承使用的是继承关系实现多态,接口采用实现的方式实现多态。
- 示例
interface PersonInter
{
public abstract void study();
public void eating();//接口默认抽象,加不加abstract都可以
}
class Student implements PersonInter
{
String name;
int age;
public Student(String name)
{
this.name = name;
}
public void study()
{
System.out.println(name+"在学习");
}
public void eating()
{
System.out.println(name+"在吃西瓜");
}
}
class Worker implements PersonInter
{
String name;
int age;
public Worker(String name)
{
this.name = name;
}
public void study()
{
System.out.println(name+"在工作");
}
public void eating()
{
System.out.println(name+"在吃苹果");
}
}
class Leader
{
public void CheckPerson(PersonInter ja)
{
String person = "";
//instanceof可以判断我们多态的引用变量到底是什么类型,提前知道那个人来了
if(ja instanceof Student)
{
person = "张三";
}
else if(ja instanceof Worker)
{
person = "李四";
}
System.out.println("开始考察"+person);
//System.out.println(name+"接受检查");
ja.eating();
System.out.println("结束");
}
}
class Welcome
{
public static void main(String[] args)
{
//接口类型多态子类的实例可以赋给父类引用,父类不能调用子类里独有的方法
PersonInter st = new Student("张三");
PersonInter wk = new Worker("李四");
//注意,此处不能像 st.name = "张三"; 这样赋值,因为接口里没有name属性
//st.name = "张三";错误
Leader ld = new Leader();
ld.CheckPerson(st);
//ld.CheckTeacher(wk);
}
}
如有错误,欢迎指正!