面向对象

面向对象

面向对象(OOP)的本质就是以类的方式组织代码,以对象的组织(封装)数据

类是一种抽象的数据类型,它是对某一类事物整体的描述/定义,但不能代表某一个具体的事物

对象是抽象概念的具体实例

package com.oop.demo01;

import java.io.IOException;

/**
 * @description 方法的定义:修饰符 返回类型 break跳出switch,结束循环 return是结束方法 方法名:见名知意命名要规范
 * 参数列表:(参数类型 参数名) (参数类型... 参数名) 异常抛出
 * @author kjy06123
 * @date 2025/4/1 22:51
 */
// Demo01 类
public class Demo01 {
  // main 方法
  public static void main(String[] args) {}

  /*
   修饰符  返回值  方法名(...){
       //方法体
      return 返回值;
      }
  */
  // return 结束方法,返回一个结果
  public String sayHello() {
    return "Hello";
  }

  public void print() {
    return;
  }

  public int max(int a, int b) {
    return a > b ? a : b;//三元运算符
  }
  //数组下标越界:Arrayindexoutofbounds
  public void readFile(String file)throws IOException{

  }
}
package com.oop.demo01;

/**
 * @description 方法的调用 递归调用 静态方法 非静态方法 形参和实参 值传递和引用传递 this关键字
 * @author kjy06123
 * @date 2025/4/1 23:04
 */
public class Demo02 {
    public static void main(String[] args){
        //实例化这个类 new
        //对象类型 对象名 = 对象值;
        Student student = new Student();
        student.say();
    }

    // static和类一起加载的
    public static void a(){
        // b();
    }
    //类实例化后才存在的
    public  void b(){

    }
}
package com.oop.demo01;

/**
 * @description
 * @author kjy06123
 * @date 2025/4/1 23:21
 */
public class Demo03 {
    public static void main(String[] args){
        //实际参数和形式参数的类型要对应
        int add = Demo03.add(1, 2);
        System.out.println(add);
    }
    public static int add(int a,int b){
        return a + b;
    }

}
package com.oop.demo01;

/**
 * @description 值传递
 * @author kjy06123
 * @date 2025/4/1 23:30
 */
public class Demo04 {
    public static void main(String[] args){
        int a = 1;
    System.out.println(a);
    Demo04.change(a);
    System.out.println(a);
    }
    public static void change(int a){
        a = 10;
    }
}
package com.oop.demo01;

/**
 * @description 引用传递:传递对象,本质还是值传递
 * @author kjy06123
 * @date 2025/4/1 23:34
 */
public class Demo05 {
  public static void main(String[] args) {
    Person person = new Person();
    System.out.println(person.name);
    Demo05.change(person);
    System.out.println(person.name);
  }

  public static void change(Person person) {
    // person是一个对象指向的是Person person = new Person();这是一个具体的人,可以改变属性
    person.name = "kjy06123";
  }
}

// 定义一个Person类,属性为name
class Person {
  String name;
}
package com.oop.demo02;

/**
 * @description
 * @author kjy06123
 * @date 2025/4/2 23:07
 */

// 在out文件中查看源码
public class Person {
  // 一个类即使什么都不写,它也会存在一个方法叫做构造器或者构造方法:public Person(){}
  String name;

  // 构造器:
  // 1.使用new关键字,本质是在调用构造器
  // 2.用来初始化值
  public Person() {
    this.name = "kjy06123";
  }

  // 有参构造器:一旦定义了有参构造器,无参构造器必须显示定义
  public Person(String name) {
    this.name = name;
  }
  // 使用alt + insert 选择Constructor可以快速创建构造器

}
/*
 public static void main(String[] args) {
   // new:实例化了一个对象
   Person person = new Person();
   System.out.println(person.name); // null
   // 总结
   // 构造器:
   // 1.和类名相同
   // 2.没有返回值
   // 作用:
   // 1.new 本质就是调用构造方法
   // 2.初始化对象的值
   // 注意点:
   // 1.定义有参构造器之后,如果想使用无参构造器,就得构造一个显示的无参构造器
   // alt + Insert
   //  this. XX(表示当前类)=XX(参数传进来的值)
 }
*/

封装

高内聚,低耦合

高内聚就是类的内部数据操作细节自己完成,不允许外部干涉;低耦合:仅暴露少量的方法给外部使用。

数据的隐藏:通常禁止直接访问一个对象中数据的实际表示,而应通过操作接口来访问

