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);
      }
      }

相关推荐
猷咪18 小时前
C++基础
开发语言·c++
IT·小灰灰18 小时前
30行PHP,利用硅基流动API,网页客服瞬间上线
开发语言·人工智能·aigc·php
快点好好学习吧18 小时前
phpize 依赖 php-config 获取 PHP 信息的庖丁解牛
android·开发语言·php
秦老师Q18 小时前
php入门教程(超详细,一篇就够了!!!)
开发语言·mysql·php·db
烟锁池塘柳018 小时前
解决Google Scholar “We‘re sorry... but your computer or network may be sending automated queries.”的问题
开发语言
是誰萆微了承諾18 小时前
php 对接deepseek
android·开发语言·php
vx_BS8133018 小时前
【直接可用源码免费送】计算机毕业设计精选项目03574基于Python的网上商城管理系统设计与实现:Java/PHP/Python/C#小程序、单片机、成品+文档源码支持定制
java·python·课程设计
2601_9498683618 小时前
Flutter for OpenHarmony 电子合同签署App实战 - 已签合同实现
java·开发语言·flutter
gzxx2007sddx18 小时前
windows vnpy运行过程及问题记录
python·量化·vnpy
星火开发设计18 小时前
类型别名 typedef:让复杂类型更简洁
开发语言·c++·学习·算法·函数·知识