Java 核心知识点查漏补缺(一)

Java 核心概念补充说明

一、封装的实际意义与示例解析

封装是面向对象三大特性之一,核心是通过访问权限控制隐藏类的内部实现细节,仅暴露必要的接口供外部交互。

以Person.java为例:

  • name属性用private修饰,限制了直接访问(如person.name = "xiaoming"会报错)
  • 通过public修饰的getName()setName()方法提供访问入口,可在方法中添加验证逻辑(如姓名长度限制)
  • 优势:保护数据完整性、降低代码耦合度、便于后续维护扩展

二、接口的应用场景与特性

接口是一种行为规范,用于定义类必须实现的方法,不关注具体实现。

从Flyable.java和Bird.java看接口特性:

  1. 抽象方法 :如fly(),实现类必须重写(Bird类实现了fly()方法)
  2. 默认方法 :带default关键字,有默认实现,实现类可选择重写(Bird重写了land()方法)
  3. 静态方法 :带static关键字,属于接口本身,通过接口名直接调用(Flyable.info()
  4. 多实现特性:类可同时实现多个接口,弥补 Java 单继承的局限性

接口降低耦合度的体现:当需要新增 "飞行" 功能的类(如Plane)时,只需实现Flyable接口,无需修改原有代码。

三、抽象类与接口的区别

Animal抽象类和Flyable接口对比:

特性 抽象类 接口
关键字 abstract class interface
实例化 不能 不能
方法类型 可包含抽象方法和具体方法 JDK8 + 可包含抽象方法、默认方法、静态方法
继承 / 实现 单继承(extends 多实现(implements
成员变量 可包含各种权限的变量 只能是public static final常量
设计意图 体现 "is-a" 关系(如Dog is a Animal 体现 "has-a" 能力(如Bird has a Flyable能力)

四、内部类的特性与使用场景

以Outer.java中的成员内部类为例:

  1. 访问权限 :内部类可直接访问外部类的所有成员(包括private修饰的outerVar
  2. 创建方式
    • 外部类内部:直接new Inner()
    • 外部类外部:需通过外部类实例创建(outer.new Inner()
  3. 应用场景
    • 当内部类仅服务于外部类时,可隐藏实现细节
    • 方便访问外部类的成员,适合编写事件监听器等场景

五、==equals()的深层对比

结合Test01.java中的示例:

  1. 基本数据类型==比较值(如a == c中 10 与 10.0 值相等,返回 true)
  2. 引用数据类型
    • ==比较内存地址(s1 == s2为 false,因是两个不同对象)
    • equals()默认等同于==(Object 类实现),但可重写用于内容比较(如 String 类重写后比较字符序列)
  3. 注意点
    • 比较字符串内容时应使用equals(),而非==
    • 重写equals()时需遵循对称性、传递性等规则,通常需同时重写hashCode()

六、静态成员的特性与生命周期

从Test01.java的Student类示例:

  1. 静态变量static String school):
    • 属于类本身,所有对象共享同一份内存
    • 一个对象修改后,所有对象访问到的都是修改后的值
  2. 静态方法static void eat()):
    • 通过类名直接调用(Student.eat()),无需创建对象
    • 不能访问非静态成员(因静态成员加载时非静态成员可能尚未初始化)
  3. 静态代码块
    • 类加载时执行,且只执行一次
    • 用于初始化静态资源,执行顺序早于构造器

七、多态的实现与优势

在Test02.java中体现:

  1. 向上转型Animal dog = new Dog("旺财")
    • 父类引用指向子类对象,自动完成
    • 可调用父类声明的方法,实际执行子类重写的实现(如dog.eat()执行Dog类的eat()
  2. 优势
    • 提高代码灵活性:同一方法调用可表现不同行为
    • 便于扩展:新增子类(如Cat)无需修改使用父类的代码
  3. instanceof运算符 :判断对象实际类型,避免转型错误(如animal instanceof Dog

八、权限修饰符的实际应用

根据Test01.java中的权限表:

  • private:仅本类可见,用于隐藏内部状态(如Personname
  • default(缺省):同一包内可见,适合包内组件间协作
  • protected:同一包或不同包子类可见,用于继承体系中的成员共享
  • public:全局可见,用于对外提供的接口方法(如PersongetName()

合理使用权限修饰符可降低类之间的依赖,提高代码安全性和可维护性。

整理在一起,写成word文档形式

Java 核心知识点全解析

一、数据类型与类型转换

(一)数据类型分类

Java 数据类型分为基本数据类型和引用数据类型,二者在存储方式和使用场景上有显著区别。

  1. 基本数据类型 (8 种):直接存储数据值,占用固定内存空间。
    • 整数类型:byte(1 字节)、short(2 字节)、int(4 字节)、long(8 字节),用于存储整数数值,根据数值范围选择对应类型。
    • 浮点类型:float(4 字节)、double(8 字节),用于存储小数,double精度高于float,日常开发中更常用。
    • 字符类型:char(2 字节),用于存储单个字符,如'a''中'
    • 布尔类型:boolean,仅表示true(真)或false(假),JVM 未明确规定其占用内存大小。
  2. 引用数据类型:存储对象的内存地址,而非数据本身,包括类、接口、数组三类。

(二)类型转换规则

类型转换需遵循 "范围匹配" 原则,避免数据精度丢失或运行错误。

  1. 自动转换 :小范围类型向大范围类型转换,无需显式声明,数据不会丢失。
    • 转换顺序:byte→short→int→long→float→double
    • 示例:int a = 10; long b = a;aint类型自动转换为long类型。
  2. 强制转换 :大范围类型向小范围类型转换,需显式添加目标类型括号,可能导致数据精度丢失。
    • 示例:int c = 100; byte d = (byte)c;,若c值超过byte范围(-128~127),转换后数据会异常。

二、运算符

运算符是用于执行数据运算的符号,Java 提供多种运算符以满足不同计算需求。

  1. 算术运算符 :用于基本数学运算,包括+(加)、-(减)、*(乘)、/(除)、%(取余)、++(自增)、--(自减)。
    • 自增 / 自减分为前缀和后缀两种形式:
      • 前缀:++a--a,先执行自增 / 自减,再参与其他运算。
      • 后缀:a++a--,先参与其他运算,再执行自增 / 自减。
    • 示例:int a = 5; int b = a++;b值为 5,a值变为 6);int c = ++a;a值变为 7,c值为 7)。
  2. 赋值运算符 :用于给变量赋值,基础运算符为=,扩展运算符包括+=-=*=/=等,可简化代码并自动处理类型转换。
    • 示例:int a = 3; a += 2;(等价于a = (int)(a + 2)a值变为 5)。
  3. 比较运算符 :用于比较两个值的关系,结果为boolean类型(truefalse),包括>(大于)、<(小于)、>=(大于等于)、<=(小于等于)、==(等于)、!=(不等于)。
    • 示例:int a = 5, b = 3; System.out.println(a > b);(输出true)。
  4. 逻辑运算符 :用于连接布尔表达式,结果为boolean类型,包括&&(短路与)、||(短路或)、!(非)、&(与)、|(或)、^(异或)。
    • "短路" 特性:&&若左侧表达式为false,右侧不再执行;||若左侧表达式为true,右侧不再执行。
    • 示例:int a = 2; System.out.println(a > 3 && ++a > 2);(左侧为falsea值仍为 2)。
  5. 位运算符 :直接对二进制位进行运算,包括&(按位与)、|(按位或)、^(按位异或)、~(按位取反)、<<(左移)、>>(右移),常用于底层开发或高效运算。
    • 示例:int a = 3; int b = a << 1;3二进制为11,左移 1 位后为110b值为 6)。
  6. 三元运算符 :语法为条件表达式 ? 表达式1 : 表达式2,根据条件表达式结果选择执行表达式 1 或表达式 2,可简化简单的分支逻辑。
    • 示例:int max = (a > b) ? a : b;(若a > bmaxa值,否则取b值)。

三、流程控制

流程控制用于控制代码的执行顺序,包括分支结构和循环结构两类。

(一)分支结构

根据条件判断执行不同代码块,主要有if-elseswitch两种形式。

  1. if-else :适合范围性条件判断,可嵌套使用,逻辑清晰。

    • 语法:

      if (条件1) {
      // 条件1为true时执行
      } else if (条件2) {
      // 条件1为false、条件2为true时执行
      } else {
      // 所有条件均为false时执行
      }

    • 示例:

      int score = 85;
      if (score > 90) {
      System.out.println("优秀");
      } else if (score > 60) {
      System.out.println("及格");
      } else {
      System.out.println("不及格");
      }

  2. switch :适合等值条件判断,JDK7 及以上支持String类型,需注意 "穿透" 问题。

    • 语法:

      switch (表达式) {
      case 值1:
      // 表达式等于值1时执行
      break; // 终止switch,避免穿透
      case 值2:
      // 表达式等于值2时执行
      break;
      default:
      // 表达式不等于任何case值时执行
      }

    • 示例:

      String day = "周一";
      switch (day) {
      case "周一":
      System.out.println("工作日第一天");
      break;
      case "周日":
      System.out.println("休息日");
      break;
      default:
      System.out.println("普通日期");
      }

    • 注意:若省略break,会从匹配的case开始,依次执行后续所有代码,直至遇到breakswitch结束,即 "switch 穿透"。

(二)循环结构

用于重复执行某段代码,主要有forwhiledo-while三种形式。

  1. for :适合已知循环次数的场景,语法简洁,控制变量作用域明确。

    • 语法:

      for (初始化语句; 循环条件; 更新语句) {
      // 循环体:条件为true时执行
      }

    • 示例:

      for (int i = 0; i < 5; i++) {
      System.out.println("循环第" + (i + 1) + "次");
      }

  2. while :适合未知循环次数的场景,先判断条件,再执行循环体。

    • 语法:

      while (循环条件) {
      // 循环体:条件为true时执行
      }

    • 示例:

      int count = 0;
      while (count < 3) {
      System.out.println("count: " + count);
      count++;
      }

  3. do-while :与while类似,但先执行一次循环体,再判断条件,确保循环体至少执行一次。

    • 语法:

      do {
      // 循环体
      } while (循环条件);

    • 示例:

      int num = 5;
      do {
      System.out.println("num: " + num);
      num--;
      } while (num > 3);

  4. 循环控制关键字

    • break:立即终止当前所在的循环或switch,跳出代码块。
    • continue:跳过当前循环的剩余代码,直接进入下一次循环判断。

四、类与对象

类与对象是面向对象编程的核心,类是对象的模板,对象是类的实例。

(一)类的结构

类包含属性(成员变量)、方法、构造器、代码块等组件,共同描述对象的特征和行为。

  1. 属性(成员变量) :用于存储对象的状态信息,声明在类中、方法外,有默认初始值(如int默认 0,String默认null)。

    • 示例:public class Person { String name; int age; }nameage即为Person类的属性。
  2. 方法 :用于定义对象的行为,包含方法名、参数列表、返回值类型、方法体。

    • 示例:

      public class Person {
      public void sayHello() {
      System.out.println("Hello!");
      }
      }

  3. 构造器 :与类名相同,无返回值类型,用于创建对象时初始化属性,若未自定义,编译器会生成默认无参构造器。

    • 示例:

      public class Person {
      String name;
      // 自定义构造器
      public Person(String name) {
      this.name = name;
      }
      }

  4. 代码块 :分为静态代码块和实例代码块,用于初始化资源。

    • 静态代码块:用static修饰,类加载时执行,仅执行一次,优先于构造器。

    • 实例代码块:无static修饰,创建对象时执行,每次创建对象都会执行。

    • 示例:

      public class Person {
      // 静态代码块
      static {
      System.out.println("类加载时执行");
      }
      // 实例代码块
      {
      System.out.println("创建对象时执行");
      }
      }

(二)访问权限修饰符

访问权限修饰符用于控制类、属性、方法的访问范围,保障代码安全性和封装性,共 4 种。

修饰符 同一类中 同一包中 同包子类中 不同包中
public ✔️ ✔️ ✔️ ✔️
protected ✔️ ✔️ ✔️
默认(无修饰符) ✔️ ✔️
private ✔️
  • 应用场景:
    • private:修饰属性,仅本类可访问,通过getter/setter对外暴露访问接口。
    • public:修饰对外提供的类、方法,方便外部调用。

(三)封装

封装是面向对象三大特性之一,核心是 "隐藏内部细节,暴露安全接口",通过private修饰属性、提供publicgetter/setter方法实现。

  • 示例(参考Person.java):

    public class Person {
    // private修饰属性,隐藏内部细节
    private String name;
    private int age;

    复制代码
      // getter方法:获取属性值
      public String getName() {
          return name;
      }
      
      // setter方法:设置属性值,可添加验证逻辑
      public void setName(String name) {
          // 验证姓名不为空
          if (name != null && !name.isEmpty()) {
              this.name = name;
          }
      }

    }

  • 优势:保护数据完整性,避免非法赋值;降低代码耦合度,便于后续维护和扩展。

五、继承与多态

继承与多态是面向对象编程的重要特性,实现代码复用和灵活扩展。

(一)继承

继承通过extends关键字实现,子类继承父类的非私有属性和方法,Java 支持单继承(一个子类只能有一个直接父类)。

  1. 继承的核心特性

    • 子类可直接使用父类的非私有成员,减少代码重复。
    • 子类可重写父类方法,实现个性化逻辑。
    • 通过super关键字调用父类的构造器、属性、方法。
  2. 示例

    // 父类
    public class Animal {
    public void eat() {
    System.out.println("动物进食");
    }
    }

    // 子类,继承Animal
    public class Dog extends Animal {
    // 重写父类eat方法
    @Override
    public void eat() {
    System.out.println("狗吃骨头");
    }
    }

(二)抽象类

抽象类用abstract关键字修饰,是包含抽象方法的类,不能实例化,需通过子类继承并实现抽象方法使用。

  1. 抽象类的特性

    • 可包含抽象方法(无方法体,用abstract修饰)和具体方法(有方法体)。
    • 非抽象子类继承抽象类后,必须实现所有抽象方法;若子类也为抽象类,可不用实现。
  2. 示例(参考Test02.java

    // 抽象父类
    abstract class Animal {
    String name;
    // 具体方法
    public void sleep() {
    System.out.println(name + "在睡觉");
    }
    // 抽象方法
    public abstract void eat();
    }

    // 非抽象子类,实现抽象方法
    class Dog extends Animal {
    public Dog(String name) {
    this.name = name;
    }
    @Override
    public void eat() {
    System.out.println(name + "吃骨头");
    }
    }

(三)多态

多态是指同一行为在不同对象上有不同表现形式,核心是 "父类引用指向子类对象"(向上转型),需满足 "继承""方法重写""向上转型" 三个条件。

  1. 多态的实现

    • 向上转型:自动转换,父类引用指向子类对象,可调用父类声明的方法,实际执行子类重写的实现。

    • 示例(参考Test02.java):

      Animal dog = new Dog("旺财"); // 向上转型
      dog.eat(); // 执行Dog类的eat(),输出"旺财吃骨头"
      dog.sleep(); // 执行Animal类的sleep(),输出"旺财在睡觉"

  2. 多态的优势

    • 提高代码灵活性:同一方法调用可根据对象实际类型执行不同逻辑。
    • 便于扩展:新增子类(如Cat)时,无需修改使用父类的代码,符合 "开闭原则"。
  3. instanceof运算符 :用于判断对象的实际类型,避免转型错误,返回值为boolean类型。

    • 示例:

      Animal animal = new Dog("旺财");
      System.out.println(animal instanceof Dog); // true(animal实际是Dog对象)
      System.out.println(animal instanceof Animal); // true(Dog是Animal子类)

六、接口

接口是一种行为规范,用interface关键字定义,用于约束类的行为,不关注具体实现,弥补 Java 单继承的局限性。

(一)接口的结构

接口包含抽象方法、默认方法(JDK8+)、静态方法(JDK8+),所有成员默认用public修饰(可省略)。

  1. 抽象方法:无方法体,实现类必须重写。

  2. 默认方法 :用default修饰,有方法体,实现类可选择重写或直接使用。

  3. 静态方法 :用static修饰,有方法体,属于接口本身,通过接口名直接调用,实现类不能重写。

  4. 示例(参考Flyable.java

    public interface Flyable {
    // 抽象方法
    void fly();
    // 默认方法
    default void land() {
    System.out.println("默认降落");
    }
    // 静态方法
    static void info() {
    System.out.println("这是飞行接口");
    }
    }

(二)接口的实现

类通过implements关键字实现接口,可同时实现多个接口,需重写所有接口的抽象方法。

  1. 示例(参考Bird.javaTest02.java

    // 实现Flyable接口
    class Bird implements Flyable {
    // 重写抽象方法fly()
    @Override
    public void fly() {
    System.out.println("鸟儿飞翔");
    }
    // 重写默认方法land()(可选)
    @Override
    public void land() {
    System.out.println("鸟儿降落");
    }
    }

    // 测试
    public class Test02 {
    public static void main(String[] args) {
    Flyable bird = new Bird();
    bird.fly(); // 输出"鸟儿飞翔"
    bird.land(); // 输出"鸟儿降落"
    Flyable.info(); // 输出"这是飞行接口"(调用静态方法)
    }
    }

  2. 接口的优势

    • 降低耦合度:接口定义规范,实现类可独立变化,如新增Plane类实现Flyable接口,无需修改原有代码。
    • 支持多实现:一个类可实现多个接口,满足多种行为需求,如class Plane implements Flyable, Runnable

七、内部类

内部类是定义在另一个类(外部类)内部的类,根据位置和修饰符分为成员内部类、静态内部类、局部内部类、匿名内部类,此处重点介绍成员内部类(参考Outer.java)。

(一)成员内部类的特性

成员内部类定义在外部类内部、方法外,无static修饰,与外部类实例关联。

  1. 访问权限 :可直接访问外部类的所有成员(包括private修饰的成员),外部类需通过内部类实例访问内部类成员。

  2. 创建方式

    • 外部类内部:直接new 内部类()创建。
    • 外部类外部:需先创建外部类实例,再通过外部类实例.new 内部类()创建。
  3. 示例(参考Outer.java

    public class Outer {
    private int outerVar = 10; // 外部类私有成员

    复制代码
     // 成员内部类
     class Inner {
         int innerVar = 20;
         public void innerMethod() {
             // 访问外部类私有成员
             System.out.println("外部类变量:" + outerVar);
             System.out.println("内部类变量:" + innerVar);
         }
     }
     
     // 外部类方法中使用内部类
     public void outerMethod() {
         Inner inner = new Inner(); // 外部类内部创建内部类实例
         inner.innerMethod();
     }
     
     public static void main(String[] args) {
         // 外部类外部创建内部类实例
         Outer outer = new Outer();
         Outer.Inner inner = outer.new Inner();
         inner.innerMethod(); // 输出"外部类变量:10""内部类变量:20"
     }

    }

(二)成员内部类的应用场景

  • 当内部类仅服务于外部类,且需要频繁访问外部类成员时使用,可隐藏内部实现细节,提高代码封装性,如事件监听器、迭代器等场景。

八、关键字补充

(一)final

final用于修饰类、方法、变量,表示 "不可变"。

  1. 修饰类 :类不能被继承,如final class String,确保类的稳定性。
  2. 修饰方法 :方法不能被重写,如父类中final修饰的方法,子类无法修改其逻辑。
  3. 修饰变量
    • 基本数据类型变量:初始化后值不可改变。

    • 引用数据类型变量:初始化后内存地址不可改变,但对象内容可修改。

    • 示例:

      final int a = 5;
      // a = 6; // 报错:基本类型变量值不可变

      final int[] arr = {1, 2, 3};
      arr[0] = 100; // 允许:修改数组内容
      // arr = new int[5]; // 报错:引用地址不可变

(二)static

static用于修饰属性、方法、代码块,属于类本身,而非对象实例。

  1. 静态属性 :所有对象共享同一数据,通过类名.属性名访问,如Student.school(参考Test01.java)。

    • 示例:

      class Student {
      static String school; // 静态属性
      }
      Student.school = "河金";
      System.out.println(Student.school); // 输出"河金"

  2. 静态方法 :属于类,通过类名.方法名访问,不能访问非静态成员(非静态成员依赖对象实例),如Student.eat()(参考Test01.java)。

    • 示例:

      class Student {
      public static void eat() {
      System.out.println("吃饭");
      }
      }
      Student.eat(); // 直接通过类名调用

  3. 注意 :静态成员加载时机早于非静态成员,在静态方法中不能使用thissuper关键字。

(三)this

this代表当前对象的引用,用于区分成员变量和局部变量、调用当前类的构造器、调用当前类的方法。

  • 示例:

    public class Person {
    private String name;
    public Person(String name) {
    this.name = name; // 区分成员变量和局部变量
    }
    }

九、数组

数组是存储相同类型数据的容器,属于引用数据类型,长度固定(初始化后不可改变)。

(一)数组的声明与初始化

  1. 声明方式 :两种语法等价,推荐第一种,更符合 Java 风格。
    • 数据类型[] 数组名,如int[] arr
    • 数据类型 数组名[],如int arr[]
  2. 初始化方式
    • 静态初始化:指定数组元素,长度由元素个数决定,如int[] arr = {1, 2, 3};
    • 动态初始化:指定数组长度,元素为默认值,如int[] arr = new int[3];(元素默认值为 0)。

(二)数组的访问与遍历

  1. 访问 :通过 "数组名 [索引]" 访问元素,索引从 0 开始,最大索引为 "数组长度 - 1",若索引越界会抛出ArrayIndexOutOfBoundsException
    • 示例:int[] arr = {1, 2, 3}; System.out.println(arr[0]);(输出 1)。
  2. 遍历 :通过for循环或增强for循环(for-each)遍历数组元素。
    • 示例:

      int[] arr = {1, 2, 3};
      // 普通for循环
      for (int i = 0; i < arr.length; i++) {
      System.out.println(arr[i]);
      }
      // 增强for循环
      for (int num : arr) {
      System.out.println(num);
      }

十、字符串比较

字符串比较是常见操作,需区分==equals()的差异,避免逻辑错误。

(一)==的作用

  • 基本数据类型:比较值是否相等,如int a = 10, b = 10; System.out.println(a == b);(输出true)。
  • 引用数据类型:比较对象的内存地址是否相同,即是否指向同一个对象,如String s1 = new String("abc"), s2 = new String("abc"); System.out.println(s1 == s2);(输出false,因s1s2是两个不同对象)。

(二)equals()的作用

equals()Object类的方法,默认实现与==一致(比较内存地址),但许多类(如StringInteger)重写了该方法,用于比较对象内容是否相等。

  1. String类的equals() :比较字符串的字符序列是否相同,与内存地址无关。

    • 示例:

      String s1 = new String("abc");
      String s2 = new String("abc");
      System.out.println(s1.equals(s2)); // 输出true(内容相同)

  2. 自定义类重写equals() :若需比较自定义对象的内容,需手动重写equals()方法,通常需同时重写hashCode()方法(保证 "equals 相等的对象,hashCode 一定相等")。

    • 示例:

      public class Person {
      private String name;
      @Override
      public boolean equals(Object o) {
      if (this == o) return true;
      if (o == null || getClass() != o.getClass()) return false;
      Person person = (Person) o;
      return Objects.equals(name, person.name);
      }
      @Override
      public int hashCode() {
      return Objects.hash(name);
      }
      }

相关推荐
空空kkk3 小时前
Java——类和对象
java·开发语言
JIngJaneIL3 小时前
篮球论坛|基于SprinBoot+vue的篮球论坛系统(源码+数据库+文档)
java·前端·数据库·vue.js·论文·毕设·篮球论坛系统
毕设源码-赖学姐4 小时前
【开题答辩全过程】以 安卓的服装销售APP为例,包含答辩的问题和答案
java·eclipse·tomcat
闲人编程4 小时前
自动化文件管理:分类、重命名和备份
python·microsoft·分类·自动化·备份·重命名·自动化文件分类
沐知全栈开发4 小时前
Python3 集合
开发语言
青云交5 小时前
Java 大视界 -- Java 大数据在智能农业温室环境调控与作物生长模型构建中的应用
java·机器学习·传感器技术·数据处理·作物生长模型·智能农业·温室环境调控
曾经的三心草5 小时前
SpringAI5-智能聊天机器⼈
java·springai
微露清风5 小时前
系统性学习C++-第八讲-vector类
java·c++·学习
Jonathan Star5 小时前
用Python轻松提取视频音频并去除静音片段
开发语言·python·音视频