本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Java是一种广泛使用的面向对象编程语言,具有跨平台、高性能和丰富类库等优势。本”Java基础教程PPT”专为初学者和有编程经验者设计,系统讲解Java核心知识体系,内容涵盖基础语法、面向对象编程、容器、多线程、数据库连接、网络编程、RMI远程调用和JSP动态网页技术。通过本教程学习,可帮助开发者系统掌握Java编程基础,为后续学习框架开发和企业级项目打下坚实基础。PPT内容经过教学验证,适合自学和课堂教学使用。

1. Java语言概述与开发环境搭建

Java是一种面向对象的高级编程语言,由Sun Microsystems于1995年正式发布。其“一次编写,到处运行”的特性得益于Java虚拟机(JVM)机制,使Java在企业级应用、安卓开发、大数据处理等领域占据重要地位。

Java平台的三大版本

Java平台主要分为三个版本,适用于不同应用场景:

版本 全称 用途
Java SE Java Standard Edition 标准版,提供核心API和JVM,适合基础学习和桌面应用开发
Java EE Java Enterprise Edition 企业版,构建在SE之上,支持Web和企业级应用开发
Java ME Java Micro Edition 微型版,适用于嵌入式系统和移动设备

JDK与JRE的区别

  • JRE(Java Runtime Environment) :提供运行Java程序所需的环境,包含JVM和基础类库。
  • JDK(Java Development Kit) :包含JRE,并提供编译、调试、文档生成等开发工具,是开发者必备的工具包。

JVM的作用与工作机制

Java虚拟机(JVM)是Java程序的运行引擎,其核心作用是加载 .class 字节码文件并执行。JVM通过类加载器(ClassLoader)将类文件加载进内存,随后通过解释器或即时编译器(JIT)执行字节码,实现跨平台运行。

开发环境搭建流程详解

1. 安装JDK

前往 Oracle官网 或使用OpenJDK发行版(如 Adoptium)下载对应操作系统的JDK安装包并安装。

2. 配置环境变量

以Windows系统为例:

  • JAVA_HOME :设置为JDK安装路径,例如 C:\Program Files\Java\jdk-17
  • PATH :添加 %JAVA_HOME%\bin ,确保命令行可识别 javac java 命令

验证安装:

javac -version  # 查看编译器版本
java -version   # 查看运行环境版本

3. 安装IDE(以IntelliJ IDEA为例)

下载安装 IntelliJ IDEA Community Edition ,启动后配置JDK路径即可开始开发。

4. 编写第一个Java程序

创建文件 HelloWorld.java

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, Java World!");  // 输出语句
    }
}

编译并运行:

javac HelloWorld.java  # 编译
java HelloWorld        # 执行

输出结果:

Hello, Java World!

本章为后续学习打下基础,下一章将深入讲解Java基础语法结构。

2. Java基础语法详解

2.1 Java程序的基本结构

2.1.1 类与主类的定义

Java是一种面向对象的语言,所有代码必须定义在类中。类是Java程序的基本组成单元,使用 class 关键字声明。例如:

public class HelloWorld {
    // 类体
}

在这个例子中, HelloWorld 是类名, public 是访问修饰符,表示该类可以被外部访问。Java规定,每个 .java 文件最多只能有一个 public 类,并且该类的名称必须与文件名一致。

主类是指程序的入口类,其中必须包含 main 方法。 main 方法是 Java 应用程序的起点,其标准定义如下:

public static void main(String[] args) {
    // 程序入口代码
}
  • public :表示该方法可以被虚拟机调用。
  • static :使方法可以在不创建对象的情况下被调用。
  • void :表示方法没有返回值。
  • String[] args :是命令行参数,可以通过命令行传递参数给程序。
示例:完整的 Java 程序结构
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello, World!");
    }
}

该程序定义了一个类 HelloWorld ,并在其中定义了 main 方法,使用 System.out.println 输出字符串。

2.1.2 方法的声明与调用

方法是类中执行特定任务的代码块。Java 中的方法声明格式如下:

修饰符 返回类型 方法名(参数列表) {
    // 方法体
}
方法声明示例
public int add(int a, int b) {
    return a + b;
}
  • public :访问权限修饰符。
  • int :返回值类型。
  • add :方法名。
  • (int a, int b) :参数列表。
方法调用

要在其他方法中调用该方法,需要先创建类的实例(对象),或者方法本身是静态的( static )。

public class MethodExample {
    public static void main(String[] args) {
        MethodExample example = new MethodExample();
        int result = example.add(5, 3);
        System.out.println("Result: " + result);
    }

    public int add(int a, int b) {
        return a + b;
    }
}

上述代码中:

  1. 创建了 MethodExample 的对象 example
  2. 调用 add 方法并传入参数 5 3
  3. 输出结果为 8

2.1.3 注释与命名规范

注释类型

Java 支持三种注释方式:

  1. 单行注释 :使用 //
    java // 这是一个单行注释

  2. 多行注释 :使用 /* ... */
    ```java
    /*

    • 这是一个
    • 多行注释
      */
      ```
  3. 文档注释 :使用 /** ... */ ,用于生成 API 文档
    ```java
    /**

    • 这是一个文档注释
    • @param a 第一个整数
    • @param b 第二个整数
    • @return 两个整数的和
      */
      ```
命名规范

Java 的命名遵循一定的约定,以提高代码的可读性:

元素 命名规范 示例
类名 首字母大写,驼峰命名 StudentInfo
方法名 首字母小写,驼峰命名 calculateTotal()
变量名 首字母小写,驼峰命名 studentName
常量名 全大写,下划线分隔 MAX_VALUE
包名 小写字母,点分隔 com.example.project

2.2 标识符与关键字

2.2.1 合法标识符的命名规则

标识符是变量、方法、类等命名的名称。Java 对标识符的命名有以下规则:

  1. 只能使用字母、数字、下划线(_)和美元符号($)
  2. 不能以数字开头
  3. 不能使用 Java 关键字
  4. 区分大小写
合法标识符示例
int age;
double salary;
String _name;
boolean $valid;
非法标识符示例
int 1age;        // 以数字开头非法
int class;       // 使用关键字非法

2.2.2 关键字列表与使用限制

Java 有 53 个关键字,其中 48 个由 java.lang 包定义,5 个保留关键字( goto , const , true , false , null )但未被使用。

Java 常见关键字列表
类型 关键字示例
数据类型 int , double , boolean , char
控制结构 if , else , for , while
类与对象 class , extends , implements
修饰符 public , private , static
异常处理 try , catch , finally
特殊用途 this , super , import , package
示例:关键字使用场景
public class KeywordExample {
    private int count;  // 使用 private 修饰符

