java 面向对象高级1

[复制链接]
发表于 2025-12-27 08:38:47 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
1.final关键字

  1. class Demo{
  2.     public static void main(String[] args) {
  3.         final int[] a=new int[]{1,2,3};
  4.        // a=new int[]{4,5,6};  报错
  5.         a[0]=5;//可以,解释了final修饰引用性变量,变量存储的地址不能被改变,但地址所指向的对象的内容可以改变
  6.     }
  7. }
复制代码
什么是常量?

2.单例计划模式-懒汉式单例-饿汉式单例





3.罗列类



  1. //常规写法
  2. class Constant{
  3.     public static final int UP=0;
  4.     public static final int DOWN=1;
  5.     public static final int LEFT=2;
  6.     public static final int RIGHT=3;
  7. }
  8. class Demo{
  9.     public static void move(int direction){
  10.         switch (direction){
  11.             case Constant.UP:
  12.                 System.out.println("向上移动");
  13.                 break;
  14.             case Constant.DOWN:
  15.                 System.out.println("向下移动");
  16.                 break;
  17.             case Constant.LEFT:
  18.                 System.out.println("向左移动");
  19.                 break;
  20.             case Constant.RIGHT:
  21.                 System.out.println("向右移动");
  22.                 break;
  23.             default:
  24.                 System.out.println("无效方向");
  25.         }
  26.     }
  27. }
  28. //枚举类写法,相较于常规的好处是
  29. /*类型安全:枚举提供了更好的类型安全,因为它们限制了变量只能取预定义的值,而常规的静态常量类则没有这种限制。
  30. 可读性:枚举通常更易于阅读和理解,因为它们使用名称而不是数字或字符串来表示常量值。
  31. 维护性:使用枚举可以更容易地管理和维护一组相关的常量值,因为它们是集中定义的。
  32. 功能扩展:枚举可以有自己的方法和属性,这为扩展功能提供了可能,而常规的静态常量类则没有这样的能力。*/
  33. enum Direction{
  34.     UP,DOWN,LEFT,RIGHT
  35. }
  36. class Demo2{
  37.     public static void move(Direction direction){
  38.         switch (direction){
  39.             case UP:
  40.                 System.out.println("向上移动");
  41.                 break;
  42.             case DOWN:
  43.                 System.out.println("向下移动");
  44.                 break;
  45.             case LEFT:
  46.                 System.out.println("向左移动");
  47.                 break;
  48.             case RIGHT:
  49.                 System.out.println("向右移动");
  50.                 break;
  51.         }
  52.     }
  53. }
复制代码
4.认识抽象类




5.模板方法计划模式


  1. class A extends fu{
  2.     public void writemain(){
  3.         System.out.println("特殊方法A");
  4.     }
  5. }
  6. class B extends fu{
  7.     public void writemain(){
  8.         System.out.println("特殊方法B");
  9.     }
  10. }
  11. abstract class fu{
  12.     public final void write(){
  13.         System.out.println("公用方法1");
  14.         writemain();
  15.         System.out.println("公用方法2");
  16.     }
  17.     public abstract void writemain();
  18. }
  19. class Demo{
  20.     public static void main(String[] args) {
  21.         fu a=new A();
  22.         a.write();
  23.     }
  24. }
  25. /*
  26. 输出:
  27. 公用方法1
  28. 特殊方法A
  29. 公用方法2
  30. */
复制代码
  1. // 抽象类:饮料制作
  2. abstract class BeverageMaker {
  3.     // 模板方法,定义了制作饮料的算法骨架
  4.     public final void makeBeverage() {
  5.         boilWater();
  6.         brew();
  7.         pourInCup();
  8.         if (customerWantsCondiments()) {
  9.             addCondiments();
  10.         }
  11.     }
  12.     // 具体方法:烧水,属于算法中的固定部分
  13.     private void boilWater() {
  14.         System.out.println("Boiling water");
  15.     }
  16.     // 抽象方法:冲泡,属于算法中的可变部分
  17.     protected abstract void brew();
  18.     // 具体方法:倒入杯子,属于算法中的固定部分
  19.     private void pourInCup() {
  20.         System.out.println("Pouring into cup");
  21.     }
  22.     // 钩子方法:是否添加调料,子类可以重写该方法来决定是否添加调料
  23.     protected boolean customerWantsCondiments() {
  24.         return true;
  25.     }
  26.     // 抽象方法:添加调料,属于算法中的可变部分
  27.     protected abstract void addCondiments();
  28. }
  29. // 具体子类:制作咖啡
  30. class CoffeeMaker extends BeverageMaker {
  31.     @Override
  32.     protected void brew() {
  33.         System.out.println("Dripping coffee through filter");
  34.     }
  35.     @Override
  36.     protected void addCondiments() {
  37.         System.out.println("Adding sugar and milk");
  38.     }
  39.     // 重写钩子方法,决定是否添加调料
  40.     @Override
  41.     protected boolean customerWantsCondiments() {
  42.         return false;
  43.     }
  44. }
  45. // 具体子类:制作茶
  46. class TeaMaker extends BeverageMaker {
  47.     @Override
  48.     protected void brew() {
  49.         System.out.println("Steeping the tea");
  50.     }
  51.     @Override
  52.     protected void addCondiments() {
  53.         System.out.println("Adding lemon");
  54.     }
  55. }
  56. // 测试类
  57. public class TemplateMethodPatternDemo {
  58.     public static void main(String[] args) {
  59.         // 制作咖啡
  60.         BeverageMaker coffeeMaker = new CoffeeMaker();
  61.         coffeeMaker.makeBeverage();
  62.         System.out.println();
  63.         // 制作茶
  64.         BeverageMaker teaMaker = new TeaMaker();
  65.         teaMaker.makeBeverage();
  66.     }
  67. }
复制代码

6.认识接口


  1. //jdk 8之前,接口中只能定义常量和抽象方法
  2. //接口不能创建对象
  3. public interface A {
  4.     String STUDENT_NAME="li hua"; //接口中默认加上 public static final
  5.     // 等价于 public static final String STUDENT_NAME="li hua";
  6.     void run();//接口中给方法默认加上public abstract
  7.     //等价于 public abstract void run();
  8. }
  9. //Demo被称为实现类,可以同时实现多个接口,
  10. //实现类实现多个接口必须重写全部抽象方法,否则必须定义成抽象类
  11. public class Demo implements A{
  12.     @Override
  13.     public void run() {
  14.     }
  15. }
复制代码
  1. public class Demo{
  2.     public static void main(String[] args) {
  3.         people p=new student();
  4.         doctor d=new student();
  5.         driver dr=new student();
  6.     }
  7. }
  8. interface driver{}
  9. interface doctor{}
  10. class student extends people implements driver,doctor{}
  11. class people{}
复制代码

  1. public class Demo {
  2.     public static void main(String[] args) {
  3.         people p = new student();
  4.         doctor d = new student();
  5.         driver dr = new student();
  6.     }
  7. }
  8. interface driver {}
  9. interface doctor {}
  10. class student extends people implements driver, doctor {}
  11. class people {}
复制代码
多态表现:


  • 向上转型(多态的根本):

    • people p = new student();
    • doctor d = new student();
    • driver dr = new student();
    这里 student 对象被赋值给了父类 people 和两个接口 doctor、driver 的引用变量。这种举动是向上转型,即子类对象可以被赋值给父类或接口范例的引用。

  • 多态的本质:

    • 多态的本质是:父类或接口的引用可以指向子类对象。在运行时,通过这些父类或接口的引用,可以调用子类的重写方法(假如有)。这种计划使得代码更加机动,可以大概通过同一的父类或接口来处置处罚差异的子类对象。

  • 接口多态:

    • 这里 student 实现了两个接口:doctor 和 driver。通过利用接口作为引用范例(doctor d 和 driver dr),可以将 student 的对象赋值给这些接口变量。这种计划使得 student 可以被看作是一名医生(doctor)大概司机(driver),从而实现了接口层面的多态。