属性私有 get/set

package com.oop.demo04;

/**
 * @description
 * @author kjy06123
 * @date 2025/4/18 17:08
 */
public class Student {
  // 属性私有
  private String name;
  private int id;
  private char sex;
  private int age;

  // 提供一些可以操作这个属性的方法 ,public 的get和set方法
  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public char getSex() {
    return sex;
  }

  public void setSex(char sex) {
    this.sex = sex;
  }

  public int getAge() {
    return age;
  }

  public void setAge(int age) {
    if (age < 0 || age > 120) {
      this.age = 3;
    } else {
      this.age = age;
    }
  }
}
/*
public static void main(String[] args){
  Student s1 = new Student();
  s1.setName("kjy");
  System.out.println(s1.getName());
  s1.setAge(-1);
  System.out.println(s1.getAge());
}
 */
/*
   1. 提高程序的安全性,保护数据
   2.隐藏代码的实现细节
   3.统一接口
   4.系统可维护性增加了
*/

继承

本质是对某一批类的抽象,从而实现对现实世界更好的建模

extends :扩展

java中类只有单继承,没有多继承!

继承是类和类之间的一种关系。类与类之间的关系还有依赖、组合、聚合等。

super注意点:

  1. super调用父类的构造方法,必须在构造方法的第一个
  2. super只能出现在子类的方法或者构造方法中
  3. super和this不能同时调用构造方法

Vs this:

​ 代表的对象不同:

​ this:本身调用这个对象

​ super:代表父类对象的引用

​ 前提

​ this:没有继承也可以使用

​ super:只能在继承条件下才可以使用

​ 构造方法

​ this()本类的构造

​ super()父类的构造

重写:需要有继承关系,子类重写父类的方法

  1. 方法名必须相同
  2. 参数列表必须相同
  3. 修饰符:范围可以扩大但不能缩小: Public>Protected>Default>Private
  4. 抛出的异常:范围可以被缩小,但不能扩大

重写子类的方法和父类必须要一致,方法体不同

为什么需要重写:

1. 父类的功能,子类不一定需要,或者不一定满足
1. Alt + Insert    override;

多态

多态是方法的多态,属性没有多态

父类和子类有联系 不然会出现类型转换异常如ClassCastException

存在条件:继承关系,方法需要重写,父类引用指向子类对象 Father f1 = new Son();

不能重写的有:

  1. static 方法 属于类,不属于实例
  2. final 常量
  3. private 方法

instanceof (类型类型)引用类型,判断一个对象是什么类型

父类引用指向子类的对象

子类转换成父类,向上转型

父类转换成子类,向下转型:强制转换

方便方法的调用,减少重复的代码简洁

//static只会在类加载时运行一次
public class Person {
    {
    System.out.println("匿名代码块");
    }
    static {
    System.out.println("静态代码块");
    }
    public Person(){
    System.out.println("构造方法");
    }
    public static void main(String[] args){
        Person person = new Person();
    System.out.println("================");
        Person person1 = new Person();
    }
}

image-20250420205531169

import static java.lang.Math.random;

/**
 * @description
 * @author kjy06123
 * @date 2025/4/20 20:57
 */
public class Test {
    public static void main(String[] args){
    System.out.println(random());
    }
}

抽象类

当父类的某些方法,需要声明,但是又不确定如何实现时,可以将声明为抽象方法,那么这个类就是抽象类

package com.oop.demo08;

/**
 * @description abstract 抽象类
 * @author kjy06123
 * @date 2025/4/20 21:41
 */
public abstract class Action {
    //抽象方法只有方法名,没有方法的实现
    public abstract void doSomething();

    //不能new 只能靠子类来去实现
    //抽象类中可以写普通的方法
    //抽象方法必须在抽象类中
}
package com.oop.demo08;

/**
 * @description
 * @author kjy06123
 * @date 2025/4/20 21:44
 */
//extends 是单继承的   接口是可以多继承
//抽象类的方法,必须由继承他的子类来实现方法重写 除非子类也是抽象的
public class A extends Action{
    @Override
    public void doSomething() {

    }
}

接口

接口就是给出一些没有实现的方法,封装到一起,到某个类需要使用时根据具体情况在把方法实现出来

语法:

interface 接口名{

//属性

//方法(1抽象方法 2默认实现方法(default)3静态方法(static)))

}

