Skip to content

Java 面向对象

一、核心修饰符

Java修饰符主要分为 访问修饰符非访问修饰符,用于限定类、属性、方法的特性和访问范围。

1. 访问修饰符(控制访问权限)
修饰符作用可修饰目标核心说明
public全局访问类、属性、方法、接口所有包、所有类均可访问
protected受保护访问属性、方法(不可修饰顶层类)本类、同包类、子类可访问
default同包访问类、属性、方法、接口仅同一包下的类可访问
private私有访问属性、方法(不可修饰顶层类)仅当前类内部可访问
2. 非访问修饰符(赋予特殊特性)
修饰符作用可修饰目标核心说明
static静态修饰属性、方法、代码块、内部类属于「类」而非「对象」,全局共享,可通过类名直接调用
final最终修饰类、属性、方法修饰类:不可继承;修饰方法:不可重写;修饰变量:不可修改(常量)
abstract抽象修饰类、方法修饰类:抽象类,不可实例化;修饰方法:抽象方法,无实现体,子类必须重写
final最终修饰类、属性、方法修饰类不可继承,修饰方法不可重写,修饰变量不可修改(赋值后不能变更)
transient瞬态修饰属性序列化时忽略该属性,不参与对象的序列化过程
synchronized同步修饰方法、代码块保证多线程环境下的线程安全,防止资源竞争

二、类与对象

1. 类的定义与使用

类是对象的模板,包含属性(成员变量)和方法(行为):

java
// 类的基本结构
public class Person {
  // 属性(成员变量)
  String name;
  int age;
  private String idCard; // 私有属性,仅类内部访问

  // 方法(行为)
  public void eat() {
    System.out.println(name + "在吃饭");
  }

  // 带参数的方法
  public void sayHello(String friendName) {
    System.out.println(name + "向" + friendName + "问好");
  }
}
java
public class Test {
  public static void main(String[] args) {
    // 创建对象(实例化)
    Person person = new Person();
    
    // 访问对象属性
    person.name = "张三";
    person.age = 25;
    
    // 调用对象方法
    person.eat(); // 输出:张三在吃饭
    person.sayHello("李四"); // 输出:张三向李四问好
  }
}

2. 构造方法

  • 方法名与类名完全一致,无返回值类型(连 void 都没有)
  • 用于对象初始化,创建对象时自动调用
  • 若未自定义构造方法,系统会提供默认无参构造方法
  • 可重载(多个构造方法参数列表不同)

快捷生成 Javabean

快捷键:alt + insert / alt + fn + insert

插件:PTG 1秒生成标准 Javabean

java
public class Person {
  String name;
  int age;

  // 无参构造方法(默认构造)
  public Person() {
    this.name = "未知姓名";
    this.age = 0;
  }

  // 带参构造方法(重载)
  public Person(String name, int age) {
    this.name = name; // this 区分成员变量和局部变量
    this.age = age;
  }

  // 构造方法调用其他构造方法(通过 this(),必须在第一行)
  public Person(String name) {
    this(name, 18); // 调用带两个参数的构造方法
  }
}

// 使用构造方法创建对象
Person p1 = new Person(); // 无参构造,name=未知姓名,age=0
Person p2 = new Person("张三", 25); // 带参构造
Person p3 = new Person("李四"); // 调用单参构造,age=18
练习
public class Student {
  private int id;
  private String name;
  private int age;

  public Student() {}

  public Student(int id, String name, int age) {
    this.id = id;
    this.name = name;
    this.age = age;
  }

  public int getId() {
    return id;
  }
}
public class StudentTest {
  public static void main(String[] args) {
    Student[] arr = new Student[4];

    Student stu1 = new Student(1, "张三", 18);
    Student stu2 = new Student(2, "小米", 18);
    Student stu3 = new Student(3, "阿萨", 18);

    arr[0] = stu1;
    arr[1] = stu2;
    arr[2] = stu3;
    System.out.println(contains(arr, new Student(3, "阿萨", 18)));
  }

  public static boolean contains(Student[] arr, Student stu) {
    for (int i = 0; i < arr.length; i++) {
      if (arr[i].getId() == stu.getId()) {
        System.out.println("已经存在");
        return false;
      }
    }
    return true;
  }
}

三、继承与多态

1. 继承(extends)

  • 单继承:一个类只能继承一个父类,但可多层继承
  • 子类继承父类的非私有属性和方法(private 修饰的不可继承)
  • 子类可通过 super 调用父类的构造方法、属性和方法