第二段代码的多态表现
  1. class animals {
  2.     String name = "animals";
  3.     public void run() {}
  4. }
  5. class cat extends animals {
  6.     String name = "cat";
  7.     @Override
  8.     public void run() {
  9.         System.out.println("cat run");
  10.     }
  11. }
  12. class dog extends animals {
  13.     String name = "dog";
  14.     @Override
  15.     public void run() {
  16.         System.out.println("dog run");
  17.     }
  18. }
  19. class demo {
  20.     public static void main(String[] args) {
  21.         animals a = new cat();
  22.         a.run();
  23.         animals b = new dog();
  24.         b.run();
  25.         System.out.println(a.name);
  26.         System.out.println(b.name); // 成员变量不具有多态性
  27.     }
  28. }
复制代码
多态表现:


  • 向上转型(多态的根本):

    • animals a = new cat();
    • animals b = new dog();
    子类 cat 和 dog 的对象被赋值给父类 animals 的引用变量 a 和 b。这也是向上转型,即用父类范例的引用来指向子类对象。

  • 动态绑定(运行时多态):

    • 调用 a.run() 和 b.run() 时,实际上调用的是子类 cat 和 dog 的 run 方法,而不是父类 animals 的 run 方法。这是由于方法调用是动态绑定的,即在运行时根据对象的实际范例(cat 或 dog)来决定调用哪个方法。
    • 输出效果:
      1. cat run
      2. dog run
      复制代码

  • 成员变量不具有多态性:

    • 当访问成员变量 a.name 和 b.name 时,输出的是父类 animals 的 name 属性值,而不是子类 cat 或 dog 的 name 属性值。这是由于成员变量的访问是编译时绑定的,取决于引用变量的范例(这里是父类 animals)。
    • 输出效果:
      1. animals
      2. animals
      复制代码


两段代码的多态对比

特性第一段代码第二段代码多态的实现方式通过接口和父类的引用指向子类对象,表现了接口多态和继续多态。通过父类引用指向子类对象,表现了继续多态。动态绑定没有方法调用的详细实现,未展示动态绑定的效果。通过调用重写的 run 方法,展示了动态绑定的效果。成员变量的多态性未涉及成员变量的多态性题目。明确指出成员变量不具有多态性,访问的是父类的成员变量值。接口的利用利用了接口 doctor 和 driver,表现了接口多态。未利用接口,完全基于继续实现多态。代码计划的机动性通过接口可以让 student 以差异的身份(doctor 或 driver)存在,机动性更高。通过继续实现了差异子类的举动差异,但不涉及接口的机动性。
总结


  • 第一段代码紧张通过接口和继续的组合来表现多态,展示了对象可以以多种身份存在(people、doctor、driver),夸大了接口多态的机动性。
  • 第二段代码紧张通过继续和方法的重写来表现多态,展示了运行时的动态绑定(方法调用的多态性)以及成员变量不具有多态性的特点。