class 类名 implements 接口{

自己属性

自己方法

必须要实现接口的抽象方法

}

细节:

  1. 接口不能被实例化
  2. 接口的所有方法都是public,接口中抽象方法可以不用abstract修饰
  3. 一个普通类实现接口,必须将该接口所有方法都实现
  4. 抽象类实现接口,可以不用实现接口方法 class abstract A implements IA{}
  5. 一个类同时可以实现多个接口 class C implements A,B{}
  6. 接口中的属性都是public static final修饰的比如 int a =1;实际上是public static final int a =1;
  7. 接口中属性的访问形式:接口名.属性名
  8. 接口不能继承其他类,但是可以继承多个别的接口 interface A extends B,C{}
  9. 接口的修饰符只能是public和默认这个和类的修饰符一样 public interface AI {}||interface AI {}

接口在一定程度上实现代码解耦(接口规范性+动态绑定机制)

接口的多态性

  1. 多态参数

    package com.kjy06123.interface_;
    
    /**
     * @description 多态参数
     * @author kjy06123
     * @date 2025/4/25 0:37
     */
    public class InterfacePolyParameter {
      public static void main(String[] args) {
        // 接口的多态体现
        // 接口类型的变量if01可以指向实现了IF接口类的对象实例
        IF if01 = new Monster();
        if01 = new Car();
        // 继承体现的多态
        // 父类类型的变量a可以指向继承AAA的子类的对象实例
        AAA a = new BBB();
        a = new CCC();
      }
    }
    
    interface IF {}
    
    class Monster implements IF {}
    
    class Car implements IF {}
    
    class AAA {}
    
    class BBB extends AAA {}
    
    class CCC extends AAA {}
    
    
  2. 多态数组

    package com.kjy06123.interface_;
    
    /**
     * @description 多态数组
     * @author kjy06123
     * @date 2025/4/25 0:43
     */
    public class InterfacePolyArr {
        public static void main(String[] args){
            Usb[] usbs = new Usb[2];
            usbs[0] = new Phone_();
            usbs[1] = new Camera_();
            for(int i = 0; i < usbs.length; i++) {
                usbs[i].work();
                if (usbs[i] instanceof Phone_){
                    ((Phone_) usbs[i]).call();
                }
            }
        }
    }
    interface Usb{
        void work();
    }
    class Phone_ implements Usb{
        public void call(){
        System.out.println("Phone calling");
        }
        @Override
        public void work() {
        System.out.println("Phone working");
        }
    }
    class Camera_ implements Usb{
        @Override
        public void work() {
        System.out.println("camera working");
        }
    }
    
  3. 接口存在多态传递

    package com.kjy06123.interface_;
    
    /**
     * @description 多态传递现象
     * @author kjy06123
     * @date 2025/4/25 0:55
     */
    public class InterfacePolyPass {
        public static void main(String[] args){
            IG ig = new Teacher();
            IH ih = new Teacher();
        }
    }
    interface IH{}
    interface IG extends IH{}
    class Teacher implements IG{}
    

内部类

局部内部类

package com.kjy06123.innerclass;

/**
 * @description 局部内部类的使用
 * @author kjy06123
 * @date 2025/4/25 20:29
 */
public class LocalInnerClass {
  public static void main(String[] args) {
    Outer02 outer02 = new Outer02();
    outer02.m1();
  }
}

class Outer02 {//外部类
  private int n1 = 100;

  private void m2() {
    System.out.println("Outer02 m2()");
  }

  public void m1() {
    // 1.局部内部类是定义在外部类的局部位置,通常在方法
    // 3.不能添加访问修饰符,但是可以使用final修饰
    // 4.作用域:仅仅在定义它的方法或代码块中
    final class Inner02 {//局部内部类(本质还是一个类)
      // 2.可以直接访问外部类的所有成员,包含私有的
      public void f1() {
        // 5.局部内部类可以直接访问外部类的成员,比如下面 外部类n1 和m2()
        System.out.println("n1=" + n1);
        m2();
      }
    }
    // 6.外部类在方法中,可以创建Inner02对象,然后调用方法即可
    Inner02 inner02 = new Inner02();
    inner02.f1();
  }
}
//局部内部类定义在方法中或代码块
//作用域在方法体或者代码块中
//本质还是一个类

匿名内部类

package com.kjy06123.innerclass;

/**
 * @description 匿名内部类
 * @author kjy06123
 * @date 2025/4/25 21:13
 */