非私有private
构造方法
成员变量✔️✔️
成员方法✔️
java
// 父类
public class Animal {
  String type;

  public void eat() {
    System.out.println(type + "在吃东西");
  }
}

// 子类继承父类
public class Dog extends Animal {
  // 子类特有属性
  String name;

  // 子类重写父类方法(@Override 注解标识)
  @Override
  public void eat() {
    System.out.println(name + "(" + type + ")在吃骨头");
  }

  // 子类特有方法
  public void bark() {
    System.out.println(name + "在叫");
  }
}

// 使用子类
Dog dog = new Dog();
dog.type = "犬科";
dog.name = "旺财";
dog.eat(); // 输出:旺财(犬科)在吃骨头
dog.bark(); // 输出:旺财在叫

2. 多态

  • 同一行为的不同表现形式,基于继承和方法重写实现
  • 条件:子类继承父类、子类重写父类方法、父类引用指向子类对象

多态调用成员的特点

1️⃣ 变量调用:编译看左边,运行也看左边。

2️⃣ 方法调用:编译看左边,运行看右边。

Animal a = new Dog();

换句话讲

成员变量:在子类的对象中,会把父类的成员变量也继承下来的

成员方法:如果子类对方法进行了重写,那么在虚方法表中是会把父类的方法进行覆盖

java
public class Cat extends Animal {
  String name;

  @Override
  public void eat() {
    System.out.println(name + "(" + type + ")在吃鱼");
  }

  public void catchMouse() {
    System.out.println(name + "在抓老鼠");
  }
}

// 多态体现:父类引用指向子类对象
Animal animal1 = new Dog();
Animal animal2 = new Cat();

animal1.type = "犬科";
((Dog) animal1).name = "旺财"; // 向下转型才能访问子类特有属性
animal1.eat(); // 输出:旺财(犬科)在吃骨头

animal2.type = "猫科";
((Cat) animal2).name = "咪宝";
animal2.eat(); // 输出:咪宝(猫科)在吃鱼

四、权限修饰符

控制类、属性、方法的访问范围,从大到小排序:(private < 空着不写 < protected < public)

修饰符说明本类同包子类其他包
public公共的✔️✔️✔️✔️
protected受保护的✔️✔️✔️
默认(无修饰符)只能本包使用✔️✔️
private私房自己用✔️
java
public class Person {
  public String publicAttr;    // 所有地方可访问
  protected String protectAttr;// 本类、同包、子类可访问
  String defaultAttr;          // 本类、同包可访问
  private String privateAttr;  // 仅本类可访问

  public void publicMethod() {}
  protected void protectMethod() {}
  void defaultMethod() {}
  private void privateMethod() {}
}