    public void increment() {
        count++;  // 修改类成员变量
    }

    public static void main(String[] args) {
        try {
            int result = 10 / 0;  // 会抛出异常
        } catch (ArithmeticException e) {
            System.out.println("除法异常");
        }
    }
}

2.3 语句与代码块

2.3.1 单条语句与复合语句

Java 中的语句是以分号 ; 结尾的执行单元。例如:

int a = 10;  // 单条语句
System.out.println(a);

复合语句是一组用花括号 {} 包裹的多个语句,常用于条件判断或循环中。

示例:if 条件复合语句
if (a > 0) {
    System.out.println("a 是正数");
    a = a + 1;
}

2.3.2 代码块的作用域与执行流程

代码块由 {} 包裹,具有自己的作用域。变量在代码块内部声明后,只能在该块内访问。

示例:代码块作用域
public class ScopeExample {
    public static void main(String[] args) {
        int x = 10;

        if (x > 5) {
            int y = 20;  // y 的作用域仅限于 if 块内
            System.out.println("y = " + y);
        }

        // System.out.println(y); // 编译错误:y 未定义
    }
}
流程图:代码块执行流程
graph TD
    A[开始] --> B{条件判断}
    B -->|条件成立| C[执行代码块]
    B -->|条件不成立| D[跳过代码块]
    C --> E[继续执行后续代码]
    D --> E

2.4 基本输入输出操作

2.4.1 使用 Scanner 类实现控制台输入

Java 中的 Scanner 类用于从控制台读取输入数据。使用前需要导入 java.util.Scanner 包。

示例:读取整数输入
import java.util.Scanner;

public class InputExample {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入一个整数:");
        int number = scanner.nextInt();
        System.out.println("你输入的整数是:" + number);
        scanner.close();
    }
}
  • Scanner scanner = new Scanner(System.in); :创建 Scanner 对象,监听标准输入。
  • nextInt() :读取整数。
  • close() :关闭扫描器,释放资源。
示例:读取字符串输入
String name = scanner.nextLine();  // 读取一行字符串

2.4.2 使用 System 类实现输出

Java 中使用 System.out 实现输出,常见方法如下:

方法名 功能描述
System.out.print() 输出内容,不换行
System.out.println() 输出内容并换行
System.out.printf() 格式化输出
示例:格式化输出
int age = 25;
double salary = 5000.50;

System.out.printf("年龄:%d,工资:%.2f%n", age, salary);
  • %d :表示整数。
  • %.2f :表示保留两位小数的浮点数。
  • %n :换行符。
输出结果:
年龄:25,工资:5000.50

(未完待续)

3. 数据类型与变量定义

在Java编程语言中, 数据类型与变量定义 是构建程序逻辑的基石。无论是简单的数值运算,还是复杂的对象模型,都离不开对数据类型的准确理解与变量的合理使用。Java是一种静态类型语言,这意味着在程序运行前必须明确变量的数据类型,从而确保类型安全与内存管理的高效性。

本章将从 基本数据类型 入手,逐步深入到 变量与常量的定义 类型转换机制 ,并最终过渡到 引用数据类型的初步认识 。每一部分都将以递进的方式展开,结合代码示例、参数说明和逻辑分析,帮助读者建立起对Java数据类型体系的全面认知。

3.1 基本数据类型

Java语言内置了 八种基本数据类型 ,它们是程序中最基础的数据单元,用于存储简单的数值信息。这些类型被划分为四类:整型、浮点型、字符型和布尔型。

3.1.1 整型、浮点型、字符型与布尔型

类型 大小(字节) 取值范围/描述
byte 1 -128 到 127
short 2 -32,768 到 32,767
int 4 -2^31 到 2^31 - 1
long 8 -2^63 到 2^63 - 1(后缀 L 表示 long)
float 4 单精度浮点数(后缀 F 表示 float)
double 8 双精度浮点数
char 2 Unicode字符(0 到 65535)
boolean 1 只能是 true false

这些基本类型是Java语言的核心组成部分,它们不是对象,而是直接操作的原始数据类型。

示例代码:基本数据类型声明与赋值
public class PrimitiveTypesExample {
    public static void main(String[] args) {
        byte b = 100;         // byte 类型
        short s = 30000;      // short 类型
        int i = 100000;       // int 类型
        long l = 1000000000L; // long 类型,注意后缀 L

        float f = 3.14f;      // float 类型,注意后缀 f
        double d = 3.1415926535; // double 类型

        char c = 'A';         // char 类型
        boolean bool = true;  // boolean 类型

        // 输出变量值
        System.out.println("byte: " + b);
        System.out.println("short: " + s);
        System.out.println("int: " + i);
        System.out.println("long: " + l);
        System.out.println("float: " + f);
        System.out.println("double: " + d);
        System.out.println("char: " + c);
        System.out.println("boolean: " + bool);
    }
}
代码逻辑分析
  • 第1~4行:声明并初始化 byte short int long 类型变量,其中 long 类型需要添加后缀 L ,否则默认为 int
  • 第6~7行: float 必须添加后缀 f ,否则会被识别为 double
  • 第9~10行: char 用于存储 Unicode 字符,而 boolean 仅能取 true false
  • 第13~20行:使用 System.out.println() 打印变量内容,验证变量的值。

3.1.2 数据类型的大小与取值范围

Java的基本数据类型具有 固定的大小 ,不随平台变化,这保证了程序在不同系统中的一致性。例如, int 在所有平台上都是 4 字节(32位),而 double 永远是 8 字节。

数据类型大小与取值范围对照表
类型 字节大小 位数 最小值 最大值
byte 1 8 -128 127
short 2 16 -32,768 32,767
int 4 32 -2,147,483,648 2,147,483,647
long 8 64 -9,223,372,036,854,775,808 9,223,372,036,854,775,807
float 4 32 ±1.4E-45(正负) ±3.4028235E38
double 8 64 ±4.9E-324 ±1.7976931348623157E308
char 2 16 ‘\u0000’(0) ‘\uffff’(65535)
boolean 1 N/A false true
示例:整数溢出演示
public class IntegerOverflow {
    public static void main(String[] args) {
        byte maxByte = Byte.MAX_VALUE;
        System.out.println("Byte 最大值: " + maxByte);

        // 溢出操作
        byte overflow = (byte)(maxByte + 1);
        System.out.println("溢出后: " + overflow);
    }
}
代码逻辑分析
  • Byte.MAX_VALUE byte 类型的最大值 127
  • maxByte + 1 会变成 128 ,但由于 byte 的最大值为 127 ,所以发生 溢出 ,结果为 -128
  • Java不会自动抛出异常,因此在使用基本类型时需注意边界问题。