public class AnonymousInnerClass {
  public static void main(String[] args) {
    Outer04 outer04 = new Outer04();
    outer04.method();
  }
}

class Outer04 {
  private int n1 = 10;

  public void method() {
    // 基于接口的匿名内部类
    // 1.需求:想使用IA接口,并创建对象
    // 2.传统方式,写一个类,实现该接口,并创建对象
    // IA tiger = new Tiger();//传统方式
    // tiger.cry();
    // 3.需求:Tiger类只使用一次,后面不再使用
    // 4.使用匿名内部类来简化开发
    // 5.tiger的编译类型是IA 运行类型就是匿名内部类(Outer04$1)
    /* 底层会分配 类名 Outer04$1
    class Outer04$1 implements IA{
     @Override
      public void cry() {
        System.out.println("Tiger 叫唤");
      }
    }
    }
     */
    // 6.jdk底层在创建匿名内部类 Outer04$1,立即马上就创建了Outer04$1实例,并把地址
    //  返回给tiger
    // 7.匿名内部类使用一次,就不能再使用了
    IA tiger =
        new IA() {
          @Override
          public void cry() {
            System.out.println("Tiger 叫唤");
          }
        };
    System.out.println("tiger的运行类型=" + tiger.getClass()); // Outer04$1
    tiger.cry();

    // 分析基于接口的匿名内部类
    // 1.father编译类型是Father
    // 2.运行类型是Outer04$2
    // 3.底层会创建匿名内部类
    /*
       class Outer04$2 extends Father{
    @Override
             public void test() {
               System.out.println("匿名内部类重写了test方法");
             }
       }
        */
      //4.同时也直接返回了匿名内部类 Outer04$2的对象
      //5.(jack)参数列表会传递给 构造器
    Father father =
        new Father("jack") {
          @Override
          public void test() {
            System.out.println("匿名内部类重写了test方法");
          }
        };

    System.out.println("father对象的运行类型=" + father.getClass()); // Outer04$2
    father.test();

    // 基于抽象类的匿名内部类
    Animal animal =
        new Animal() {
          @Override
          void eat() {
            System.out.println("dog");
          }
        };
    animal.eat();
  }
}

interface IA {
  public void cry();
}

// class Tiger implements IA{//传统方式
//   @Override
//   public void cry() {
//     System.out.println("Tiger 叫唤");
//   }
// }
class Father {
  public Father(String name) {
    System.out.println("接收到name="+name);
  }

  public void test() {}
}
abstract class  Animal{
    abstract void eat();

}
package com.kjy06123.innerclass;

/**
 * @description
 * @author kjy06123
 * @date 2025/4/25 23:32
 */
public class AnonymousInnerClassDetail {
    public static void main(String[] args){
        Outer05 outer05 = new Outer05();
        outer05.f1();
        //外部其他类 不能访问匿名内部类
        System.out.println("main Outer05 hashcode="+outer05);
    }
}
class Outer05{
private int n1 = 99;
public void f1(){
    // 不能添加访问修饰符,因为它的地位就是一个局部变量
    // 作用域:仅仅在定义它的方法或代码块中
    Person person =
        new Person() {
          private int n1 = 88;

          @Override
          public void hi() {
            // 可以直接访问外部类的所有成员,包含私有的
            // 如果外部类和匿名内部类的成员重名时,匿名内部类访问的话,
            // 默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.this.成员)去访问
            System.out.println("匿名内部类重写了hi方法 n1=" + n1 + "外部类的n1=" + Outer05.this.n1);
            System.out.println("Outer05.this hashcode="+Outer05.this);
          }
        };
    person.hi();
    new Person() {
        @Override
        public void hi() {
            System.out.println("匿名内部类重写了hi方法 哈哈哈");
        }

        @Override
        public void ok(String str) {
            super.ok(str);
        }
    }.ok("jack");
}
}
class Person{
    public void hi(){
        System.out.println("Person hi()");
    }
    public void ok(String str){
        System.out.println("Person ok()"+ str);
    }
}

匿名内部类的最佳实践

package com.kjy06123.innerclass;

/**
 * @description 匿名内部类的最佳实践
 * @author kjy06123
 * @date 2025/4/26 0:34
 */
public class InnerClassExercise {
  public static void main(String[] args) {
    // 当做实参直接传递,简洁高效
    f1(
        new IL() {
          @Override
          public void show() {
            System.out.println("hello");
          }
        });
      //传统方法
    f1(new Picture());
  }

