手把手带你一小时零基础入门Java!

        由于我是初学者,所以有错误请一定要指正

        总共11章,24000字,手把手带你零基础入门Java_(:з」∠)_从Java基础到进阶内容,通俗易懂,适合初学者!完美实现前端变前台,后端变后厨,全栈变全完,运维变运输,测试变测绘!

        Kawaii LOGO of Java LOGO图源 Sawaratsuki

目录

目录

第一章:Java 环境搭建

 第二章:变量、数据类型、运算符、表达式

第三章:分支结构

第四章:循环结构

第五章:函数

第六章:数组

第七章:面向对象

第八章:面向对象的三大特性

第九章:三个修饰符

第十章:接口

第十一章:理解内部类


第一章:Java 环境搭建

Java 是一种计算机编程语言,除了 Java 之外,还有很多其他编程语言,如 C、C++、C#、Python 等。不同编程语言就像不同国家的语言,每种编程语言的语法和应用场景都不同。Java 主要用于后端开发。

一、Java 历史

  1. 1995年,Sun 公司推出了一款面向对象的编程语言——Java。
  2. JDK:Java 开发的必要工具。
    • 1997年:JDK 1.1
    • 1998年:JDK 1.2
    • 2004年:JDK 1.5 版本,更名为 JDK 5.0,添加了新特性如泛型和增强的 for 循环。
    • 随后版本:
      • JDK 6.0
      • JDK 7.0
      • JDK 8.0 -> 企业级,添加 lambda 表达式和 stream 流
      • 最新版本:JDK 22
  3. 2009年:Sun 被 Oracle(甲骨文)收购。

Java 的发展方向:

  • JavaSE:Java 语言核心基础
  • JavaEE:企业级开发应用
  • JavaME:通信相关

二、Java 语言的特点

  1. 简单性:相对于 C、C++ 等。
  2. 开源性:开放源代码,编程人员可以查看和修改。
  3. 资源广泛性:有很多编程爱好者研究,大厂也积极推动。
  4. 跨平台性:可以在不同操作系统上运行,如 Windows、Linux、Unix、macOS 等。
  5. 面向对象性:强调对象的概念,后续会详细讲解。

三、Java 运行机制

  1. Java 运行机制:先编译后解释运行。

    • 源码文件:.java 文件,由开发人员编写。
    • 编译:将 .java 源文件通过编译器生成对应的字节码文件(.class 文件)。
    • 运行:将 .class 文件通过解释器逐行翻译并运行。
  2. 注意:实际运行时,运行的是 .class 文件。.java 文件只需编译一次,.class 文件可以被多次运行。如果源代码更改,需要重新编译,生成新的 .class 文件。

四、环境搭建

  1. 名词解释

    • JVM:Java 虚拟机,屏蔽不同操作系统之间的差异。
    • JRE:Java 运行环境,包含解释器和 JVM。
    • JDK:Java 开发工具,包含 JRE、编译器和工具类。
  2. 安装 JDK

    • 点击 JDK 的安装文件,按照步骤完成安装。
    • 不要重复安装 JDK,如需卸载,请通过控制面板操作。
    • JDK 没有提供操作界面,需要安装文本编辑器(如 Notepad++)进行代码编写。
  3. 配置环境变量

    • JAVA_HOME:JDK 的根目录(如 C:\Program Files\Java\jdk1.8.0_131)。
    • Path:JDK 的 bin 目录(如 C:\Program Files\Java\jdk1.8.0_131\bin)。
    • ClassPath:告诉 JVM 去哪里找 .class 文件,. 代表当前路径。
  4. 测试 JDK 是否安装成功

    • 打开 CMD 命令窗口进行测试。
    • 在命令窗口中输入 javacjava。(或者java -version)

五、Java 的第一个开发程序

  1. Java 的源文件以 .java 结尾。
  2. Class:类,是代码的容器。
  3. 编译和运行
    class Main {
        public static void main(String[] args) {
            System.out.println("Hello World");
            System.out.println("LXH Cat is here");
        }
    }
    
    • Main 函数:程序的入口,一个类中最多只能有一个主函数。
    • System.out.println():控制台打印输出信息。
    • 编译javac 源文件名.java
    • 运行java 类名

六、Package(包)

  1. 作用:类似于文件夹,方便进行分类管理。

  2. 语法package 包名;

  3. 注意事项

    • package 语句必须位于源文件中第一行有效语句。
    • 一个源文件中最多只能定义一个 package 语句。
  4. 带包的编译和运行

    • 编译javac -d . 源文件名.java
    • 运行java 包名.类名

七、编码规范

  1. 良好的标识符命名规范

    • 硬性要求
      1. Java 中标识符只能以字母、数字、下划线(_)或美元符号($)组成,不能以数字开头。
      2. 没有长度限制。
      3. 严格区分大小写。
      4. 不能使用 Java 中的关键字、保留字、特殊符号命名(如 truefalsenull)。
    • 建议要求
      1. 名字应具有描述性,如 StudentWorker
      2. 包名:全小写(如 package demo.com.zmj)。
      3. 类名:每个单词首字母大写(如 TestStudent)。
      4. 变量名/函数名/方法名:第一个单词首字母小写,其余单词首字母大写(如 ageAndName)。
      5. 常量:全大写(如 PI)。
  2. 良好的编码格式

    • 一行只写一句代码。
    • 层级之间要有严格缩进,一个 Tab 键。
  3. 良好的注释习惯

    • 单行注释//,只能写一行注释内容。
    • 多行注释/* ... */,可以写多行注释内容。
    • 注意:注释内容不参与编译。
    • 注意:单行注释不能嵌套多行注释,但多行注释可以嵌套单行注释。

练习

创建一个源文件命名为 TestStudent.java,定义包结构,包名为 demo,定义公开类,类中打印输出信息如下:

package demo;

public class TestStudent {
    public static void main(String[] args) {
        System.out.println("Hello there, this is just a simple print code");
        System.out.println("LXH Cat is here");
    }
}

编译和运行

  • 编译javac -d . TestStudent.java
  • 运行java demo.TestStudent

 第二章:变量、数据类型、运算符、表达式

一、变量

  1. 概念:变量是计算机中一块内存空间,用于存储数据的基本单元。
  2. 变量的组成部分:数据类型、变量名、数据。
  3. 语法
    • 先声明,再赋值:
      数据类型 变量名;  // 声明
      变量名 = 值;    // 赋值
      

    • 声明的同时赋值:
      数据类型 变量名 = 值;
      
    • 同时定义多个相同类型的变量:
      数据类型 变量名1, 变量名2 = 值, 变量名3;
      