3.2 变量与常量

变量是程序中最基本的存储单元,而常量则是值不可变的变量。理解变量的定义、作用域以及常量的使用,是掌握Java编程的重要一步。

3.2.1 变量的声明与初始化

Java中变量的声明格式为:

数据类型 变量名 = 初始值;
示例:变量的声明与使用
public class VariableExample {
    public static void main(String[] args) {
        int age = 25;           // 声明并初始化变量
        double salary = 5000.50;
        char grade = 'A';
        boolean isEmployed = true;

        System.out.println("年龄: " + age);
        System.out.println("工资: " + salary);
        System.out.println("等级: " + grade);
        System.out.println("是否在职: " + isEmployed);
    }
}
代码逻辑分析
  • 每个变量都必须指定类型,变量名必须符合Java的命名规则(字母、数字、下划线等)。
  • 初始化值必须与变量类型兼容,否则编译器会报错。
  • 使用 System.out.println() 输出变量值,观察变量在内存中的状态。

3.2.2 final关键字定义常量

在Java中,使用 final 关键字可以将变量定义为 常量 ,其值在初始化后不能更改。

示例:定义常量
public class ConstantExample {
    public static void main(String[] args) {
        final double PI = 3.14159;
        final String COMPANY_NAME = "ABC Corp";

        System.out.println("圆周率: " + PI);
        System.out.println("公司名称: " + COMPANY_NAME);

        // 下面这行代码会报错,因为PI是常量
        // PI = 3.14;
    }
}
代码逻辑分析
  • final 修饰的变量一旦赋值,就不能再修改,否则编译错误。
  • 常量命名通常采用 全大写 ,多个单词用下划线分隔,如 MAX_VALUE

3.3 类型转换与自动提升

在Java中,当不同数据类型的变量进行运算时,系统会进行 类型转换 ,以确保运算的正确性和安全性。类型转换分为 自动类型转换 强制类型转换 两种方式。

3.3.1 强制类型转换

强制类型转换用于将一个较大的类型转换为较小的类型,可能会导致数据丢失。

示例:强制类型转换
public class TypeCastingExample {
    public static void main(String[] args) {
        double d = 123.765;
        int i = (int) d;  // 强制转换 double -> int
        System.out.println("转换后的整数: " + i); // 输出 123

        byte b = (byte) 130; // 超出 byte 范围
        System.out.println("byte 类型转换后: " + b); // 输出 -126
    }
}
代码逻辑分析
  • double 转换为 int 时,小数部分被截断。
  • 130 超出 byte 范围(-128~127),结果发生溢出,变为 -126

3.3.2 自动类型提升规则

Java在进行运算时,会自动将较小的数据类型提升为较大的类型,以避免数据丢失。

示例:自动类型提升
public class AutoPromotionExample {
    public static void main(String[] args) {
        byte b1 = 10, b2 = 20;
        int result = b1 + b2; // byte 自动提升为 int
        System.out.println("结果: " + result);
    }
}
代码逻辑分析
  • byte 类型在加法运算中被自动提升为 int ,因此 result 的类型必须是 int
  • 如果尝试将结果赋值给 byte ,必须进行强制转换。

3.4 引用数据类型简介

除了基本数据类型外,Java还支持 引用数据类型 ,它们指向对象的内存地址,而不是直接存储数据。最常用的引用类型包括字符串 String 和数组。

3.4.1 字符串类型String的使用

String 是Java中最常用的引用类型之一,用于表示文本信息。

示例:字符串的声明与操作
public class StringExample {
    public static void main(String[] args) {
        String name = "Alice";
        String greeting = "Hello, " + name;

        System.out.println(greeting);
        System.out.println("字符串长度: " + name.length());
        System.out.println("是否包含 'A': " + name.contains("A"));
    }
}
代码逻辑分析
  • String 是不可变对象,每次拼接都会创建新对象。
  • length() 返回字符串长度, contains() 检查是否包含子串。

3.4.2 数组的声明与访问

数组是用于存储多个相同类型数据的结构。

示例:数组的声明与遍历
public class ArrayExample {
    public static void main(String[] args) {
        int[] numbers = {1, 2, 3, 4, 5};

        // 使用 for 循环遍历数组
        for (int i = 0; i < numbers.length; i++) {
            System.out.println("索引 " + i + " 的值为: " + numbers[i]);
        }

        // 使用增强型 for 循环
        for (int num : numbers) {
            System.out.println("值: " + num);
        }
    }
}
代码逻辑分析
  • int[] numbers 声明一个整型数组。
  • numbers.length 获取数组长度。
  • 增强型 for 循环适用于只读操作,简化代码结构。

本章总结

本章围绕 Java的基本数据类型 展开,深入讲解了整型、浮点型、字符型和布尔型的使用方法与取值范围,并通过代码示例演示了变量的声明、常量的定义、类型转换机制以及引用类型如字符串和数组的基本操作。

通过本章内容,读者可以建立起对Java数据类型体系的完整认知,为后续面向对象编程和复杂数据处理打下坚实基础。

4. 运算符与表达式使用

在 Java 编程语言中,运算符与表达式是构建程序逻辑的核心工具之一。它们不仅用于执行基本的数学运算,还广泛应用于条件判断、位操作、赋值操作等关键逻辑中。理解运算符的优先级、结合性以及在不同上下文中的行为,是编写高效、可维护代码的基础。本章将深入探讨 Java 中各类运算符的使用方式,并通过代码示例展示其在实际开发中的应用。

4.1 算术运算符

Java 提供了丰富的算术运算符,用于执行加、减、乘、除、取余等基本数学运算。它们是构建数值表达式的基础。

4.1.1 加减乘除与取余运算

以下是最常见的五种算术运算符:

运算符 描述 示例
+ 加法 5 + 3 8
- 减法 10 - 4 6
* 乘法 3 * 4 12
/ 除法 10 / 3 3 (整数除法)
% 取余(模运算) 10 % 3 1
示例代码:
public class ArithmeticDemo {
    public static void main(String[] args) {
        int a = 10, b = 3;

        System.out.println("加法: " + (a + b));       // 输出 13
        System.out.println("减法: " + (a - b));       // 输出 7
        System.out.println("乘法: " + (a * b));       // 输出 30
        System.out.println("除法: " + (a / b));       // 输出 3(整数除法)
        System.out.println("取余: " + (a % b));       // 输出 1
    }
}
逻辑分析与参数说明:
  • a + b :执行加法运算,结果为 13。
  • a - b :执行减法运算,结果为 7。
  • a * b :执行乘法运算,结果为 30。
  • a / b :由于 a b 都是整型,Java 默认执行整数除法,结果为 3,而不是 3.333。
  • a % b :返回 a 除以 b 的余数,即 1。