  // 静态方法,形参是接口类型
  public static void f1(IL il) {
    il.show();
  }
}

interface IL {
  void show();
}

// 类->实现 IL => 编程领域 (硬编码)
class Picture implements IL {
  @Override
  public void show() {
    System.out.println("这是一副名画 XX...");
  }
}

成员内部类

package com.kjy06123.innerclass;

/**
 * @description 成员内部类
 * @author kjy06123
 * @date 2025/4/26 15:46
 */
public class MemberInnerClass {
  public static void main(String[] args) {
    Outer08 outer08 = new Outer08();
    outer08.t1();
    //外部其他类,使用成员内部类的三种方式
    //第一种
    //outer08.new Inner08();相当于把 new Inner08()当做outer08成员
    Outer08.Inner08 inner08 = outer08.new Inner08();
    inner08.say();
    //第二种在外部类中,编写一个方法返回Inner08duixiang
    Outer08.Inner08 inner08Instance = outer08.getInner08Instance();
    inner08Instance.say();
  }
}

class Outer08 { // 外部类
  private int n1 = 10;
  public String name = "张三";
  private void hi(){
    System.out.println("hi()");
  }

  //1.注意:成员内部类,是定义在外部类的成员位置上
  //2.可以添加任意访问修饰符(public protected 默认 private),因为它的地位就是一个成员
  class Inner08 { // 成员内部类
    public double sal = 998;
    private int n1 = 666;
    public void say() {
      // 可以直接访问外部类的所有成员,包含私有的
      //如果成员内部类的成员和外部类的成员重名,就会遵守就近原则
      //可以通过 外部类名.this.属性 来访问外部类的成员
      System.out.println("n1=" + n1 + "name=" + name +"外部类的n1="+Outer08.this.n1);
      hi();
    }
  }
//写一个方法,返回Inner08实例
  public Inner08 getInner08Instance(){
    return new Inner08();
  }
  // 写方法
  public void t1() {
    // 使用成员内部类
    // 创建成员内部类的对象,然后使用相关的方法
    Inner08 inner08 = new Inner08();
    inner08.say();
    System.out.println(inner08.sal);
  }
}

静态内部类

package com.kjy06123.innerclass;

/**
 * @description 静态内部类
 * @author kjy06123
 * @date 2025/4/26 21:06
 */
public class StaticInnerClass {
  public static void main(String[] args) {
    Outer10 outer10 = new Outer10();
    outer10.m1();
    // 外部其他类 使用静态内部类
    // 方式 1
    // 因为静态内部类,是可以通过类名直接访问(前提是满足访问权限)
    Outer10.Inner10 inner10 = new Outer10.Inner10();
    inner10.say();
    // 方式 2
    // 编写一个方法,可以返回静态内部类的对象实例. Outer10.Inner10 inner101 = outer10.getInner10();
    System.out.println("============");
    inner10.say();
    Outer10.Inner10 inner10_ = Outer10.getInner10_();
    System.out.println("************");
    inner10_.say();
  }
}

class Outer10 { // 外部类
  private int n1 = 10;
  private static String name = "张三";

  private static void cry() {}

  // Inner10 就是静态内部类
  // 1. 放在外部类的成员位置
  // 2. 使用 static 修饰
  // 3. 可以直接访问外部类的所有静态成员,包含私有的,但不能直接访问非静态成员
  // 4. 可以添加任意访问修饰符(public、protected 、默认、private),因为它的地位就是一个成员
  // 5. 作用域 :同其他的成员,为整个类体
  static class Inner10 {
    private static String name = "jack";

    public void say() {
      // 如果外部类和静态内部类的成员重名时,静态内部类访问的时,
      // 默认遵循就近原则,如果想访问外部类的成员,则可以使用 (外部类名.成员)
      System.out.println(name + " 外部类 name= " + Outer10.name);
      cry();
    }
  }

  public void m1() { // 外部类---访问------>静态内部类 访问方式:创建对象,再访问
    Inner10 inner10 = new Inner10();
    inner10.say();
  }

  public Inner10 getInner10() {
    return new Inner10();
  }

  public static Inner10 getInner10_() {
    return new Inner10();
  }
}
posted @ 2025-04-28 20:20  kjy06123  阅读(25)  评论(0)    收藏  举报