二、Java 中的数据类型分类

  1. 基本数据类型(原始数据类型)

    • 整数类型(4种)
      • byte:1字节,范围 -128 到 127。
      • short:2字节,范围 -32768 到 32767。
      • int:4字节,范围 -2147483648 到 2147483647。
      • long:8字节,范围 -9223372036854775808 到 9223372036854775807,字面值后面需要加 Ll(建议大写,区分数字1)。
    • 浮点类型(2种)
      • float:单精度,4字节,字面值后面必须加 fF
      • double:双精度,8字节,字面值后面可以加 dD,或不加。
    • 字符类型(1种)
      • char:2字节,字面值形式为单引号引起来的一个字符,如 'A'。也可以用整数表示字符,范围 0 到 65535,如 char c = 65;
      • 转义字符:\n(换行)、\t(水平制表符)、\'(单引号)、\"(双引号)。
    • 布尔类型(1种)
      • boolean:字面值为 truefalse
  2. 引用数据类型

    • 类、数组、接口等。
    • 例如,字符串 String 使用双引号引起来的一个或多个字符:
      String str = "你快去给我看罗小黑战记";
      
  3. 数据类型的实际开发总结

    • 整数类型通常使用:int
    • 小数类型:double
    • 布尔类型:常用于判断、循环结构中
    • 字符类型:实际开发不常用
    • 字符串:实际开发中频繁使用
    • 实际存储数据根据项目业务需求
      String name = "LXH Cat";  // 姓名
      int age = 10;          // 年龄
      double score = 0;   // 成绩
      String sex = "男";     // 性别
      char gender = '男';    // 性别
      int flag = 1;          // 性别标识,1-男,0-女
      String tel = "123123123123"; // 电话
      String addr = "北京市"; // 地址
      String id = "123456789012345678"; // 身份证号
      

三、数据类型之间的转换

  1. 自动类型提升
    • 场景:小数据类型赋值给大数据类型(存储的数据范围衡量数据的大小)。
    • 规则:byte -> short -> int -> long -> float -> double
    • 规则:char -> int -> long -> float -> double
  2. 强制类型转换
    • 场景:大数据类型赋值给小数据类型,需要强制类型转换。
    • 语法:
      源数据类型 变量名 = 值;
      目标类型 变量名2 = (目标类型)变量名;
      

四、表达式

  1. 理解:表达式由字面值、变量、运算符组成,通常有一个结果。
  2. 表达式的结果规则
    • 如果表达式中有 double 类型,结果为 double
    • 表达式中没有 double 类型,有 float,结果为 float
    • 表达式中没有 doublefloat 类型,有 long,结果为 long
    • 其余结果为 int

五、运算符

  1. 算术运算符
    • +(加法/字符串拼接)
    • -(减法)
    • *(乘法)
    • /(除法)
    • %(取余数/取模)
    • 注意:+ 的两种用法:
      • 两端为数值类型,则为加法运算。
      • 两端有一端为字符串类型,则为字符串拼接。
  2. 赋值运算符
    • =(赋值)
    • +=(加后赋值)
    • -=(减后赋值)
    • *=(乘后赋值)
    • /=(除后赋值)
  3. 比较运算符(关系运算符)
    • >(大于)
    • >=(大于等于)
    • <(小于)
    • <=(小于等于)
    • ==(等于)
    • !=(不等于)
    • 注意:关系运算符连接的表达式结果类型为布尔类型,称为布尔表达式(结果为 truefalse)。
  4. 逻辑运算符
    • &&(逻辑与):两端表达式都为 true,结果才为 true
    • ||(逻辑或):只要有一端为 true,结果为 true
    • !(逻辑非):对结果取反。
  5. 一元运算符
    • ++(自增)
    • --(自减)
    • 应用:
      • a++++a:将 a 自增1。
      • a----a:将 a 自减1。
    • 面试/考试常见内容:
      • int c = a++; 先使用,再自增。
      • int c = ++a; 先自增,再使用。
  6. 三元运算符
    • 语法:布尔表达式 ? 表达式1 : 表达式2
    • 原理:判断表达式是否成立,结果为 true,执行表达式1,否则执行表达式2。

六、Scanner(扫描仪)

  1. 作用:让用户输入信息,提高人机交互。
  2. 导包
    • 语法:
      import 包名1.包名2.类名; // 导入指定类
      import 包名1.包名2.*; // 导入包中所有类
      
    • 位置:定义在 package 语句的后面,所有类的上面。
    • 例如:
      import java.util.Scanner;
      
  3. 步骤
    1. 导入包:
      import java.util.Scanner;
      import java.util.*; 
      
    2. 创建对象:
      Scanner sc = new Scanner(System.in);
    3. 使用:

      int n = sc.nextInt(); // 输入一个整数
      double d = sc.nextDouble(); // 输入一个小数
      String s = sc.next(); // 输入一个字符串
      char c = sc.next().charAt(0); // 输入一个字符
      

第三章:分支结构

一、if 分支结构

1. 基本 if 结构
  • 语法
    if (判断条件/布尔表达式) {
        // 语句
    }
    
  • 执行原理:如果判断条件成立,则执行 {} 中的语句。
2. 带 else 的 if 结构
  • 语法
    if (判断条件/布尔表达式) {
        // 语句1
    } else {
        // 语句2
    }
    
  • 执行原理:如果 if 条件成立,则执行语句1,否则执行语句2。

3. 多重 if 结构
  • 语法
    if (判断条件1) {
        // 语句1
    } else if (判断条件2) {
        // 语句2
    } else if (判断条件3) {
        // 语句3
    } else {
        // 语句n
    }
    
  • 执行原理:从上往下依次判断,哪个条件成立,则执行对应 {} 中的语句。
4. if 嵌套结构
  • 语法
    if (判断条件/布尔表达式) {
        if (判断条件/布尔表达式) {
            // 语句
        } else if (判断条件) {
            // 语句
        } else {
            // 语句
        }
    } else {
        // 语句
    }
    
  • 执行原理:外层 if 条件成立时,进入内层判断。

二、等值分支结构(switch...case 结构)

1. 语法
  • 语法
    switch (表达式) {
        case 值1:
            语句1;
            break;
        case 值2:
            语句2;
            break;
        case 值3:
            语句3;
            break;
        ...
        default:
            语句n;
            break;
    }
    
2. 执行原

首先获取 switch 中表达式的结果,根据结果从上往下匹配 case 后面的值,结果与哪一个 case 的值相等,则执行对应的语句。如果都不相等,则执行 default 后面的语句。

3. 细节
  • 表达式的结果类型:可以是 byteshortintcharString
  • break:终止 switch 结构,防止 case 穿透。
  • default:没有位置先后要求,可以放在任意位置。

三、局部变量

1. 概念

定义在函数/方法内部的变量。

2. 特点
  • 必须先赋值,再使用
    • 报错:可能尚未初始化变量。
  • 作用范围:从定义位置开始,到定义它的代码块结束。
    • 报错信息为:找不到符号。
  • 在重合的作用范围内,不允许命名冲突
    • 报错信息为:已在方法 xxx 中定义了变量 xx。

四、if 语句示例

public class IfExample {
    public static void main(String[] args) {
        int number = 10;

        if (number > 0) {
            System.out.println("这个数是正数");
        } else {
            System.out.println("这个数是负数,也可能是0");
        }

        if (number > 0) {
            System.out.println("这个数是正数");
        } else if (number < 0) {
            System.out.println("这个数是负数");
        } else {
            System.out.println("这个数是0");
        }
    }
}

五、switch 语句示例

public class SwitchExample {
    public static void main(String[] args) {
        int day = 3;
        String love;

        switch (day) {
            case 1:
                love  = "Monday left me broken";
                break;
            case 2:
                love = "Tuesday I was through with hopin";
                break;
            case 3:
                love = "Wednesday my empty arms were open";
                break;
            case 4:
                love = "Thursday waiting for love, waiting for love";
                break;
            case 5:
                love = "Thank the stars it's Friday";
                break;
            case 6:
                love = "I'm burning like a fire gone wild on Saturday";
                break;
            case 7:
                love = "Guess I won't be coming to church on Sunday";
                break;
            default:
                love = "Invalid day. Waiting for love";
                break;
        }

        System.out.println(love);
    }
}

六、局部变量示例

public class LocalVariableExample {
    public static void main(String[] args) {
        int a = 5;  // 定义并初始化局部变量 a
        {
            int b = 10; // 定义局部变量 b
            System.out.println(a); // 可以访问变量 a
            System.out.println(b); // 可以访问变量 b
        }
        // System.out.println(b); // 报错,变量 b 超出作用范围
    }
}

第四章:循环结构

一、循环概述

1. 循环的概念

循环是通过某个条件,重复并且有规律地执行一段代码。

2. 循环的组成部分
  • 循环变量的初始化
  • 循环条件
  • 循环变量的改变
  • 循环体
3. 循环的分类
  • while 循环
  • do..while 循环
  • for 循环

二、while 循环

1. 语法
// 循环变量的初始化
while (循环条件) {
    // 循环体
    // 循环变量的改变
}
2. 执行原理

先执行循环变量的初始化,接着判断循环条件。如果循环条件满足(结果为 true),则执行循环体,然后执行循环变量的改变,再次判断循环条件。如果满足(结果为 true),则再次执行循环体,同时循环变量进行改变。如此重复,直到循环条件不满足(结果为 false),则终止并跳出循环结构。

3. 循环特点
  • 先判断,再执行,执行次数:0~n次
  • 如果程序写得不合适,可能会出现死循环

三、do..while 循环

1. 语法
// 循环变量的初始化
do {
    // 循环体
    // 循环变量的改变
} while (循环条件); // 分号不能省
2. 执行原理

先执行循环变量的初始化,然后执行循环体,接着对循环变量进行改变,判断循环条件。如果满足(结果为 true),则再次执行循环体,对循环变量进行改变,再判断循环条件。如此重复,直到循环条件结果为 false,结束并跳出循环结构。

3. 特点

先执行,再判断,执行次数为 1~n 次。

四、for 循环

1. 语法
for (循环变量的初始化; 循环条件; 循环变量的改变) {
    // 循环体
}
2. 执行原理

执行顺序:

  1. 循环变量的初始化
  2. 判断循环条件
  3. 如果循环条件为 true,执行循环体
  4. 执行循环变量的改变
  5. 回到步骤2,继续循环,直到循环条件为 false,终止循环
3. 执行特点
  • 先判断,再执行,执行次数 0~n 次
  • for 中的循环变量初始化可以定义在外面,但变量的作用范围扩大了
  • for 中的判断条件如果为空语句,则默认结果为 true

循环总结

  • whilefor:循环特点相同,先判断,再执行
  • do...while:先执行,再判断
  • 实际开发中:
    • for 循环比较常用
    • 循环次数不明确时,建议使用 while 循环
    • 循环次数明确时,建议使用 for 循环

五、循环控制语句

1. break
  • 终止、结束当前循环结构
  • 可以应用在 switch..case 结构中,防止 case 穿透
2. continue
  • 中止、结束本次循环,从而进入下一次循环
示例:
public class LoopControlExample {
    public static void main(String[] args) {
        // 示例:break
        for (int i = 0; i < 10; i++) {
            if (i == 5) {
                break; // 当i等于5时,终止循环
            }
            System.out.println("i = " + i);
        }

        System.out.println("----------");

        // 示例:continue
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0) {
                continue; // 跳过当前循环,进入下一个循环
            }
            System.out.println("i is: " + i);
        }
    }
}

六、循环的嵌套

1. 理解

在循环结构中,定义一个完整的循环结构,即外层循环和内层循环。

2. 循环的次数

外层循环次数 * 内层循环次数

3. 循环控制语句应用的嵌套中
  • break:终止、结束本层循环
  • continue:中止、结束本层本次循环
4. 利用循环结构打印图形
  • 外层循环控制行数
  • 内层循环控制列数

示例代码

while
public class DoWhileExample {
    public static void main(String[] args) {
        int i = 0; // 初始化循环变量
        while (i < 5) { // 循环条件
            System.out.println("i = " + i);
            i++; // 循环变量的改变
        }  
    }
}
do..while
public class DoWhileExample {
    public static void main(String[] args) {
        int i = 0; // 初始化循环变量
        do {
            System.out.println("i = " + i);
            i++; // 循环变量的改变
        } while (i < 5); // 循环条件
    }
}
for
public class ForExample {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) { // 初始化、条件、改变都在同一个语句中
            System.out.println("i is: " + i);
        }
    }
}
循环嵌套示例
public class NestedLoopExample {
    public static void main(String[] args) {
        for (int i = 1; i <= 5; i++) { // 外层循环控制行数
            for (int j = 1; j <= i; j++) { // 内层循环控制列数
                System.out.print("*");
            }
            System.out.println(); // 换行
        }
    }
}