两段代码各自侧重多态的差异方面,共同表现了多态在 Java 中的紧张性和机动性。
接口的应用案例
  1. import lombok.AllArgsConstructor;
  2. import lombok.Data;
  3. import lombok.NoArgsConstructor;
  4. public class Demo{
  5.     public static void main(String[] args) {
  6.         student[] s=new student[3];
  7.         s[0]=new student("li hua","boy",90);
  8.         s[1]=new student("zhang san","boy",100);
  9.         s[2]=new student("tu xin yue","girl",95);
  10.         tool t=new imp2(s);
  11.         t.listallinfo();
  12.         t.sumscore();
  13.     }
  14. }
  15. class student{
  16.     private String name;
  17.     private String sex;
  18.     private double score;
  19.     public student(String name, String sex, double score) {
  20.         this.name = name;
  21.         this.sex = sex;
  22.         this.score = score;
  23.     }
  24.     public student(){}
  25.     public String getName() {
  26.         return name;
  27.     }
  28.     public void setName(String name) {
  29.         this.name = name;
  30.     }
  31.     public String getSex() {
  32.         return sex;
  33.     }
  34.     public void setSex(String sex) {
  35.         this.sex = sex;
  36.     }
  37.     public double getScore() {
  38.         return score;
  39.     }
  40.     public void setScore(double score) {
  41.         this.score = score;
  42.     }
  43. }
  44. interface tool{
  45.     public void listallinfo();
  46.     public void sumscore();
  47. }
  48. class imp1 implements tool{
  49.     private student[] s;  
  50.     public imp1(student[] s){    //一般建议利用有参构造方法,推荐这种形式
  51.         this.s=s;
  52.     }
  53.     @Override
  54.     public void listallinfo() {
  55.         for(int i=0;i<s.length;i++){
  56.             System.out.println(s[i].getName()+" "+s[i].getSex()+" "+s[i].getScore());
  57.         }
  58.     }
  59.     @Override
  60.     public void sumscore() {
  61.         double sum=0;
  62.         for(int i=0;i<s.length;i++){
  63.             sum+=s[i].getScore();
  64.         }
  65.         System.out.println(sum/s.length);
  66.     }
  67. }
  68. class imp2 implements tool{
  69.     private student[] s;
  70.     public imp2(student[] s){
  71.         this.s=s;
  72.     }
  73.     @Override
  74.     public void listallinfo() {
  75.         int flag=0;
  76.         for(int i=0;i<s.length;i++){
  77.             System.out.println(s[i].getName()+" "+s[i].getSex()+" "+s[i].getScore());
  78.             if(s[i].getSex()=="boy"){
  79.                 flag++;
  80.             }
  81.         }
  82.         System.out.println("男生人数:"+flag+"女生人数:"+(s.length-flag));
  83.     }
  84.     @Override
  85.     public void sumscore() {
  86.         double max=s[0].getScore();
  87.         double min=s[0].getScore();
  88.         double sum=0;
  89.         for(int i=0;i<s.length;i++){
  90.             sum+=s[i].getScore();
  91.             if(max<s[i].getScore()){
  92.                 max=s[i].getScore();
  93.             }
  94.             if(min>s[i].getScore()){
  95.                 min=s[i].getScore();
  96.             }
  97.         }
  98.         System.out.println("去掉一个最高分和最低分后的平均分为"+(sum-max-min)/(s.length-2));
  99.     }
  100. }
复制代码
7.JDK8开始,接口新增的三种方法

  1. public class Demo{
  2.     public static void main(String[] args) {
  3.         A a=new impA();
  4.         a.run();
  5.         A.show();
  6.     }
  7. }
  8. class impA implements A{}
  9. interface A{
  10.     //1.大部分情况下,接口只能写抽象方法,jdk8之后,可以写普通实例方法了,但必须加default修饰
  11.     //默认用public修饰
  12.     //但是接口不能构建对象,应该怎么调用该方法?利用接口的实现类的对象来调用
  13.     default void run(){
  14.         System.out.println("--run--");
  15.         go();
  16.     }
  17.     //2.jdk9开始支持私有方法,他是私有的,利用接口的实现类的对象也不能调用了,只能使用接口中的其他实例方法来调用
  18.     private void go(){
  19.         System.out.println("--go--");
  20.     }
  21.     //3.静态方法,默认用public方法,如何调用?只能通过接口名字直接调用
  22.     static void show(){
  23.         System.out.println("--show--");
  24.     }
  25. }
复制代码
8.接口的留意事项

  1. //
  2. public class Demo{
  3.     public static void main(String[] args) {
  4.         
  5.     }
  6. }
  7. class D implements C{
  8.     @Override
  9.     public void show3() {}
  10.     @Override
  11.     public void show1() {}
  12.     @Override
  13.     public void show2() {}
  14. }
  15. interface A{
  16.     void show1();
  17. }
  18. interface B{
  19.     void show2();
  20. }
  21. interface C extends A,B{
  22.     void show3();
  23. }
复制代码
9.抽象类和接口的区别