五、接口(interface)

  • 纯抽象的行为规范,仅包含抽象方法(JDK8+ 支持默认方法 default 和静态方法 static
  • 接口中的属性默认是 public static final(常量)
  • 类通过 implements 实现接口,可多实现(弥补单继承缺陷)
  • 实现类必须重写接口的所有抽象方法
java
// 定义接口
public interface Flyable {
  // 常量(默认 public static final)
  String TYPE = "飞行生物";

  // 抽象方法(默认 public abstract)
  void fly();

  // 默认方法(带实现,可被实现类重写)
  default void showInfo() {
    System.out.println("这是" + TYPE);
  }

  // 静态方法(属于接口,通过接口名调用)
  static void staticMethod() {
    System.out.println("飞行接口的静态方法");
  }
}

// 类实现接口
public class Bird implements Flyable {
  @Override
  public void fly() {
    System.out.println("小鸟在天空飞翔");
  }
}

// 多实现接口
public class Plane implements Flyable, Runnable {
  @Override
  public void fly() {
    System.out.println("飞机在高空飞行");
  }

  @Override
  public void run() {
    System.out.println("飞机在跑道滑行");
  }
}

// 使用
Bird bird = new Bird();
bird.fly(); // 输出:小鸟在天空飞翔
bird.showInfo(); // 输出:这是飞行生物
Flyable.staticMethod(); // 输出:飞行接口的静态方法

六、抽象类(abstract class)

  • abstract 修饰,不能直接实例化(需通过子类继承并实例化)
  • 可包含抽象方法(无实现)和普通方法(有实现)
  • 子类必须重写抽象类的所有抽象方法(除非子类也是抽象类)
  • 抽象类是"模板",接口是"规范",抽象类可实现接口
java
// 抽象类
public abstract class Vehicle {
  String brand;

  // 普通方法(有实现)
  public void start() {
    System.out.println(brand + "启动了");
  }

  // 抽象方法(无实现,子类必须重写)
  public abstract void run();
}

// 子类继承抽象类
public class Car extends Vehicle {
  @Override
  public void run() {
    System.out.println(brand + "汽车在公路上行驶");
  }
}

// 使用
Car car = new Car();
car.brand = "特斯拉";
car.start(); // 输出:特斯拉启动了
car.run(); // 输出:特斯拉汽车在公路上行驶

七、内部类

定义在另一个类内部的类,根据位置和修饰符分为:

1. 成员内部类

  • 定义在类的成员位置,可访问外部类的所有属性和方法
  • 创建方式:外部类.内部类 变量名 = new 外部类().new 内部类()
java
public class Outer {
  private String outerAttr = "外部类属性";

  // 成员内部类
  public class Inner {
    public void show() {
      System.out.println("访问外部类属性:" + outerAttr);
    }
  }
}

// 创建和使用内部类
Outer.Inner inner = new Outer().new Inner();
inner.show(); // 输出:访问外部类属性:外部类属性

2. 静态内部类

  • static 修饰的成员内部类,不能访问外部类的非静态资源
  • 创建方式:外部类.内部类 变量名 = new 外部类.内部类()
java
public class Outer {
  private static String staticAttr = "外部类静态属性";

  // 静态内部类
  public static class StaticInner {
    public void show() {
      System.out.println("访问外部类静态属性:" + staticAttr);
    }
  }
}

// 创建和使用静态内部类
Outer.StaticInner staticInner = new Outer.StaticInner();
staticInner.show(); // 输出:访问外部类静态属性:外部类静态属性

3. 局部内部类

  • 定义在方法内部,作用域仅限于当前方法
  • 不能用访问修饰符修饰,可访问方法的局部变量(需是 final 或effectively final)
java
public class Outer {
  public void method() {
    String localVar = "方法局部变量";

    // 局部内部类
    class LocalInner {
      public void show() {
        System.out.println("访问方法局部变量:" + localVar);
      }
    }

    // 方法内部创建并使用
    LocalInner localInner = new LocalInner();
    localInner.show();
  }
}

// 调用
new Outer().method(); // 输出:访问方法局部变量:方法局部变量

4. 匿名内部类(常用)

  • 没有类名的局部内部类,常用于快速实现接口或抽象类
  • 一次性使用,不能重复创建对象
java
// 接口
public interface Greet {
  void sayHello();
}

// 使用匿名内部类实现接口
public class Test {
  public static void main(String[] args) {
    // 匿名内部类(直接实现 Greet 接口)
    Greet greet = new Greet() {
      @Override
      public void sayHello() {
        System.out.println("你好,匿名内部类!");
      }
    };

    greet.sayHello(); // 输出:你好,匿名内部类!
  }
}

小结

知识点重点强调常见误区
类与对象类是模板,对象是实例,new 关键字创建对象混淆成员变量和局部变量的作用域
构造方法方法名与类名一致,无返回值,支持重载忘记调用 super() 导致父类初始化失败
继承多态单继承、方法重写是多态的基础父类引用不能直接访问子类特有方法(需转型)
权限修饰符private 仅本类访问,public 全局访问误将 protected 当作全局访问修饰符
接口与抽象类接口是规范(多实现),抽象类是模板(单继承)抽象类不能实例化,接口不能有普通方法(JDK8+ 除外)
内部类匿名内部类常用于快速实现接口局部内部类访问局部变量需满足 final 要求
核心修饰符static 属于类,final 不可修改/继承/重写,abstract 不可实例化混淆 static 修饰的成员与对象成员的调用方式
  1. 修饰符分为访问修饰符(4种)和非访问修饰符(核心为staticfinalabstract),用于限定类和成员的特性与访问范围。
  2. 面向对象核心三大特性是封装(权限修饰符实现)、继承(extends)、多态(父类引用指向子类对象+方法重写)。
  3. 接口是纯规范(多实现),抽象类是模板(单继承),内部类中匿名内部类最常用,用于快速实现接口/抽象类。

小小棱镜,无限可能 | CC BY-NC-SA 4.0 协议