多态的两种实现方式
使用父类作为方法形参实现多态
使用父类作为返回值实现多态
当这个作为参数的父类是普通类或者抽象类时,构成继承多态
当这个作为参数的父类是一个接口时,构成接口多态
多态作为形参:
形式参数:
注意:当一个方法的形参是引用类型的时候,建议养成一个好的习惯:做非空判断
基本类型(…)
引用类型:
普通类:
当一个形参希望我们传入的是一个普通类时,我们实际传入的是该类的对象/匿名对象
package sxt.com.workdemo;
public class ArgsDemo01 {
public static void main(String[] args) {
new Student().study();
Student s = new Student();
new StudentDemo().method(s); //如果这里的s为(null)时编译会报空指针异常
}
}
class Student {
public void study() {
System.out.println("Student.study()");
}
}
class StudentDemo {
public void method(Student s) {
//s.study();
//空指针异常解决办法
/* 第一种解决办法
if (s != null) {
s.study();
}*/
/*第二种(手动抛出异常,并给出异常提示)
if (s == null) {
throw new NullPointerException("学生对象不能为空");
}
s.study();*/
/*第三种(Object判断)
if (!Objects.isNull(s)) {
s.study();
}*/
}
}
抽象类:
当一个形参希望我们传入的是一个抽象类时,我们实际传入的是该类的子类对象/子类匿名对象
子类匿名对象:
new 类名() {
重写方法;
自定义方法;
};
1.这是一个对象
2.这是一个子类对象
3.这是一个子类匿名对象
package sxt.com.workdemo;
public class ArgsDemo01 {
public static void main(String[] args) {
// 直接创建子类对象
// new MiddleStudent().study();
// 利用多态
// AbsStudent s = new MiddleStudent();
// s.study();
// 调用method
// MiddleStudent m = new MiddleStudent();
// new StudentDemo().method(m);
//子类匿名对象
new MiddleStudent() { //MiddleStudent类的子类匿名对象
@Override
public void study() {
System.out.println("MiddleStudent子类匿名对象里的study");
}
}.study();
new MiddleStudent() {
public void show() {
System.out.println("MiddleStudent的子show");
};
}.show();
// 希望一个对象调用两个方法 利用多态
MiddleStudent ms = new MiddleStudent() {};
ms.study();
ms.show();
new AbsStudent() { // "new"一个抽象类的子类(实际上是抽象类的子类)
@Override
public void study() {
System.out.println("抽象类study");
}
}.study();
}
}
abstract class AbsStudent {
public abstract void study();
}
class MiddleStudent extends AbsStudent {
@Override
public void study() {
System.out.println("中学生学习");
}
public void show() {
System.out.println("MiddleStudent show");
}
}
class StudentDemo {
public void method(AbsStudent s) {
s.study();
}
}
接口:
当一个形参希望我们传入的是一个接口时,我们实际传入的是该类的实现类对象/实现类匿名对象
package sxt.com.workdemo;
public class ArgsDemo01 {
public static void main(String[] args) {
MiddleStudent ms = new MiddleStudent();
ms.study();
IStudent s = new MiddleStudent();
s.study();
new StudentDemo().method(s);
new IStudent() {
@Override
public void study() {
System.out.println("study1");
}
}.study();
new StudentDemo().method(new IStudent() {
@Override
public void study() {
System.out.println("study2");
}
});
}
}
interface IStudent {
public abstract void study();
}
class MiddleStudent implements IStudent {
@Override
public void study() {
System.out.println("中学生学习");
}
}
class StudentDemo {
public void method(IStudent s) {
/* IStudent s = new IStudent() {
@Override
public void study() {
System.out.println("study2");
}
} */
s.study();
}
}
当方法的返回类型是引用类型时,可以使用链式调用
多态作为返回值:
package returndemo;
/*
* 方法调用的三要素: 返回什么类型就用什么类型接收
* 多态作为返回值
返回值类型
基本类型(前面讲过,不解释)
引用类型
普通类
当一个方法的返回值是一个普通的类时,实际上返回的是该类的对象,我们可以使用该类的对象接收
抽象类
当一个方法的返回值是一个抽象类时,实际上返回的是该抽象类的子类对象,我们可以使用该抽象类接收
接口
当一个方法的返回值是一个接口时,实际上返回的是该接口的实现类对象,我们可以使用接口接收
当方法的返回值类型是引用类型的时候,可以使用链式调用
*/
/*public class ReturnDemo01 {
public static void main(String[] args) {
Student s = new StudentDemo().method();
s.study();
}
}
class Student {
public void study() {
System.out.println("Student.study()");
}
}
class StudentDemo {
public Student method() {
Student s = new Student();
return s;
}
}*/
package returndemo;
/*
* 多态作为返回值
返回值类型
基本类型(前面讲过,不解释)
引用类型
普通类
当一个方法的返回值是一个普通的类时,实际上返回的是该类的对象,我们可以使用该类的对象接收
抽象类
当一个方法的返回值是一个抽象类时,实际上返回的是该抽象类的子类对象,我们可以使用该抽象类接收
接口
当一个方法的返回值是一个接口时,实际上返回的是该接口的实现类对象,我们可以使用接口接收
当方法的返回值类型是引用类型的时候,可以使用链式调用
*/
/*public class ReturnDemo02 {
public static void main(String[] args) {
// Student s = (Student) new StudentDemo().method();
// s.study();
AbsStudent s = new StudentDemo().method();
if (s instanceof Student) {
Student stu = (Student) s;
stu.study();
}
new StudentDemo().method().study();
// 以后会接触一个叫做StringBuffer的类
StringBuffer sb = new StringBuffer("abc").append("efg").append("hij").append("opq");
System.out.println(sb);
}
}
abstract class AbsStudent {
public abstract void study();
}
class Student extends AbsStudent {
@Override
public void study() {
System.out.println("Student.study()");
}
}
class StudentDemo {
public AbsStudent method() {
AbsStudent s = new Student();
return s;
}
}*/
package returndemo;
/*
* 多态作为返回值
返回值类型
基本类型(前面讲过,不解释)
引用类型
普通类
当一个方法的返回值是一个普通的类时,实际上返回的是该类的对象,我们可以使用该类的对象接收
抽象类
当一个方法的返回值是一个抽象类时,实际上返回的是该抽象类的子类对象,我们可以使用该抽象类接收
接口
当一个方法的返回值是一个接口时,实际上返回的是该接口的实现类对象,我们可以使用接口接收
当方法的返回值类型是引用类型的时候,可以使用链式调用
*/
public class ReturnDemo03 {
public static void main(String[] args) {
new StudentDemo().method(new IStudent() {
@Override
public void study() {
System.out.println("外界study");
}
}).study();
/*
* new IStudent() {
@Override
public void study() {
System.out.println("返回 study");
}
}.study();
*
*/
}
}
interface IStudent {
public abstract void study();
}
class Student implements IStudent {
@Override
public void study() {
System.out.println("Student.study()");
}
}
class StudentDemo {
/*public IStudent method() {
// return new Student();
return new IStudent() {
@Override
public void study() {
System.out.println("实现类匿名对象");
}
};
}*/
public IStudent method(IStudent stu) {
/*
* IStudent stu = new IStudent() {
@Override
public void study() {
System.out.println("外界study");
}
}
*
*/
stu = new IStudent() {
@Override
public void study() {
System.out.println("内部 study");
}
};
return new IStudent() {
@Override
public void study() {
System.out.println("返回 study");
}
};
}
}