⚠️ 注意 :如果希望得到浮点数结果,可以将其中一个操作数转换为 double float ,例如 (double)a / b

4.1.2 自增与自减运算符

自增( ++ )和自减( -- )运算符是 Java 中非常常用的简化操作符,用于将变量的值增加或减少 1。

使用方式:
  • 前缀形式 ++a ,先自增后使用。
  • 后缀形式 a++ ,先使用后自增。
示例代码:
public class IncrementDecrementDemo {
    public static void main(String[] args) {
        int a = 5;

        System.out.println("后缀自增: " + a++); // 输出 5,之后 a 变为 6
        System.out.println("当前值: " + a);     // 输出 6

        System.out.println("前缀自增: " + ++a); // 输出 7
        System.out.println("当前值: " + a);     // 输出 7
    }
}
逻辑分析与参数说明:
  • a++ :先输出 a 的值(5),然后 a 自增为 6。
  • ++a :先将 a 增加到 7,再输出结果。

建议 :在复杂表达式中慎用自增/自减,以避免可读性问题。

4.2 比较与逻辑运算符

比较与逻辑运算符用于构建布尔表达式,是控制程序流程(如 if、while、for)的关键。

4.2.1 条件判断中的布尔表达式

Java 中的布尔表达式通常用于判断两个值之间的关系,其结果为 true false

运算符 描述 示例
== 等于 5 == 5 true
!= 不等于 5 != 3 true
> 大于 6 > 3 true
< 小于 2 < 4 true
>= 大于等于 5 >= 5 true
<= 小于等于 3 <= 4 true
示例代码:
public class ComparisonDemo {
    public static void main(String[] args) {
        int x = 10, y = 5;

        System.out.println("x == y: " + (x == y)); // false
        System.out.println("x > y: " + (x > y));   // true
        System.out.println("x <= y: " + (x <= y)); // false
    }
}
逻辑分析与参数说明:
  • x == y :比较 x y 是否相等,结果为 false
  • x > y :判断 x 是否大于 y ,结果为 true
  • x <= y :判断 x 是否小于等于 y ,结果为 false

⚠️ 注意 :对于对象比较,应使用 .equals() 方法而非 ==

4.2.2 逻辑与、或、非的使用场景

逻辑运算符用于组合多个布尔表达式,形成更复杂的条件判断。

运算符 描述 示例
&& 逻辑与 true && false false
\|\| 逻辑或 true || false true
! 逻辑非 !true false
示例代码:
public class LogicalDemo {
    public static void main(String[] args) {
        boolean isRaining = true, hasUmbrella = false;

        if (isRaining && !hasUmbrella) {
            System.out.println("应该带伞出门");
        }

        if (isRaining || hasUmbrella) {
            System.out.println("天气状况需要关注");
        }
    }
}
逻辑分析与参数说明:
  • isRaining && !hasUmbrella :当“下雨且没有带伞”时输出提示。
  • isRaining || hasUmbrella :只要“下雨或有伞”就输出提示。

短路特性 && 在第一个操作数为 false 时不会计算第二个; \|\| 在第一个为 true 时也不会计算第二个,这在性能优化和防止异常时非常有用。

4.3 位运算符

Java 提供了位运算符,可以直接操作整数的二进制位。这类运算符在系统编程、加密算法、性能优化等场景中具有重要价值。

4.3.1 位与、位或、异或与移位操作

运算符 描述 示例
& 位与 5 & 3 1 (二进制)
\| 位或 5 \| 3 7
^ 异或 5 ^ 3 6
~ 取反 ~5 -6 (补码)
<< 左移 5 << 1 10
>> 右移(带符号) 5 >> 1 2
>>> 右移(无符号) -5 >>> 1 2147483645
示例代码:
public class BitwiseDemo {
    public static void main(String[] args) {
        int a = 5;  // 二进制:0101
        int b = 3;  // 二进制:0011

        System.out.println("位与: " + (a & b));      // 0001 → 1
        System.out.println("位或: " + (a | b));      // 0111 → 7
        System.out.println("异或: " + (a ^ b));      // 0110 → 6
        System.out.println("左移: " + (a << 1));     // 1010 → 10
        System.out.println("右移: " + (a >> 1));     // 0010 → 2
    }
}
逻辑分析与参数说明:
  • a & b :按位与,仅当两位都为 1 时才为 1。
  • a | b :按位或,任一位为 1 即为 1。
  • a ^ b :异或,相同位不同值时为 1。
  • a << 1 :左移一位,相当于乘以 2。
  • a >> 1 :右移一位,相当于除以 2。

应用场景 :位运算在集合操作、状态位管理、图像处理中非常高效。

4.3.2 位运算的实际应用场景

应用场景一:状态位管理(标志位)

在系统开发中,常常使用一个整型变量的每一位表示不同的状态。

int flags = 0; // 初始状态全为 0

// 设置第 0 位为 1(表示打开某个功能)
flags |= 1 << 0;

// 设置第 2 位为 1
flags |= 1 << 2;

// 检查第 0 位是否开启
boolean isFeature0Enabled = (flags & (1 << 0)) != 0;
应用场景二:快速乘除法

左移和右移运算比乘除法快得多,适合性能敏感的代码段。

int x = 10;
x = x << 2; // 相当于 x * 4 → 40
x = x >> 1; // 相当于 x / 2 → 20

4.4 赋值与三目运算符

赋值与三目运算符是 Java 中用于简洁表达逻辑的重要工具。

4.4.1 简单赋值与复合赋值

运算符 描述 示例
= 赋值 a = 5
+= 加法赋值 a += 3 a = a + 3
-= 减法赋值 a -= 2 a = a - 2
*= 乘法赋值 a *= 4 a = a * 4
/= 除法赋值 a /= 2 a = a / 2
%= 取余赋值 a %= 3 a = a % 3
示例代码:
public class AssignmentDemo {
    public static void main(String[] args) {
        int a = 10;

        a += 5; // 等价于 a = a + 5
        System.out.println("a += 5 后: " + a); // 输出 15

        a *= 2; // 等价于 a = a * 2
        System.out.println("a *= 2 后: " + a); // 输出 30
    }
}
逻辑分析与参数说明:
  • a += 5 :将 a 增加 5,结果为 15。
  • a *= 2 :将 a 乘以 2,结果为 30。

优点 :复合赋值使代码更简洁,且编译器会进行优化。

4.4.2 三目运算符的语法与应用

三目运算符( ? : )是 Java 中唯一的三元运算符,常用于简化 if-else 逻辑。

语法格式:
result = condition ? valueIfTrue : valueIfFalse;
示例代码:
public class TernaryDemo {
    public static void main(String[] args) {
        int score = 85;
        String grade = score >= 60 ? "及格" : "不及格";
        System.out.println("成绩等级: " + grade);
    }
}
逻辑分析与参数说明:
  • score >= 60 :判断是否及格。
  • 如果为真,返回 "及格" ;否则返回 "不及格"

应用场景 :适合用于赋值逻辑简洁的条件判断,如 UI 状态切换、配置选择等。

4.5 总结与流程图

为了帮助理解 Java 中运算符的分类与执行顺序,以下是本章内容的流程图总结:

graph TD
    A[Java运算符] --> B[算术运算符]
    A --> C[比较与逻辑运算符]
    A --> D[位运算符]
    A --> E[赋值与三目运算符]

    B --> B1[加减乘除]
    B --> B2[自增自减]

    C --> C1[比较运算符]
    C --> C2[逻辑运算符]

    D --> D1[位与、位或、异或]
    D --> D2[左移、右移]

    E --> E1[简单赋值]
    E --> E2[复合赋值]
    E --> E3[三目运算符]

本章详细讲解了 Java 中的各类运算符及其使用方式,并通过代码示例展示了它们在实际开发中的具体应用场景。理解这些运算符的优先级、结合性以及在不同数据类型中的行为,是掌握 Java 编程语言的关键一步。

5. 控制结构(if语句、循环结构)

5.1 条件控制语句

5.1.1 if-else结构的使用

Java中的 if-else 语句是最基本的条件判断结构,用于根据布尔表达式的结果来执行不同的代码块。其基本语法如下:

if (条件表达式) {
    // 条件为true时执行的代码
} else {
    // 条件为false时执行的代码(可选)
}

代码解析:
- 条件表达式 必须是一个返回布尔值的表达式。
- 如果 条件表达式 true ,则执行 if 块中的代码。
- 如果 条件表达式 false ,并且存在 else 块,则执行 else 块中的代码。

多条件判断:if-else if-else 结构

当需要判断多个条件时,可以使用 else if 进行条件分支扩展:

int score = 85;

if (score >= 90) {
    System.out.println("A");
} else if (score >= 80) {
    System.out.println("B");
} else if (score >= 70) {
    System.out.println("C");
} else {
    System.out.println("D");
}

代码逻辑逐行分析:
- 第1行:定义一个整型变量 score 并赋值为85。
- 第3行:判断 score 是否大于等于90,如果为真,输出”A”。
- 第5行:若前一个条件不成立,判断是否大于等于80,输出”B”。
- 第7行:继续判断是否大于等于70,输出”C”。
- 第9行:若以上条件都不满足,则输出”D”。

嵌套if语句

当条件判断本身又包含多个子条件时,可以使用嵌套的 if 语句:

int age = 25;
boolean isStudent = true;

if (age >= 18) {
    if (isStudent) {
        System.out.println("成年学生");
    } else {
        System.out.println("成年非学生");
    }
} else {
    System.out.println("未成年");
}

执行流程:
- 若 age >= 18 为真,进入内部判断 isStudent 是否为真。
- 内部判断决定输出“成年学生”或“成年非学生”。
- 若 age < 18 ,则直接输出“未成年”。

5.1.2 switch-case结构的语法与注意事项

switch-case 结构适用于多个固定值的判断,尤其适合枚举或整数型条件判断。其基本语法如下:

switch (表达式) {
    case 值1:
        // 执行语句1
        break;
    case 值2:
        // 执行语句2
        break;
    ...
    default:
        // 默认执行语句(可选)
}

参数说明:
- 表达式 必须是 byte short int char String 或枚举类型(Java 7及以上支持 String )。
- 每个 case 后跟一个常量值,与 表达式 比较。
- break 用于跳出当前 case ,防止“穿透”(fall-through)到下一个 case
- default 是可选的,用于处理没有匹配的默认情况。

示例代码:使用switch-case判断星期几
int day = 3;
String dayName;

switch (day) {
    case 1:
        dayName = "星期一";
        break;
    case 2:
        dayName = "星期二";
        break;
    case 3:
        dayName = "星期三";
        break;
    case 4:
        dayName = "星期四";
        break;
    case 5:
        dayName = "星期五";
        break;
    case 6:
        dayName = "星期六";
        break;
    case 7:
        dayName = "星期日";
        break;
    default:
        dayName = "无效的天数";
}

System.out.println(dayName);

执行流程分析:
- day 被赋值为3,进入 switch 结构。
- 匹配到 case 3 ,将 dayName 设为“星期三”。
- 执行 break 跳出 switch ,最终输出“星期三”。

注意事项:
项目 说明
数据类型限制 仅支持 byte short int char String 和枚举类型
必须使用 break 否则会继续执行下一个 case ,导致逻辑错误
default 可选 可以省略,但建议添加以处理意外输入

5.2 循环控制语句

5.2.1 for循环的结构与变体

for 循环是Java中最常用的循环结构之一,适用于已知循环次数的情况。其基本语法如下:

for (初始化; 条件判断; 更新语句) {
    // 循环体
}

参数说明:
- 初始化 :循环开始前执行一次。
- 条件判断 :每次循环前检查是否为 true ,若为 false 终止循环。
- 更新语句 :每次循环结束后执行。

示例:打印1到10的数字
for (int i = 1; i <= 10; i++) {
    System.out.println(i);
}

执行流程:
- 初始化 i=1
- 判断 i <= 10 ,若为真,执行循环体;
- 执行 i++
- 重复判断直到 i > 10 ,循环结束。

变体:增强型for循环(for-each)

适用于数组或集合的遍历:

int[] numbers = {1, 2, 3, 4, 5};

for (int num : numbers) {
    System.out.println(num);
}

执行流程:
- 每次从数组中取出一个元素赋值给 num
- 直到遍历完整个数组。

无限循环与跳出机制
for (;;) {
    // 执行循环体
    if (条件满足) {
        break;
    }
}

说明:
- 这是一个无限循环,需结合 break 语句跳出。
- 通常用于监听事件、服务器监听等场景。

5.2.2 while与do-while循环的对比

while循环

适用于循环次数未知的情况,先判断条件,再执行循环体:

int i = 1;
while (i <= 5) {
    System.out.println(i);
    i++;
}

执行流程:
- 判断 i <= 5 是否为真;
- 若为真,执行循环体并更新 i
- 重复直到条件不满足。

do-while循环

while 循环不同,它先执行一次循环体,再判断条件:

int i = 1;
do {
    System.out.println(i);
    i++;
} while (i <= 5);

执行流程:
- 先执行循环体;
- 然后判断条件是否为真;
- 若为真,继续循环。

对比表格:
特性 while循环 do-while循环
是否先判断
循环体执行次数 可能0次 至少1次
语法结构 while(条件) { ... } do { ... } while(条件);
适用场景 已知条件是否成立 确保循环体至少执行一次

5.3 跳转语句

5.3.1 break语句在循环与switch中的作用

break 语句用于立即终止当前所在的循环或 switch 语句。

在switch中使用break
int day = 2;
switch (day) {
    case 1:
        System.out.println("星期一");
        break;
    case 2:
        System.out.println("星期二");
        break;
    default:
        System.out.println("未知");
}

作用:
- 防止 case 穿透,确保只执行匹配的代码段。

在循环中使用break
for (int i = 1; i <= 10; i++) {
    if (i == 5) {
        break;
    }
    System.out.println(i);
}

执行结果:
- 打印1到4,当 i == 5 时跳出循环。

5.3.2 continue语句的使用场景

continue 语句用于跳过当前循环体中剩余的代码,直接进入下一次循环。

示例:跳过偶数,打印奇数
for (int i = 1; i <= 10; i++) {
    if (i % 2 == 0) {
        continue;
    }
    System.out.println(i);
}

执行流程:
- 判断 i 是否为偶数;
- 若是偶数,执行 continue 跳过后续语句;
- 若是奇数,打印 i

continue与break的区别
特性 continue break
作用 跳过当前循环迭代 终止整个循环
应用场景 过滤特定值 提前结束循环
是否跳出循环

5.4 综合实例分析

5.4.1 判断素数的程序实现

素数是指除了1和它本身之外没有其他因数的自然数。我们使用循环和条件判断来实现素数判断程序。

import java.util.Scanner;

public class PrimeChecker {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("请输入一个整数:");
        int number = scanner.nextInt();
        boolean isPrime = true;

        if (number < 2) {
            isPrime = false;
        } else {
            for (int i = 2; i <= Math.sqrt(number); i++) {
                if (number % i == 0) {
                    isPrime = false;
                    break;
                }
            }
        }

        if (isPrime) {
            System.out.println(number + " 是素数。");
        } else {
            System.out.println(number + " 不是素数。");
        }
    }
}

代码逻辑分析:
- 使用 Scanner 读取用户输入;
- 判断是否小于2,小于2的数不是素数;
- 从2开始循环到 √number ,判断是否存在因数;
- 若存在因数,设置 isPrime = false 并跳出循环;
- 最后根据 isPrime 的值输出结果。

优化建议:
  • 使用 Math.sqrt(number) 代替 i <= number / 2 ,提高效率;
  • 对于大数,可以使用更高级的算法如Miller-Rabin素数测试。

5.4.2 简单排序算法的控制结构应用

我们以冒泡排序为例,展示如何使用循环和条件判断实现排序。

public class BubbleSort {
    public static void main(String[] args) {
        int[] arr = {64, 34, 25, 12, 22, 11, 90};

        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] > arr[j + 1]) {
                    // 交换
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }

        System.out.println("排序后的数组:");
        for (int num : arr) {
            System.out.print(num + " ");
        }
    }
}

流程分析:
- 外层循环控制排序轮数;
- 内层循环负责比较相邻元素并交换;
- 每轮排序后,最大的元素会“冒泡”到最后;
- 最终输出排序后的数组。

流程图:
graph TD
    A[开始] --> B[定义数组]
    B --> C[外层循环i从0到n-2]
    C --> D[内层循环j从0到n-2-i]
    D --> E[判断arr[j] > arr[j+1]]
    E -->|是| F[交换arr[j]和arr[j+1]]
    E -->|否| G[继续]
    F --> H[继续内层循环]
    G --> H
    H --> I[内层循环结束]
    I --> J[外层循环继续]
    J --> K[i是否小于n-1]
    K -->|是| C
    K -->|否| L[输出排序结果]
    L --> M[结束]

优化建议:
- 添加一个标志位,在某一轮没有发生交换时提前结束排序;
- 使用更高效的排序算法如快速排序或归并排序。

6. 面向对象编程基础

面向对象编程(Object-Oriented Programming,简称OOP)是Java语言的核心编程范式。它通过类与对象的结构组织代码,使得程序结构更加清晰、易于维护和扩展。本章将从类与对象的基本概念出发,深入探讨构造方法、方法重载、static关键字等面向对象编程的关键要素,帮助读者建立对Java面向对象编程体系的系统性理解。

6.1 面向对象的核心概念

6.1.1 类与对象的关系

类(Class)是对一类具有相同属性和行为的事物的抽象描述。对象(Object)则是类的具体实例。例如,“汽车”是一个类,而“一辆红色宝马X5”就是“汽车”类的一个对象。

代码示例:定义一个类并创建对象

public class Car {
    // 属性
    String color;
    String brand;

    // 方法
    void startEngine() {
        System.out.println(brand + "的引擎启动了");
    }
}

// 测试类
public class TestCar {
    public static void main(String[] args) {
        // 创建对象
        Car myCar = new Car();
        myCar.color = "红色";
        myCar.brand = "宝马X5";
        myCar.startEngine(); // 调用方法
    }
}

逐行分析:

  • public class Car :定义一个名为 Car 的类。
  • String color; String brand; :类中定义的两个属性,用于描述汽车的颜色和品牌。
  • void startEngine() :类中定义的一个方法,表示汽车的行为。
  • Car myCar = new Car(); :使用 new 关键字创建一个 Car 类的实例,即一个对象。
  • myCar.color = "红色"; :为对象的属性赋值。
  • myCar.startEngine(); :调用对象的方法。

关系图示:

classDiagram
    Class Car
    Object myCar : Car
    Car <|-- myCar

6.1.2 属性与方法的定义

属性(Fields)是类中用于描述对象状态的变量,方法(Methods)是类中用于描述对象行为的函数。

属性定义:
- 通常使用访问修饰符(如 private public )控制其可见性。
- 可以是基本数据类型或引用类型。

方法定义:
- 方法名后紧跟括号 () ,可以带参数。
- 方法可以有返回值,也可以是 void 类型。

代码示例:带有访问控制的方法与属性

public class Person {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }
}

参数说明:
- private :限制属性只能在本类内部访问。
- this.name :用于区分参数与类属性的同名冲突。

6.2 构造方法与对象生命周期

6.2.1 默认构造方法与自定义构造方法

构造方法(Constructor)是在创建对象时自动调用的方法,用于初始化对象的状态。

默认构造方法:
- 如果没有显式定义构造方法,Java会自动提供一个无参构造方法。
- 例如: new Person();

自定义构造方法:
- 可以定义带参数的构造方法,以便在创建对象时传入初始值。

代码示例:自定义构造方法

public class Person {
    private String name;
    private int age;

    // 自定义构造方法
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void display() {
        System.out.println("姓名:" + name + ",年龄:" + age);
    }
}

// 使用构造方法创建对象
public class TestPerson {
    public static void main(String[] args) {
        Person p = new Person("张三", 25);
        p.display();
    }
}

逻辑分析:
- Person p = new Person("张三", 25); :调用自定义构造方法,传入姓名和年龄。
- 构造方法将传入的参数赋值给类的属性。
- p.display(); :调用方法输出对象信息。

6.2.2 对象的创建与销毁过程

对象的生命周期包括创建、使用和销毁三个阶段。

创建阶段:
- 使用 new 关键字调用构造方法创建对象。
- 对象在堆内存中分配空间。
- 引用变量(如 Person p )指向堆中的对象。

使用阶段:
- 通过引用变量调用对象的方法和属性。

销毁阶段:
- 当对象不再被引用时,Java垃圾回收机制(Garbage Collector)会在适当的时候回收其占用的内存。

流程图:

graph TD
    A[程序启动] --> B[调用new创建对象]
    B --> C[调用构造方法初始化]
    C --> D[对象在堆中创建]
    D --> E[引用变量指向对象]
    E --> F[使用对象的方法和属性]
    F --> G[对象不再被引用]
    G --> H[GC回收内存]

6.3 方法的重载与参数传递

6.3.1 方法重载的规则

方法重载(Overloading)是指在同一个类中定义多个同名方法,但它们的参数列表不同。

重载规则:
- 方法名必须相同。
- 参数列表必须不同(参数个数、类型、顺序不同均可)。
- 返回值类型可以不同,但不能作为唯一区分依据。

代码示例:方法重载

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }

    public double add(double a, double b) {
        return a + b;
    }

    public int add(int a, int b, int c) {
        return a + b + c;
    }
}

// 测试类
public class TestCalculator {
    public static void main(String[] args) {
        Calculator calc = new Calculator();
        System.out.println(calc.add(2, 3));       // 调用第一个add方法
        System.out.println(calc.add(2.5, 3.7));   // 调用第二个add方法
        System.out.println(calc.add(2, 3, 4));    // 调用第三个add方法
    }
}

分析说明:
- Java通过参数类型和数量来决定调用哪个重载方法。
- calc.add(2, 3) :匹配 int add(int, int)
- calc.add(2.5, 3.7) :匹配 double add(double, double)
- calc.add(2, 3, 4) :匹配 int add(int, int, int)

6.3.2 参数的值传递与引用传递

Java中所有参数都是 值传递 ,不存在真正的引用传递。

基本数据类型:
- 传递的是变量的值,修改不会影响原变量。

引用数据类型:
- 传递的是引用地址的副本,方法中修改对象属性会影响原对象,但修改引用本身不会影响外部引用。

代码示例:值传递与引用传递演示

public class ParamTest {
    public static void changeInt(int x) {
        x = 100;
    }

    public static void changeArray(int[] arr) {
        arr[0] = 99;
    }

    public static void main(String[] args) {
        int a = 10;
        changeInt(a);
        System.out.println("a = " + a); // 输出 10

        int[] nums = {1, 2, 3};
        changeArray(nums);
        System.out.println("nums[0] = " + nums[0]); // 输出 99
    }
}

参数说明:
- changeInt(a) :将 a 的值复制给 x ,修改 x 不影响 a
- changeArray(nums) :将数组引用复制给 arr ,两者指向同一数组,修改内容影响原数组。
- arr[0] = 99 :修改的是数组对象的内容,而非引用本身。

6.4 static关键字的应用

6.4.1 静态属性与静态方法

static 关键字用于定义类级别的属性和方法,它们属于类,而不属于某个对象。

静态属性(Static Field):
- 所有对象共享同一个静态属性。
- 通过类名直接访问。

静态方法(Static Method):
- 不能访问非静态属性和方法。
- 可以直接通过类名调用。

代码示例:静态属性与静态方法

public class Counter {
    public static int count = 0;

    public Counter() {
        count++; // 每次创建对象,count加1
    }

    public static void displayCount() {
        System.out.println("当前对象数量:" + count);
    }
}

// 测试类
public class TestCounter {
    public static void main(String[] args) {
        Counter c1 = new Counter();
        Counter c2 = new Counter();

        Counter.displayCount(); // 输出 2
    }
}

分析说明:
- count 是静态属性,所有 Counter 对象共享。
- displayCount() 是静态方法,通过类名直接调用。
- 每次创建对象,构造方法都会使 count 自增。

6.4.2 静态代码块与初始化顺序

静态代码块(Static Block)在类加载时执行,常用于初始化静态资源。

初始化顺序:
1. 静态变量和静态代码块按声明顺序执行。
2. 非静态变量和构造代码块按声明顺序执行。
3. 最后执行构造方法。

代码示例:静态代码块与初始化顺序

public class InitOrder {
    static {
        System.out.println("静态代码块执行");
    }

    {
        System.out.println("构造代码块执行");
    }

    public InitOrder() {
        System.out.println("构造方法执行");
    }
}

// 测试类
public class TestInit {
    public static void main(String[] args) {
        new InitOrder();
        new InitOrder();
    }
}

输出结果:

静态代码块执行
构造代码块执行
构造方法执行
构造代码块执行
构造方法执行

结论:
- 静态代码块只在类首次加载时执行一次。
- 构造代码块在每次创建对象时执行,早于构造方法。
- 构造方法在对象创建时最后执行。

本章通过类与对象的定义、构造方法的使用、方法重载机制、static关键字的应用等多个层面,系统地讲解了Java面向对象编程的基础知识。这些内容构成了Java OOP的基石,也是后续封装、继承、多态等高级特性的基础。

7. 封装、继承与多态特性

7.1 封装机制

封装(Encapsulation)是面向对象编程的三大特性之一,旨在将对象的内部状态和行为隐藏起来,只对外暴露必要的接口。通过封装,可以有效地保护对象的数据安全性和逻辑完整性。