雷同点:
1.都是抽象情势,都可以抽象方法,都不能创建对象
2.都是派生子类情势,抽象类是被子类继续利用,接口是被实现类实现
3.一个类继续抽象类,大概实现接口,都必须重写玩他们的抽象方法,否则本身要成为抽象类否则会报错
4.都能支持多态,都能实现解耦合
差异点:
1.抽象类可以界说类的全部平凡成员,接口只能界说常量和抽象方法(以及JDK8以后的三种新方法)
2.抽象类只能被类单继续,接口可以被类多实现
3.一个类继续抽象类就不能再继续别的类,一个类实现了接口还可以继续其他类或实现其他接口
4.抽象类表现模板头脑,更利于做父类,实当代码的复用性
5.接口更得当做功能的解耦合,解耦合性更强更机动。
6.计划目的
抽象类
紧张用于代码复用和提供一个通用的模板。它表现了一种 “is - a” 的关系,即子类是一种特殊的抽象类。比方,Dog是一种Animal,Dog类可以继续Animal抽象类,复用Animal类中的属性和方法,同时实现本身特有的举动(如makeSound()方法实现狗叫)。
接口
用于界说举动规范,实现接口的类必须依照这个规范。它表现了一种 “can - do” 的关系,即类可以做接口界说的变乱。比方,假如一个类实现了Flyable接口,就表现这个类可以飞行,不管这个类是Bird照旧Airplane,只要实现了Flyable接口,就必须实现fly()方法来界说飞行的举动。

10.一个案例

  1. import java.util.Scanner;
  2. public class Demo{
  3.     public static void main(String[] args) {
  4.         JD[] jd=new JD[3];
  5.         jd[0]=new Air("空调",true);
  6.         jd[1]=new TV("电视",false);
  7.         jd[2]=new Lamp("灯",false);
  8.         while(true) {
  9.             Control c = Control.getControl();
  10.             c.dolist(jd);
  11.             System.out.println("输入要控制的编号");
  12.             Scanner sc = new Scanner(System.in);
  13.             int tmp = sc.nextInt();
  14.             if(tmp==0){
  15.                 return;
  16.             }
  17.             c.dopress(jd[tmp - 1]);
  18.         }
  19.     }
  20. }
  21. class JD implements modif{
  22.     private String name;
  23.     private boolean status;
  24.     public JD(String name, boolean status) {
  25.         this.name = name;
  26.         this.status = status;
  27.     }
  28.     public JD(){}
  29.     public String getName() {
  30.         return name;
  31.     }
  32.     public void setName(String name) {
  33.         this.name = name;
  34.     }
  35.     public boolean isStatus() {
  36.         return status;
  37.     }
  38.     public void setStatus(boolean status) {
  39.         this.status = status;
  40.     }
  41.     @Override
  42.     public void press() {
  43.         this.status=!status;
  44.     }
  45. }
  46. class Lamp extends JD{
  47.     public Lamp(String name,boolean status){
  48.         super(name,status);
  49.     }
  50. }
  51. class TV extends JD{
  52.     public TV(String name,boolean status){
  53.         super(name,status);
  54.     }
  55. }
  56. class Air extends JD{
  57.     public Air(String name,boolean status){
  58.         super(name,status);
  59.     }
  60. }
  61. interface modif{
  62.     void press();
  63. }
  64. class Control {
  65.     private Control(){}
  66.     private static Control c=new Control();
  67.     public static Control getControl(){
  68.         return c;
  69.     }
  70.     public void dolist(JD[] jd){
  71.         for(int i=0;i< jd.length;i++){
  72.             System.out.println((i+1)+"号为"+jd[i].getName()+",当前状态为"+jd[i].isStatus());
  73.         }
  74.     }
  75.     public void dopress(JD jd){
  76.         System.out.println(jd.getName()+"当前状态为"+((jd.isStatus()==true)?"开":"关"));
  77.         jd.setStatus(!jd.isStatus());
  78.         System.out.println(jd.getName()+"当前状态为"+((jd.isStatus()==true)?"开":"关"));
  79.     }
  80. }
复制代码
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表