第五章:函数

一、函数的基本概念

1. 理解

函数是一段执行特定功能的代码块,并且可以通过名字反复调用。

2. 函数的使用流程
  1. 函数的定义:确定函数的功能和名称
    • 函数的声明:确定函数的名字
    • 函数的实现:确定函数的功能
  2. 函数的调用:通过函数名进行调用
3. 函数的定义位置

定义在类的内部,与其他方法(如 main 方法)并列。

二、函数的基本使用

1. 函数的定义
public static void 函数名() {
    // 函数的实现
}
  • 函数的声明public static void 函数名()
    • 函数名通常采用驼峰命名法
  • 函数的实现:用 {} 包围的代码块
2. 函数的调用
  • 通过函数名直接调用函数
  • 语法:
函数名(参数);

三、参数的使用

1. 参数的作用

多数情况下,函数与调用者之间需要数据交互。调用者必须提供必要的数据,才能使函数完成相应的功能。这些数据称为参数。

2. 形式参数(形参)
  • 形式参数:简称形参,是函数和调用者之间的一种约定,定义了调用者需要传递什么数据。
  • 形参的定义:
public static void 函数名(数据类型 变量名1, 数据类型 变量名2, 数据类型 变量名3) {
    // 函数体
}
  • 形参在函数内部相当于局部变量。
  • 一个函数可以定义多个形参。
3. 实际参数(实参)
  • 实际参数:简称实参,是函数调用时传递的数据。
  • 实参的作用:给形参赋值。
  • 注意:实参的个数、顺序、数据类型必须与形参一致。
示例

定义一个函数 selectMax,接收两个整数 mn,打印两个数据中的较大值,并在 main 函数中调用此函数。

public class MaxSelector {
    public static void main(String[] args) {
        selectMax(10, 20);
    }

    public static void selectMax(int m, int n) {
        if (m > n) {
            System.out.println("最大值是:" + m);
        } else {
            System.out.println("最大值是:" + n);
        }
    }
}

四、函数的返回值

1. 理解

函数和调用者之间的一种数据交互,调用者通过函数获取某些数据结果。

2. 返回值的语法
public static 返回值类型 函数名(形参列表) {
    // 函数体
}
3. 函数的返回值分类
  1. 返回值类型为 void,代表函数没有返回值:
    public static void 函数名(参数) {
        // 函数体
    }
    
  2. 返回值类型为 8 种基本数据类型或对象,代表函数有返回值:
    public static int 函数名(参数) {
        return 返回值;
    }
    
    public static double 函数名(参数) {
        return 返回值;
    }
    
    public static char 函数名(参数) {
        return 返回值;
    }
    
    public static String 函数名(参数) {
        return 返回值;
    }
    
    public static int[] 函数名(参数) {
        return 返回值;
    }
    
    public static ArrayList<String> 函数名(参数) {
        return 返回值;
    }
    
    public static 各种返回值类型 函数名(参数) {
        return 返回值;
    }
    
4. 函数返回值的处理
  1. 定义同类型的变量接收返回值。
  2. 直接使用返回值。
5. return 的作用
  • 将返回值返回给调用者。
  • 结束当前函数。
    public static void example() {
        // 如果返回类型处是void,那么也可以使用return
        //但是不能在return后面加东西,直接写return就好,这就代表结束当前函数
        return;
    }
示例

定义一个函数 add,接收两个整数 ab,返回它们的和。

public class Addition {
    public static void main(String[] args) {
        int sum = add(10, 20);
        System.out.println("sum=" + sum);
    }

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

五、函数的执行机制

1. 理解

程序以 main 函数作为入口,从上往下依次执行。如果遇到函数调用,则优先执行被调用的函数内部代码。被调用函数执行完毕后,带着返回值返回到调用位置,继续执行后续代码。

2. 函数的嵌套调用

被调用的函数内部,又调用了其他的函数。

示例
public class NestedFunctionExample {
    public static void main(String[] args) { // 主函数
        outerFunction(); // 调用外层函数
    }

    public static void outerFunction() {
        System.out.println("这是外层函数,第一个被调用");
        innerFunction(); // 调用内层函数
    }

    public static void innerFunction() {
        System.out.println("这是内层函数,第二个被调用");
    }
}

六、递归调用

1. 理解

一个函数中调用自身函数。

2. 注意

使用递归解决问题时,必须设置一个出口,否则会出现无穷递归,最终导致 java.lang.StackOverflowError(栈溢出)。

3. 递归的思想
  1. 递进:每次推进,计算都比上一次变得简单,直到简单到无需继续推进,就能获得结果。
  2. 回归:基于出口的结果,逐层向上回归,依次计算每一层的结果,直至回归到最顶层。
4. 案例:计算阶乘
public class Factorial {
    public static void main(String[] args) {
        int result = factorial(8);
        System.out.println("8的阶乘是:" + result);
    }

    public static int factorial(int n) {
        if (n == 1 || n == 0) {
            return 1;
        }
        return n * factorial(n - 1);
    }
}

第六章:数组

一、理解数组

1. 数组定义

数组是一次性定义多个同类型变量的集合,可以存储多个数据,并对这些变量进行统一管理。

2. 数组的重要因素

  • 数据类型:决定数组中存储数据的类型。
  • 数组的长度:数组中元素的个数。

3. 数组的使用

(1) 声明数组

确定数据类型和数组名:

数据类型[] 数组名; // 推荐的方式 数据类型 数组名[]; 数据类型 []数组名;

例如:

int[] a;

(2) 分配空间

确定数组的长度:

数组名 = new 数据类型[长度];

例如:

a = new int[4];

4. 细节

(1) 数组下标
  • 下标从 0 开始,依次为 0、1、2、3...数组的长度-1。
(2) 访问数组元素

通过数组名和下标访问:

数组名[下标]

(3) 数组下标越界

如果下标超出数组的合理范围,编译通过但运行时报错,错误信息为:

java.lang.ArrayIndexOutOfBoundsException: (数组的下标越界)
(4) 遍历数组

对数组元素进行逐一操作(遍历):

for(int i = 0; i < 数组名.length; i++) {
    System.out.println("元素 " + i + " 的值为:" + 数组名[i]);
}
(5) 获取数组长度
数组名.length

5. 数组的默认值

  • 整数类型:0
  • 小数类型:0.0
  • 布尔类型:false
  • 字符类型:空字符 '\u0000'
  • 引用类型:null

6. 数组的不同定义方式

(1) 先声明,再分配空间
数据类型[] 数组名;
数组名 = new 数据类型[长度];

(2) 声明的同时分配空间

数据类型[] 数组名 = new 数据类型[长度];

(3) 显示初始化

数据类型[] 数组名 = new 数据类型[]{值1, 值2, 值3};

(4) 简化的显示初始化

数据类型[] 数组名 = {值1, 值2, 值3};

二、数组的内存

1. 连续的内存空间

数组在内存中占用连续的空间。

2. 存储首地址

数组类型的变量存储数组内存空间的首地址。

3. 寻址方式

通过首地址和下标计算实际内存地址:

首地址 + 下标 * 数据类型字节数

三、数组的扩容

1. 扩容思想

  1. 创建一个更大空间的新数组,通常为原数组的两倍。
  2. 将原数组的内容复制到新数组中。
  3. 使用新数组替换旧数组。

2. 扩容的实现

(1) 手动实现扩容
int[] a = {4, 7, 3};
System.out.println("数组的长度为:" + a.length);

for(int i = 0; i < a.length; i++) {
    System.out.print(a[i] + "  ");
}
System.out.println();

// 扩容
int[] b = new int[a.length * 2];
for(int i = 0; i < a.length; i++) {
    b[i] = a[i];
}
a = b;

System.out.println("扩容后的长度为:" + a.length);
for(int i = 0; i < a.length; i++) {
    System.out.print(a[i] + "  ");
}
(2) 使用工具类扩容
int[] a = {4, 7, 3};
a = java.util.Arrays.copyOf(a, a.length * 2);
System.out.println("扩容后的长度为:" + a.length);

四、二维数组

1. 二维数组概述

类似于 Excel 表格,由行和列组成。

2. 访问二维数组

通过行标和列标进行访问:

数组名[行下标][列下标]

3. 二维数组的定义

(1) 定义一个 4 行 3 列的二维数组
int[][] a = new int[4][3];
(2) 示例
int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9},
    {10, 11, 12}
};

for(int i = 0; i < matrix.length; i++) {
    for(int j = 0; j < matrix[i].length; j++) {
        System.out.print(matrix[i][j] + " ");
    }
    System.out.println();
}

五、数组的排序

1. 排序概述

将数组中元素按一定顺序存储。

2. 排序方式

(1) 冒泡排序
int[] a = {9, 4, 5, 2, 6, 3, 1, 9};

// 冒泡排序
for(int i = 0; i < a.length - 1; i++) {
    for(int j = 0; j < a.length - 1 - i; j++) {
        if(a[j] > a[j + 1]) {
            int temp = a[j];
            a[j] = a[j + 1];
            a[j + 1] = temp;
        }
    }
}

for(int i = 0; i < a.length; i++) {
    System.out.print(a[i] + "\t");
}
(2) 使用工具类排序
int[] a = {9, 4, 5, 2, 6, 3, 1, 9};
java.util.Arrays.sort(a);

for(int i = 0; i < a.length; i++) {
    System.out.print(a[i] + "\t");
}

第七章:面向对象

一、编程思想

1. 面向过程

  • 定义:将问题分为若干步骤,逐步解决。
  • 特点:适用于解决小型、简单的业务问题,但面对复杂业务时难以处理。

2. 面向对象

  • 定义:将业务过程看作对象的集合,通过对象之间的关系解决问题。
  • 特点:适用于处理复杂的业务问题。

二、对象

1. 对象概述

  • 定义:对象是现实世界中事物在计算机中的抽象表示。Java 中一切皆对象。

2. 对象的组成部分

  • 属性:对象的特征,对应静态数据。
  • 方法:对象的行为,对应动态功能。

3. 类

  • 定义:类是描述一类对象的模板,包括对象的属性和方法。
  • 类和对象的关系:类是对象的模板,对象是类的实例。一个类可以创建多个对象。

三、类的组成

1. 类名

  • 命名规范:每个单词首字母大写。

2. 类的基本结构

class 类名 {
    // 属性
    // 方法
}

3. 属性

  • 定义:也称为成员变量。
  • 位置:定义在类内,方法外。
  • 语法
数据类型 变量名;
数据类型 变量名 = 值;
  • 默认值
    • 整数类型:0
    • 小数类型:0.0
    • 布尔类型:false
    • 字符类型:空字符 '\u0000'
    • 对象类型:null
  • 作用范围:在本类中有效。

4. 方法

  • 定义:也称为成员方法。
  • 位置:定义在类内,其他方法外。
  • 语法
public 返回值类型 方法名(形参) {
    // 方法体
}
  • 方法的组成
    • 声明:包括修饰符、返回值类型、方法名、形参列表和异常。
    • 实现:方法体部分 {}

5. 创建对象

  • 语法
类名 对象名 = new 类名();
  • 使用
对象名.属性名;
对象名.方法名(实参);

四、方法的重载 (Overload)

1. 定义

  • 一个类中可以定义多个同名的方法,但参数列表不同。

2. 要求

  • 方法名相同。
  • 形参列表不同(数据类型、个数、顺序)。
  • 返回值类型、修饰符、异常没有要求。

3. 使用

  • 根据调用时传递的实际参数决定调用哪个方法。

五、构造方法

1. 定义

  • 构造方法是一种特殊的方法,用于创建对象。

2. 定义位置

  • 定义在类内,方法外。

3. 特点

  • 方法名必须与类名一致。
  • 没有返回值类型。
  • 语法:
修饰符 类名(形参) {}
  • 允许重载(一个类中可以定义多个构造方法,但无参数的构造方法只能有一个)。

4. 使用

  • 在创建对象时,根据传递的实际参数决定调用哪个构造方法。
  • 如果类中没有提供任何构造方法,JVM 会默认提供一个无参数的构造方法。

5. 作用

  • 用于创建对象。
  • 可以给属性赋值。

6. 开发应用技巧

  • 提供两个构造方法:一个无参数的构造方法和一个有参数的构造方法。

六、this的应用

1. this.

  • 代表当前对象,用于调用本类中的属性或方法。
  • 用法
this.属性名;
this.方法名(实参);
  • 通常可以省略,但在成员变量和局部变量命名冲突时需要使用 this.

2. this()

  • 只能在构造方法中调用本类的其他构造方法。
  • 必须是构造方法中的第一行有效语句。

this本质上就是一个存储了当前对象的地址值的特殊变量

七、引用

1. 定义

  • 对象类型的变量。Java 是强类型语言,对应类型的数据需要存储在对应类型的变量中。
  • 语法
类名 引用名 = new 类名(实参);

2. 引用存储

  • 存储对象在堆空间中的首地址。

3. 对象的独立性

  • 每个对象在堆空间是相互独立的,操作一个对象不会影响其他对象。

4. 单独声明引用

  • 语法
类名 引用名;

5. 引用赋值

  • 相同类型的引用可以相互赋值,传递的是对象在堆空间中的首地址。

6. null引用

  • 可以使用 null 作为引用的初始化值,表示空地址。
  • 如果使用存储 null 的引用调用属性或方法,运行时报错,错误信息为:
java.lang.NullPointerException (空指针异常)

7. 引用的应用场景

  • 形式参数:对象类型和引用都可以作为实际参数传递。
  • 返回值类型:对象或引用都可以作为返回值。

第八章:面向对象的三大特性

一、封装

1. 现有问题

  • 程序中数据安全性无法保证,容易导致业务数据错误。

2. 使用 private 修饰符

  • 定义private 表示私有,被 private 修饰的内容只能在本类中访问。

3. 为私有化属性提供公开的 getset 方法

  • get 方法:获取私有属性的值。

    public 返回值类型 get属性名() {
        return 属性名;
    }
    
    • 注意:返回值类型取决于属性的类型,方法名为 get + 属性名首字母大写。
  • set 方法:为私有属性赋值。

    public void set属性名(数据类型 变量名) {
        this.属性名 = 变量名;
    }
    
    • 注意:参数的数据类型取决于属性类型,方法名为 set + 属性名首字母大写。

一个完整的类的封装示例(包含有参无参构造、getter和setter方法)

// User 封装
class User {

	private String account;// 账户
	private String password;// 密码
	private String phone;// 电话
	private String identityCard;// 身份证
	private double balance;// 余额

	public User() {
	}

	public User(String account, String password, String phone, String identityCard, double balance) {
		this.account = account;
		this.password = password;
		this.phone = phone;
		this.identityCard = identityCard;
		this.balance = balance;
	}

	// 账户封装
	public String getAccount() {
		return account;
	}

	public void setAccount(String account) {
		this.account = account;
	}

	// 密码封装
	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	// 电话封装
	public String getPhone() {
		return phone;
	}

	public void setPhone(String phone) {
		this.phone = phone;
	}

	// 身份证封装
	public String getIdentityCard() {
		return identityCard;
	}

	public void setIdentityCard(String identityCard) {
		this.identityCard = identityCard;
	}

	// 余额封装
	public Double getBalance() {
		return balance;
	}

	public void setBalance(double balance) {
		this.balance = balance;
	}

}

二、继承

1. 继承概述

  • 定义:继承表示类之间的一种 “is-a” 关系。
    • 例如:狗是一种动物,A is a B。
  • 语法
    class 子类类名 extends 父类类名 {}
    
  • 子类可以直接使用父类中定义的属性和方法。

2. 继承的优势

  • 继承体现了程序的复用性和可扩展性。

3. 方法的覆盖(重写 - override

  • 定义:子类中定义与父类中相同的方法。
  • 要求
    • 子类的方法名、形参列表、返回值类型必须与父类一致。
    • 子类的访问修饰符与父类相同或更宽。
  • 优先级:子类覆盖的方法优先于父类的方法。
  • 注意
    • 如果子类方法名和形参列表与父类相同但返回值类型不同,则编译报错。
    • 如果子类方法名相同但形参列表不同,则构成方法的重载,编译和运行均通过。

4. Java中的继承特点

  • 一个父类可以有多个直接子类。
    class Animal {}
    class Dog extends Animal {}
    class Cat extends Animal {}
    
  • 一个子类只能有一个直接父类,但可以有多个间接父类(多级继承),Java 中的类是单继承的。

5. 访问修饰符

  • 定义:访问修饰符表示一种访问权限。

  • Java 中的访问修饰符

    • private:私有的
    • default:默认的(无修饰符)
    • protected:受保护的
    • public:公开的
  • 访问权限

    修饰符本类同包非同包子类其他
    private
    default
    protected
    public
  • 继承性

    • private 修饰的属性和方法不能被继承。
    • default 修饰的属性和方法,同包子类允许继承。
    • protected 修饰的属性和方法,同包和非同包子类都允许继承。
    • public 修饰的属性和方法,所有子类都可以继承。

6. super 的应用

1. super. 用法
  • 定义:在子类方法中,super. 表示访问父类的属性或成员方法。
  • 语法
    super.属性名;
    super.成员方法名(实参);
    
2. super() 用法
  • 定义:在创建子类对象时,JVM 默认创建一个父类对象,并使用父类的无参数构造方法。
  • 语法
    super();
    super(实参);
    
  • 注意
    • super()super(实参) 应用在子类构造方法的第一行有效语句。
    • 如果子类构造方法的第一行没有指定 super()super(实参),则默认添加 super()
    • super本质上就是一个存储了当前对象的父类对象的地址值的特殊变量

三、多态

1. 多态概述

  • 定义:父类型的引用可以存储不同子类型的对象。
  • 语法
    父类类名 引用名 = new 子类类名();
    
  • 使用:使用父类型的引用调用属性或方法时,只能调用父类中定义的属性和方法。
  • 覆盖方法:如果子类覆盖了父类中的方法,则优先使用子类的覆盖方法。

2. 引用之间的转换

1. 父类型转子类型
  • 语法
    子类类名 引用名 = (子类类名)父类型的引用名;
    
  • 结果
    • 实际存储的对象类型和要转换的类型一致,编译和运行通过。
    • 实际存储的对象类型和要转换的类型不一致,编译通过,运行报错 java.lang.ClassCastException(类型转换异常)。
2. 子类型转父类型
  • 语法
    父类型的引用名 = 子类型的引用名;
    
  • 特点:无需强制类型转换,直接赋值,体现多态。
3. 无继承关系的类型转换
  • 限制:没有继承关系的类型之间不能相互赋值,强制类型转换也不允许。

3. instanceof 避免类型转换异常

  • 语法
    引用名 instanceof 类名
    
  • 执行:判断引用中存储的实际对象类型是否兼容于后面的类型,兼容返回 true,不兼容返回 false
  • 作用:在程序设计中避免类型转换异常。

示例代码

class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}

public class Test {
    public static void main(String[] args) {
        Animal a = null;
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        if (n % 2 == 0) {
            a = new Dog();
        } else {
            a = new Cat();
        }

        if (a instanceof Cat) {
            System.out.println("我是猫");
        } else {
            System.out.println("我不是猫");
        }
    }
}

4. 多态的应用

1. 多态在形式参数上的应用
  • 本类型和所有子类型的对象、引用都可以作为实际参数传递。
2. 多态在返回值上的应用
  • 本类型和所有子类型的对象、引用都可以作为返回值返回。

第九章:三个修饰符

一、abstract(抽象的)

1. abstract 修饰类

  • 定义:被 abstract 修饰的类称为抽象类。
  • 语法
    abstract class 类名 {}
    
  • 特点
    • 抽象类只能声明引用,不能创建对象。
    • 抽象类中可以定义属性、成员方法和构造方法。

2. abstract 修饰方法

  • 定义:被 abstract 修饰的方法称为抽象方法。
  • 语法
    访问修饰符 abstract 返回值类型 方法名(形参);
    
    • 注意:访问修饰符和 abstract 的顺序可以互换。
  • 特点
    • 抽象方法只有声明部分,没有方法的实现。
    • 抽象方法只能定义在抽象类中。

3. 抽象类与子类

  • 语法
    class 子类名 extends 抽象类名 {}
    
  • 特点
    • 子类如果不想成为抽象类,则必须覆盖父类中所有的抽象方法。

示例代码

abstract class Animal {
    abstract void makeSound();
}

class Dog extends Animal {
    void makeSound() {
        System.out.println("汪汪汪_(:з」∠)_");
    }
}

public class Test {
    public static void main(String[] args) {
        Animal myDog = new Dog();
        myDog.makeSound(); // 输出: Woof
    }
}

二、static(静态的)

1. static 修饰属性

  • 定义:被 static 修饰的属性称为静态属性、静态变量或类变量。
  • 语法
    static 数据类型 变量名;
    static 数据类型 变量名 = 值;
    
  • 特点
    • 静态变量基于类存在,被所有对象共享,与创建对象的数量无关。
  • 使用
    • 可以通过 对象.静态属性名 访问。
    • 可以直接通过 类名.静态属性名 访问。

2. static 修饰方法

  • 定义:被 static 修饰的方法称为静态方法。
  • 语法
    访问修饰符 static 返回值类型 方法名(形参) {}
  • 使用:直接通过 类名.静态方法名(实参) 调用。
  • 注意
    • 静态方法中只能访问本类的静态成员,不能直接访问本类的非静态成员。
    • 静态方法中不能使用 thissuper 关键字。

3. static 修饰代码块

  • 定义:被 static 修饰的代码称为静态代码块。
  • 位置:定义在类内、方法外。
  • 语法
    class 类名 {
        static {
            // 静态代码块内容
        }
    }
  • 作用:在类加载时,静态代码块按照属性定义的先后顺序完成对静态属性的初始化工作。
  • 类加载
    • JVM 第一次使用一个类时,通过 classpath 找到类对应的 .class 文件,读取该类的包名、类名、父类、属性、构造方法等信息,并将信息保存到 JVM 内存中,一个类进行一次类加载。
    • JVM 类加载的时机:
      • 第一次访问该类的静态成员。
      • 第一次创建该类对象时,先进行类加载,再完成对象的创建。
      • 子类加载时,先导致其父类加载。

示例代码

class MyClass {
    static int staticVar = 10;

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

    static void staticMethod() {
        System.out.println("静态方法调用");
    }
}

public class Test {
    public static void main(String[] args) {
        System.out.println(MyClass.staticVar); // 输出: 10
        MyClass.staticMethod(); // 输出: 静态方法调用
    }
}

三、final(最终的、不可变的)

1. final 修饰变量

  • 定义:被 final 修饰的变量在作用范围内是常量。
  • 语法
    final 数据类型 变量名;
    
  • 特点
    • 只允许一次赋值,不允许修改。
  • 注意:引用一旦被 final 修饰,代表引用中存储的对象不能更换。

2. final 修饰方法

  • 定义:被 final 修饰的方法允许子类继承,但不允许覆盖。

3. final 修饰类

  • 定义:被 final 修饰的类不允许被继承,没有子类。例如:SystemMath

示例代码

final class Constants {
    static final int MAX_VALUE = 100;
}

class Test {
    public static void main(String[] args) {
        System.out.println(Constants.MAX_VALUE); // 输出: 100
    }
}

思考:System.out.println() 实现原理

  • System:类
  • out:静态属性,对象类型
  • println():方法

为什么不效仿写一个呢?

public class PrintTest {
    public static void main(String[] args) {
        System.out.println("String Print Test");
        Console.log.print("String Print Test");
    }
}

class Print{
    public void print(String x){
        System.out.println(x);
    }
}

class Console{
    static Print log;
}

第十章:接口

一、了解接口

  1. 接口简介

    • 接口就像一份契约,规定了类应该实现的行为和方法。
    • 接口定义了一组方法的签名,但不提供具体实现。
    interface Animal {
        void makeSound(); // 抽象方法,无方法体
    }
    

二、实现接口

  1. 实现接口

    • 使用 implements 关键字来实现接口。
    • 实现类必须实现接口中定义的所有方法。
    class Dog implements Animal {
        @Override
        public void makeSound() {
            System.out.println("Dog barks"); // 实现抽象方法
        }
    }
    

三、接口间关系

  1. 接口继承

    • 接口支持多继承,一个接口可以继承多个父接口。
    • 类实现接口的同时可以继承父类,但接口实现必须在继承之后。
    interface Behaviour extends Animal {
        void eat(); // 新接口继承已有接口
    }
    

四、接口的特性

  1. 多态应用

    • 使用接口类型的引用可以指向不同实现类的对象,体现多态性。
    • 只能调用接口中定义的方法和属性。
    public class Main {
        public static void main(String[] args) {
            Animal animal = new Dog(); // 多态应用
            animal.makeSound(); // 调用接口方法
        }
    }
    

五、JDK新特性

  1. JDK8.0+

    • 提供默认方法和静态方法,使接口更灵活。
    interface Vehicle {
        default void start() {
            System.out.println("引擎启动了");
        }
    }
    
  2. JDK9.0+

    • 引入私有方法,用于接口内部代码重用。
    interface Person {
        private void breathe() {
            System.out.println("人在呼吸");
        }
    }
    

六、接口分类

  1. 常量接口:只包含静态常量,没有方法。

    interface Constants {
        // 常量的命名规范要全大写
        int MAX_VALUE = 100; // 静态常量
    }
    
  2. 标记接口:没有方法或属性,仅用于标记类的特性。

    interface Serializable {} // 标记接口
    
  3. 普通接口:包含至少一个抽象方法的接口。

    interface Logger {
        void log(String message); // 抽象方法
    }
    
  4. 函数式接口:只包含一个抽象方法,用于Lambda表达式。

    interface Calculator {
        int calculate(int x, int y); // 抽象方法
    }

综合示例

public class Test {
    public static void main(String[] args) {

        MyClass mc = new MyClass();

        IA ia = mc; // 多态
        ia.m1();

        IB ib = mc;
        ib.m2();

        IC ic = mc;
        ic.m1();
        ic.m2();
        ic.m3();
    }
}

interface IA{
    // 对于变量,如果什么都不写,Java会默认使用 public static final
    int a = 10;

    // 对于方法,如果什么都不写,Java会默认使用 public abstract
    void m1();
}

interface IB{
    void m2();
}

interface IC extends IA, IB{
    void m3();
}

interface ID{
    void m4();
}

class ClassA {
    public void m5(){
        System.out.println("m5 in Class A");
    }
}

class MyClass extends ClassA implements IC, ID{
    @Override
    public void m1() {
        System.out.println("m1 in MyClass");
    }

    @Override
    public void m2() {
        System.out.println("m2 in MyClass");
    }

    @Override
    public void m3() {
        System.out.println("m3 in MyClass");
    }

    @Override
    public void m4() {
        System.out.println("m4 in MyClass");
    }
}
public class Test {
    public static void main(String[] args) {
        IA ia = new MyInterImpl();
        ia.m1();
        System.out.println(ia.m2(1000));
        IA ia3 = new MyInterImpl3();
        ia3.m1();
        System.out.println(ia3.m2(1000));
    }
}

interface IA{
    void m1();
    boolean m2(int num);
}

class MyClass implements IA{
    @Override
    public void m1() {
        System.out.println("重写的方法m1");
    }

    @Override
    public boolean m2(int num) {
        if(num % 2 == 0){
            return true;
        }else{
            return false;
        }
    }
}

class MyInterImpl implements IA{

    @Override
    public void m1(){
        System.out.println("实现类");
    }
    
    @Override
    public boolean m2(int num) {
        if(num > 0){
            return true;
        }else{
            return false;
        }
    }
}

class MyInterImpl3 implements IA{
    @Override
    public void m1() {
        System.out.println("实现类3");
    }

    @Override
    public boolean m2(int num) {
        if(num > 100 && num % 2 != 0){
            return true;
        }else{
            return false;
        }
    }
}

十一章:理解内部类

一、初识内部类

  1. 什么是内部类

    • 在一个类的内部定义的类称为内部类。
    • 内部类具有独立的命名空间,可以访问外部类的所有成员。
    class Outer {
        class Inner {} // 内部类定义
    }
    

  2. 内部类分类

    • 成员内部类
    • 静态内部类
    • 局部内部类
    • 匿名内部类

二、匿名内部类

  1. 匿名内部类特点

    • 匿名内部类继承一个类或实现一个接口。
    • 只能创建一个对象,且类的定义与对象的创建同时完成。
    public class Test2 {
        public static void main(String[] args) {
            IA ia = new IA() { // 匿名内部类
                public void m1() {
                    System.out.println("m1...");
                }
    
                public int m2(int a) {
                    int sum = 0;
                    for (int i = 1; i <= a; i++) {
                        sum += i;
                    }
                    return sum;
                }
            };
            ia.m1();
            int r = ia.m2(45);
            System.out.println("r=" + r);
        }
    }
    
    interface IA {
        void m1();
    
        int m2(int a);
    }
    

三、Lambda表达式

  1. Lambda表达式

    • 用于简化函数式接口的使用,只能应用在函数式接口上。
    • 语法:(参数) -> { 方法体 }
    interface Calculator {
        int calculate(int x, int y); // 函数式接口
    }
    
    public class Main {
        public static void main(String[] args) {
            Calculator add = (x, y) -> x + y; // Lambda表达式
            int result = add.calculate(3, 5);
            System.out.println("Result: " + result);
        }
    }
    
  2. Lambda细节

    • 当方法体只有一行语句时,大括号 {} 可省略。
    • 参数类型可省略。
    • 当方法体只有一行 return 语句时,大括号 {}return 可一起省略。

综合示例

public class Test {
    public static void main(String[] args) {
        
        IB ib1 = () ->{
            System.out.println("方法的实现");
        };

        ib1.m1();

        // 当{}中有且只有一行语句时,{}可以省略
        IB ib2 = ()-> System.out.println("方法的实现2");
        ib2.m1();

        IC ic1 = (int a) -> System.out.println("a=" + a);
        ic1.m2(1);

        // 小括号中的数据类型是可以省略的
        IC ic2 = (x) -> System.out.println("x=" + x);
        ic2.m2(5);

        ID id1 = (x, y) -> {
           return x + y;
        };
        System.out.println(id1.m3(3, 5));


        // 只有一行语句且只有return语句,则return也可以省,而且要省需要一起省,不然就一个都不能省
        ID id2 = (x, y) -> x + y;
        System.out.println(id2.m3(1, 2));
    }
}

interface IB{
    void m1();
}

interface IC{
    void m2(int a);
}

interface ID{
    int m3(int a, int b);
}
public class Test {
    public static void main(String[] args) {
        IB ib1 = (a, b) -> a + b > 100 ? true : false;
        System.out.println(ib1.selectResult(199, -100));

        IB ib2 = (a, b) -> (a % 2 == 0 && b % 2 == 0) ? true : false;
        System.out.println(ib2.selectResult(101, 102));
    }
}

interface IB{
    boolean selectResult(int a, int b);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值