7.1.1 访问修饰符(private、protected、public)

Java 提供了四种访问修饰符,控制类成员的访问权限:

修饰符 同类 同包 子类 其他包
private
默认(无修饰)
protected
public

例如,定义一个 Person 类,并使用 private 修饰其字段,通过 public 方法访问:

public class Person {
    private String name;
    private int age;

    // Getter and Setter
    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        if (age > 0) {
            this.age = age;
        } else {
            System.out.println("年龄必须大于0");
        }
    }
}

上述代码中, name age 字段被声明为 private ,只能通过 getName() setName() getAge() setAge() 等方法进行访问和修改,这在一定程度上防止了非法赋值。

7.1.2 Getter与Setter方法的设计

Getter 和 Setter 方法是封装机制的重要体现。它们允许对属性进行访问控制和数据验证。例如,在 setAge() 方法中,可以加入逻辑判断防止非法输入。

此外,IDE(如 IntelliJ IDEA)支持自动生成 Getter 和 Setter 方法,提升开发效率。

7.2 继承机制

继承(Inheritance)是面向对象编程的另一个核心特性,它允许一个类(子类)继承另一个类(父类)的属性和方法。通过继承可以实现代码复用和层次化结构设计。

7.2.1 类的继承关系与extends关键字

使用 extends 关键字实现类的继承。例如:

class Animal {
    public void eat() {
        System.out.println("动物吃东西");
    }
}

class Dog extends Animal {
    public void bark() {
        System.out.println("狗在叫");
    }
}

在上述代码中, Dog 类继承了 Animal 类的 eat() 方法,同时拥有自己的 bark() 方法。

public class TestInheritance {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat();  // 继承自Animal类
        dog.bark(); // Dog类自己的方法
    }
}

执行结果:

动物吃东西
狗在叫

继承不仅实现了方法的复用,也体现了“is-a”关系。

7.2.2 super关键字与构造方法调用

在子类中,可以使用 super 关键字调用父类的构造方法或方法。例如:

class Animal {
    public Animal(String name) {
        System.out.println("Animal构造方法,名称:" + name);
    }
}

class Cat extends Animal {
    public Cat(String name) {
        super(name);  // 调用父类构造方法
        System.out.println("Cat构造方法");
    }
}

执行以下代码:

public class TestSuper {
    public static void main(String[] args) {
        Cat cat = new Cat("Tom");
    }
}

输出:

Animal构造方法,名称:Tom
Cat构造方法

通过 super() ,子类可以在构造时调用父类的构造函数,确保父类的初始化逻辑得以执行。

7.3 多态性与方法重写

多态(Polymorphism)是面向对象编程的第三大特性,指的是同一个接口可以有多种不同的实现方式。多态通常通过方法重写(Overriding)和向上转型(Upcasting)来实现。

7.3.1 方法重写的规则

子类可以重写从父类继承的方法,以实现不同的功能。重写方法必须满足以下条件:

  • 方法名、参数列表必须相同;
  • 返回类型必须相同或是子类;
  • 访问权限不能比父类更严格;
  • 抛出异常不能比父类更宽泛。

例如:

class Animal {
    public void makeSound() {
        System.out.println("动物发出声音");
    }
}

class Cat extends Animal {
    @Override
    public void makeSound() {
        System.out.println("猫喵喵叫");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("狗汪汪叫");
    }
}

测试多态:

public class TestPolymorphism {
    public static void main(String[] args) {
        Animal a1 = new Cat();
        Animal a2 = new Dog();

        a1.makeSound();  // 输出:猫喵喵叫
        a2.makeSound();  // 输出:狗汪汪叫
    }
}

7.3.2 向上转型与运行时多态

向上转型(Upcasting)指的是将子类对象赋值给父类引用。在运行时,JVM 会根据实际对象类型决定调用哪个方法,这就是运行时多态。

流程图示意如下:

graph TD
    A[Animal a = new Cat()] --> B[调用a.makeSound()]
    B --> C{运行时检查对象类型}
    C -- 是 Cat --> D[调用Cat的makeSound()]
    C -- 是 Dog --> E[调用Dog的makeSound()]

多态机制提升了代码的灵活性和可扩展性,常用于设计接口和抽象类。

7.4 抽象类与接口

抽象类和接口是实现多态和代码解耦的重要工具,尤其在大型系统设计中应用广泛。

7.4.1 抽象类的定义与应用场景

抽象类使用 abstract 关键字定义,不能被实例化,可以包含抽象方法(没有实现的方法)和具体方法。

示例:

abstract class Shape {
    abstract double getArea();  // 抽象方法

    void printType() {
        System.out.println("这是一个形状");
    }
}

class Circle extends Shape {
    private double radius;

    public Circle(double radius) {
        this.radius = radius;
    }

    @Override
    double getArea() {
        return Math.PI * radius * radius;
    }
}

测试抽象类:

public class TestAbstract {
    public static void main(String[] args) {
        Shape shape = new Circle(5);
        shape.printType();  // 输出:这是一个形状
        System.out.println("面积:" + shape.getArea());  // 输出:面积:78.53981633974483
    }
}

抽象类适用于具有相同结构但不同实现的类族设计。

7.4.2 接口的实现与多继承的实现方式

Java 中的接口(Interface)用于定义行为规范,类通过 implements 实现接口。接口支持多继承,这是 Java 实现多继承的唯一方式。

示例:

interface Flyable {
    void fly();
}

interface Swimmable {
    void swim();
}

class Duck implements Flyable, Swimmable {
    @Override
    public void fly() {
        System.out.println("鸭子飞");
    }

    @Override
    public void swim() {
        System.out.println("鸭子游泳");
    }
}

测试接口实现:

public class TestInterface {
    public static void main(String[] args) {
        Duck duck = new Duck();
        duck.fly();  // 输出:鸭子飞
        duck.swim(); // 输出:鸭子游泳
    }
}

接口适用于定义多个类共有的行为规范,且允许类实现多个接口,从而实现“多继承”效果。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:Java是一种广泛使用的面向对象编程语言,具有跨平台、高性能和丰富类库等优势。本”Java基础教程PPT”专为初学者和有编程经验者设计,系统讲解Java核心知识体系,内容涵盖基础语法、面向对象编程、容器、多线程、数据库连接、网络编程、RMI远程调用和JSP动态网页技术。通过本教程学习,可帮助开发者系统掌握Java编程基础,为后续学习框架开发和企业级项目打下坚实基础。PPT内容经过教学验证,适合自学和课堂教学使用。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