D:code黑马codeoop-up-app02srccompolymorphism
多态是在继承或实现的情况下的一种现象,分为对象多态和行为多态
对象多态
行为多态:
//父类
public class people {public String name = "people";public void say(){System.out.println("I am a people");}
}
//子类1
public class Student extends people{public String name = "Student";@Overridepublic void say(){System.out.println("I am a Student");}public void study(){System.out.println("I am studying");}
}
//子类2
public class Teacher extends people{public String name = "Teacher";@Overridepublic void say(){System.out.println("I am a Teacher");}
}
public class Test {public static void main(String[] args) {//对象多态people p1 = new people();people p2 = new Student();people p3 = new Teacher();//不存在属性多态System.out.println(p1.name);System.out.println(p2.name);System.out.println(p3.name);//行为多态p1.say();//编译看左边,运行看右边p2.say();//p2.study();//会报错,因为p2是people类型,people没有study方法,所以无法调用study方法p3.say();}
}
/*
result:peoplepeoplepeopleI am a peopleI am a StudentI am a Teacher
*/
可以解耦合,使代码扩展性更强
使用父类对象作为方法的形参,可以接收一切子类对象
//子类与父类的代码见上文代码
public class Test {public static void main(String[] args) {people p1 = new people();people p2 = new Student();people p3 = new Teacher();sayHello(p1);sayHello(p2);sayHello(p3);}public static void sayHello(people p){//可以接受父类和所有子类对象p.say();}
}
用于解决多态无法调用子类特有的方法的问题
存在继承或实现关系就可以在编译阶段进行强制类型转换,编译阶段不会报错
运行时,如果发现对象的真实类型与强转后的类型不同,会报异常
public static void main(String[] args) {people p = new Teacher();//Student s = (Student) p;// 会报ClassCastException,因为原来的p是Teacher类型,不能转换为Student类型}
解决异常问题,在强转前使用instanceof关键字判断对象真实类型,再强转
public class Test2 {public static void main(String[] args) {people p = new Teacher();hhh(p);}public static void hhh(people p){p.say();System.out.println(p instanceof Student);System.out.println(p instanceof Teacher);if (p instanceof Student) {Student s = (Student) p;s.study();} else if (p instanceof Teacher) {Teacher t = (Teacher) ach();}}
}
/*
result:I am a TeacherfalsetrueI am teaching
*/
D:code黑马codeoop-up-app02srccomfinall
修饰类:该类被称为最终类,特点是不能被继承了。
修饰方法:该方法被称为最终方法,特点是不能被重写了。
修饰变量:该变量只能被赋值一次。(必须在初始化时赋值)
final可以用来修饰局部变量和成员变量(实例成员变量和静态成员变量)
final修饰基本类型变量时,变量存储的数据不能被改变
final修饰引用类型的变量时,变量存储的地址不能变,但是地址指向的对象的内容可以改变
//final修饰局部变量的两种情况
public class Test {public static void main(String[] args) {final int a = 10;// a = 20; // 会报错,因为a是final类型,不能再次赋值}public static void hhh(final int a){// a = 20; // 会报错,因为a是final类型,不能再次赋值}
}
//final修饰成员变量
public class Test1 {static final int a = 10;final int b = 20;public static void main(String[] args) {
// 会报错,因为静态成员变量a是final类型,不能再次赋值
// a = 20;
// 会报错,因为实例成员变量b是final型,不能再次赋值
// b = 30; }
}
//final修饰基本类型和引用类型的区别
public class Test2 {public static void main(String[] args) {final int a = 10;final int[] list = {1,2,3};// a = 11;// 会报错,因为a是final修饰的基本数据类型的int变量,不能再次赋值list[0] = 10;//不会报错,因为引用类型可以修改地址指向的内容的值
// list = null//会报错,因为final修饰的引用类型的变量所存储的地址不能再次赋值}
}
程序编译后,常量会被“宏替换”:出现常量的地方全部会被替换成其记住的字面量,这样可以保证使用常量和直接用字面量的性能是一样的。也就是说不会影响性能,这些常量不会在运行时才找值,而是在编译后就将所有常量直接替换成需要的字面量
//.java文件
public class Test3 {public static final String MY_NAME = "LMH";public static void main(String[] args) {System.out.println(MY_NAME);System.out.println(MY_NAME);System.out.println(MY_NAME);System.out.println(MY_NAME);}
}
//编译后的.class文件
package com.finall;public class Test3 {public static final String MY_NAME = "LMH";public Test3() {}public static void main(String[] args) {System.out.println("LMH");//对常量进行了自动赋值System.out.println("LMH");System.out.println("LMH");System.out.println("LMH");}
}
D:code黑马codeoop-up-app02srccomabstract_
抽象类中不一定有抽象方法,有抽象方法的类一定为抽象类
//将方法注释掉不会报错,因为抽象类中不一定有抽象方法
//如果去掉类中的abstract会报错,因为有抽象方法的类一定为抽象类
public abstract class Test {public abstract void test();
}
类该有的成员(成员变量,方法,构造器)抽象类都可以有,也就是说抽象类中既可以有抽象方法,也可以有实例方法,只要类中有一个抽象方法则该类就是抽象类
//如果去掉类中的abstract会报错,因为类中有一个抽象方法
public abstract class Test {public String name;//抽象类中可以有成员变量public Test() {//抽象类中可以有构造方法System.out.println("抽象类中可以有构造方法");}public String getName() {//抽象类中可以有普通方法return name;}public void setName(String name) {//抽象类中可以有普通方法this.name = name;}public abstract void test();//抽象类中可以有抽象方法
}
一个类继承抽象类,必须重写该类所有的抽象方法,否则必须将当前类也定义为抽象类
//抽象类
public abstract class Test{public abstract void a();public abstract void b();
}
//重写了所有方法
public class test1 extends Test{@Overridepublic void a() {System.out.println("a");}@Overridepublic void b() {System.out.println("b");}
}
//由于只重写了一个方法会报错,除了重写所有方法会在类名前添加abstract
public class test2 extends Test{@Overridepublic void a() {System.out.println("a");}
}
public abstract class Animal {private String name;public abstract void action();public String getName() {return name;}public void setName(String name) {this.name = name;}
}
public class dog extends Animal{@Overridepublic void action() {System.out.println("狗汪汪汪的叫");}
}
public class cat extends Animal{@Overridepublic void action() {System.out.println("猫喵喵喵的叫");}
}
public class test {public static void main(String[] args) {Animal d = new dog();d.setName("小狗");d.action();Animal c = new cat();c.setName("小猫");c.action();}
}
/*
result:狗汪汪汪的叫猫喵喵喵的叫
*/
public abstract class Person {private String name;private int age;public Person() {}public Person(String name, int age) {this.name = name;this.age = age;}//模板方法,用final修饰,放入相同代码public final void commonintroduce(){System.out.println("我的名字是:"+name+" 年龄:"+age + selfintroduce());}//抽象方法public abstract String selfintroduce();
}
public class Teacher extends Person{private String Skill;public Teacher() {}public Teacher(String name, int age ,String skill) {super(name, age);this.Skill = skill;}//实现抽象方法@Overridepublic String selfintroduce() {return " 我的技能是:"+Skill+"。";}
}
public class Consult extends Person{private int num;public Consult() {}public Consult(String name, int age,int num) {super(name, age);this.num = num;}//实现抽象方法@Overridepublic String selfintroduce() {return " 我的咨询人数是:"+num+"人。";}
}
public class Test {public static void main(String[] args) {Person p1 = new Teacher("张三", 20, "java");Person p2 = new Consult("李四", 30, 100);p1monintroduce();p2monintroduce();}
}
/*
result:我的名字是:张三 年龄:20 我的技能是:java。我的名字是:李四 年龄:30 我的咨询人数是:100人。
*/
D:code黑马codeoop-up-app02srccominterface_
使用interface定义接口
接口不能创建对象
接口中只能由属性和抽象方法
接口需要被类使用implements实现,实现接口的类叫实现类
一个实现类可以实现多个接口,但是必须要重写所有接口的抽象方法,否则要将实现类定义为抽象类
//接口1
public interface A {// 接口中的属性都是常量,默认使用public static final修饰String MY_NAME = "A";// 接口中的方法都是抽象方法,默认使用public abstract修饰void sayA();
}
//接口2
public interface B {String MY_NAME = "B";void sayB();
}
//实现类
public class C implements A,B{
//必须同时实现所有的接口中的抽象方法@Overridepublic void sayA() {System.out.println("sayA");}@Overridepublic void sayB() {System.out.println("sayB");}
}
//测试类
public class Test {public static void main(String[] args) {// 接口不能被实例化// A a = new A();// B b = new B();// 前两个为多态,后一个为普通对象A a = new C();B b = new C();C c = new C();// 接口中的属性都是常量,默认使用public static final修饰System.out.println(A.MY_NAME);System.out.println(B.MY_NAME);
// System.out.println(C.MY_NAME);//会报错,因为C中并没有常量MY_NAME// 接口中的方法都是抽象方法,默认使用public abstract修饰a.sayA();//a中只有sayA()方法,没有sayB()b.sayB();//b中只有sayB()方法,没有sayA()c.sayA();//c中既有sayA()方法,也有sayB()}
}
/*
result:ABsayAsayBsayAsayB
*/
弥补了类单继承的不足,一个类同时可以实现多个接口。
让程序可以面向接口编程,这样程序员就可以灵活方便的切换各种业务实现。
//抽象父类
abstract class people{public String name;public int age;public people(String name, int age) {this.name = name;this.age = age;}public abstract void say();
}
//driver接口
interface Driver{void drive();
}
//cooker接口
interface Cooker{void cook();
}
//实现
class Student extends people implements Driver, Cooker{public Student(String name, int age) {super(name, age);}@Overridepublic void say() {System.out.println("我叫" + super.name + ",今年" + super.age + "岁,学生");}@Overridepublic void drive() {System.out.println("我叫" + super.name + ",今年" + super.age + "岁,司机");}@Overridepublic void cook() {System.out.println("我叫" + super.name + ",今年" + super.age + "岁,厨师");}
}
//测试
public class Test {public static void main(String[] args) {Student student = new Student("张三", 18);student.say();student.drive();k();//使用接口来接受对象,可以更有效的标识对象,当前对象就是个司机,无法调用学生和厨师的方法Driver driver = new Student("李四", 20);driver.drive();
// driver.say();//会报错,因为是Driver类型,没有say方法Cooker cooker = new Student("王五", 22);k();}
}
/*
result:我叫张三,今年18岁,学生我叫张三,今年18岁,司机我叫张三,今年18岁,厨师我叫李四,今年20岁,司机我叫王五,今年22岁,厨师
*/
//实体类
public class Student {private String name;private char sex;private double score;public Student() {}public Student(String name, char sex, double score) {this.name = name;this.sex = sex;this.score = score;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getSex() {return sex;}public void setSex(char sex) {this.sex = sex;}public double getScore() {return score;}public void setScore(double score) {this.score = score;}@Overridepublic String toString() {return "name='" + name + ''' +", sex=" + sex +", score=" + score;}
}
//接口
public interface Studentoper {void printInfo(ArrayList<Student> students);void printAverageScore(ArrayList<Student> students);
}
//实现一,完成方案一
public class StudentoperImpl1 implements Studentoper{@Overridepublic void printInfo(ArrayList<Student> students) {for (Student student : students) {System.out.println(student);}}@Overridepublic void printAverageScore(ArrayList<Student> students) {double sum = 0;for (Student student : students) {sum += Score();}System.out.println("平均分为:" + sum / students.size());}
}
//实现二,完成方案二
public class StudentoperImpl2 implements Studentoper{@Overridepublic void printInfo(ArrayList<Student> students) {int countMan = 0;int countWoman = 0;for (Student student : students) {if (Sex() == '男')countMan++;elsecountWoman++;System.out.println(student);}System.out.println("男生人数:" + countMan);System.out.println("女生人数:" + countWoman);}@Overridepublic void printAverageScore(ArrayList<Student> students) {double max = (0).getScore();double min = (0).getScore();double sum = 0;for (Student student : students) {if (Score() > max)max = Score();if (Score() < min)min = Score();sum += Score();}double sum1 = sum - max - min;double avg = sum1/ (students.size() - 2);System.out.println("平均分为:" + avg);}
}
//操作类
public class ClassOper {private final ArrayList<Student> students = new ArrayList<>();//使用多态完成方案一private final Studentoper studentoper1 = new StudentoperImpl1();//使用多态完成方案二private final Studentoper studentoper2 = new StudentoperImpl2();//添加学生public ClassOper() {students.add(new Student("张三",'男' , 100));students.add(new Student("李四", '女', 99));students.add(new Student("王五",'男' , 98));students.add(new Student("赵六", '女', 97));students.add(new Student("田七",'女' , 96));students.add(new Student("周八", '女', 95));}public void printInfo(boolean flag) {System.out.println("---------------"+flag+"----------------");if (flag)studentoper1.printInfo(students);elsestudentoper2.printInfo(students);}public void printAverageScore(boolean flag) {if (flag)studentoper1.printAverageScore(students);elsestudentoper2.printAverageScore(students);}
}
//测试类
public class Test {public static void main(String[] args) {ClassOper classOper = new ClassOper();boolean flag = true;//如果更改为false,则使用StudentoperImpl2的实现classOper.printInfo(flag);classOper.printAverageScore(flag);}
}
/*
result:---------------true----------------name='张三', sex=男, score=100.0name='李四', sex=女, score=99.0name='王五', sex=男, score=98.0name='赵六', sex=女, score=97.0name='田七', sex=女, score=96.0name='周八', sex=女, score=95.0平均分为:97.5、---------------false----------------name='张三', sex=男, score=100.0name='李四', sex=女, score=99.0name='王五', sex=男, score=98.0name='赵六', sex=女, score=97.0name='田七', sex=女, score=96.0name='周八', sex=女, score=95.0男生人数:2女生人数:4平均分为:97.5
*/
//接口
public interface A {/** 接口中的默认方法(实例方法)* 1. 必须使用default关键字修饰,默认被public修饰* 2. 接口中的默认方法,可以通过接口的实现类对象,直接调用* 3. 接口中的默认方法,也可以被接口的实现类进行覆盖重写*/default void method1(){System.out.println("A接口的默认方法");method2();}/** 接口中的私有方法(实例方法)* 1. 必须使用private关键字修饰* 2. 只能在接口中被调用* 3. JDK9之后才有私有方法,可以被接口中的默认方法或者静态方法调用*/private void method2() {System.out.println("A接口的私有方法");}/** 接口中的静态方法(类方法)* 1. 必须使用static关键字修饰,默认被public修饰* 2. 接口中的静态方法,可以通过接口名直接调用*/static void method3(){System.out.println("A接口的静态方法");}
}
//实现类
public class B implements A{
}
//测试类
public class Test {public static void main(String[] args) {A a = new B();a.method1();A.method3();}
}
/*
result:A接口的默认方法A接口的私有方法A接口的静态方法
*/
概念
好处
便于实现类去实现接口
比如A接口继承了B和C接口,那么实现类只需要实现A接口,就可以实现A,B,C三个接口,此时实现类必须重写A,B,C三个接口中的全部方法
interface B{void m1();
}
interface C{void m2();
}
interface A extends B,C{void m3();
}
//只有同时实现A,B,C三个接口中的方法,才不会报错
public class Test implements A{@Overridepublic void m1() {}@Overridepublic void m2() {}@Overridepublic void m3() {}
}
一个接口继承多个接口,如果多个接口中存在方法签名不一致,则此时不支持多继承。
一个接口继承多个接口,如果多个接口中存在方法签名一致,则此时只需要重写一次即可,支持多继承
//一个接口继承多个接口,如果多个接口中存在方法签名不一致,则此时不支持多继承。
interface D{void test();
}
interface E{String test();
}
//会报错,无法继承
interface F extends D,E{
}
//一个接口继承多个接口,如果多个接口中存在方法签名一致,则此时只需要重写一次即可,支持多继承
public class Test1 implements C{@Overridepublic void test() {System.out.println("test");}}
interface A{void test();
}
interface B{void test();
}
interface C extends A,B{}
一个类实现多个接口,如果多个接口中存在方法签名冲突,则此时不支持多实现。
//一个类实现多个接口,如果多个接口中存在方法签名冲突,则此时不支持多实现。
public class Test2 implements A1,B1{}
//会报错
interface A1{void m1();
}
interface B1{void m1(String s);
}
一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会优先用父类的。
//一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会优先用父类的。
public class Test3 {public static void main(String[] args) {T3 t3 = new T3();t3.m1();//没有重写的情况下,优先使用父类的方法}
}class T1 {public void m1() {System.out.println("T1.m1");}
}
interface T2 {default void m1() {System.out.println("T2.m1");}
}
class T3 extends T1 implements T2 {
}
/*
result:T1.m1
*/
一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。
//一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。
public class Test4 {public static void main(String[] args) {C3 c3 = new C3();c3.hi();}
}
interface C1{void hi();
}
interface C2{void hi();
}
class C3 implements C1,C2{@Overridepublic void hi() {System.out.println("hi");}
}
}
//会报错
interface A1{
void m1();
}
interface B1{
void m1(String s);
}
- 一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会优先用父类的。```java
//一个类继承了父类,又同时实现了接口,父类中和接口中有同名的默认方法,实现类会优先用父类的。
public class Test3 {public static void main(String[] args) {T3 t3 = new T3();t3.m1();//没有重写的情况下,优先使用父类的方法}
}class T1 {public void m1() {System.out.println("T1.m1");}
}
interface T2 {default void m1() {System.out.println("T2.m1");}
}
class T3 extends T1 implements T2 {
}
/*
result:T1.m1
*/
一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。
//一个类实现了多个接口,多个接口中存在同名的默认方法,可以不冲突,这个类重写该方法即可。
public class Test4 {public static void main(String[] args) {C3 c3 = new C3();c3.hi();}
}
interface C1{void hi();
}
interface C2{void hi();
}
class C3 implements C1,C2{@Overridepublic void hi() {System.out.println("hi");}
}
本文发布于:2024-01-31 21:01:35,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170670609731326.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |