Java 是由 Sun Microsystems 公司于 1995 年 5 月推出的高级程序设计语言。

Java 可运行于多个平台,如 Windows, Mac OS 及其他多种 UNIX 版本的系统。

目录

java特点

简单、面向对象、分布式、健壮、安全、体系结构中立、可移植、解释型、高性能、多线程、动态

环境搭建

版本选择

选择LTS版本

Java 8是一次重大的发行版更新,引入了大量新特性和改进。其中最为显著的是Lambda表达式的引入,它允许在代码中直接定义匿名函数,大幅简化了函数的编写,并提升了效率。此外,Java 8还新增了Stream API,使得开发者可以更方便地进行流式操作。Date/Time API的改进也为日期和时间的处理提供了更多的便利。同时,Java 8还在接口中添加了默认方法和函数式接口的概念,以及方法引用(::)和Optional容器类型等特性。

Java 17则主要关注在Java语言和Java虚拟机的性能和安全性方面的改进。其中一个重要的变化是Switch表达式的增强,支持Lambda表达式和块语句,这使得Switch语句的功能更加强大和灵活。此外,Java 17还改进了类型推断机制,允许在Lambda表达式和匿名内部类中使用var关键字,进一步提升了代码的简洁性和可读性。

至于Java 21,作为自JDK17之后的新的LTS版本,也带来了许多新特性。其中包括switch模式匹配、字符串模板、顺序集合、记录模式(Record Patterns)、未命名类和实例的main方法(预览版)以及虚拟线程等。这些新特性进一步增强了Java的编程能力和应用范围。

总的来说,从Java 8到Java 17再到Java 21,每个版本都在不断地优化和改进,为开发者提供了更加高效、安全和灵活的编程环境。具体选择哪个版本进行学习或开发,需要根据项目的实际需求和个人的技术水平进行权衡。

步骤

macos端2024/3/29测试,官网直接安装Jdk即可,自动配置环境变量

安装链接(jdk21 for Mac):

https://www.oracle.com/cn/java/technologies/downloads/#jdk21-mac

相关命令

查看java版本:

java -version
ShellScript

列出所有安装的 JDK 版本及其路径:

/usr/libexec/java_home -V
ShellScript

查看JAVA_HOME 环境变量:

echo $JAVA_HOME
ShellScript

检查 PATH 环境变量中是否包含了 JDK 的 bin 目录:

echo $PATH
ShellScript

卸载jdk:

sudo rm -rf /Library/Java/JavaVirtualMachines/jdk1.8.0_XXX.jdk
ShellScript

删除 Java Web 插件和相关的缓存文件

sudo rm -rf /Library/Internet\ Plug-Ins/JavaAppletPlugin.plugin 
sudo rm -rf /Library/Application\ Support/Oracle/Java
ShellScript

运行

编辑源文件:hello.java

编译:Javac hello.java(运行后新增hello.class,为编译后的字节码文件)

java hello(将hello.class文件放到虚拟机JVM里运行,执行hello类)

ps:

1、public类有且唯一,其他类不限,文件名必须是public类名

2、每个类单独生成一个.class编译文件

基础语法

注释

单行

//abc
Java
/*abc*/
Java

文档注释

/** * 这是一个文档注释示例
 * 它通常包含有关类、方法或字段的详细信息
 */
public class MyClass {
       // 类的成员和方法
}
Java

通常出现在类、方法、字段前,用于生成代码文档,可以被javadoc工具解析提取生成为api文档

javadoc -d 目的文件夹名 -javadoc标签1  - Javadoc标签2  ……  源文件名.java
Java

简单的例子:

/**
 * 我是主说明
 *
 * @author buer
 * @version 1.0
 */
public class hello {
    /**
     * 默认构造器,虽然在这个只包含静态方法的类中不会被使用,但为了消除警告而显式定义。
     */
    public hello() {
        // 这里没有特殊的初始化代码,因为类只包含静态方法
    }

    /**
     * 主方法,程序的入口点
     *
     * @param args 命令行参数数组
     */
    public static void main(String[] args) {
        System.out.println("hello,java");
    }
}
Java

转义符

\t   对齐
\n   换行
\\   \
\"   "
\'   '
\r   回车
Java

关键字

保留字不能用于常量、变量、和任何标识符的名称

class
public公共的
default默认的
new创建
static静态
更多查询:https://www.runoob.com/java/java-basic-syntax.html

标识符

定义

Java 所有的组成部分都需要名字。类名、变量名以及方法名都被称为标识符

规则

1、以字母(A-Z 或者 a-z),美元符($)、或者下划线(_)开始

2、不是关键字

3、大小写敏感

ps

还有字面常量null、false、ture,不是关键字,也不能作为标识符

变量

规则

type identifier [ = value][, identifier [= value] ...] ;
Java

类型 变量名 = 值(可用,号分隔多个同时声明的变量)

实例

int a, b, c;         // 声明三个int型整数:a、 b、c
int d = 3, e = 4, f = 5; // 声明三个整数并赋予初值
byte z = 22;    // 声明并初始化 z
String s = "runoob"; // 声明并初始化字符串 s
double pi = 3.14159; // 声明了双精度浮点型变量 pi
char x = 'x';        // 声明变量 x 的值是字符 'x'。
Java

局部变量

定义:

在方法、构造函数或块内部声明的变量

性质:

1、它们在声明的方法、构造函数或块执行结束后被销毁

2、局部变量在声明时需要初始化,否则会导致编译错误

public void Fun() {
    int localVar = 10; // 局部变量
    // ...
}
Java

实例变量

定义:

在类中声明,但在方法、构造函数或块之外

性质:

1、它们属于类的实例,每个类的实例都有自己的副本

2、如果不明确初始化,实例变量会被赋予默认值(数值类型为0,boolean类型为false,对象引用类型为null)

public class Fun {
    int instanceVar; // 实例变量
}
Java

静态变量(类变量)

定义:

类变量是在类中用 static 关键字声明的变量

性质:

1、它们属于类而不是实例

2、所有该类的实例共享同一个类变量的值

3、类变量在类加载时被初始化,而且只初始化一次

public class Fun {
    static int classVar; // 类变量
}
Java

参数变量

参数是方法或构造函数声明中的变量,用于接收调用该方法或构造函数时传递的值,参数变量的作用域只限于方法内部。

public void Fun(int a ){
        //在fangFa方法中,a就是参数变量
}
Java

总结:

public class Fun {
    // 成员变量
    private int instanceVar;
    // 静态变量
    private static int staticVar;

    public void method(int paramVar) {
        // 局部变量
        int localVar = 10;

        // 使用变量
        instanceVar = localVar;
        staticVar = paramVar;

        System.out.println("成员变量: " + instanceVar);
        System.out.println("静态变量: " + staticVar);
        System.out.println("参数变量: " + paramVar);
        System.out.println("局部变量: " + localVar);
    }

    public static void main(String[] args) {
        Fun v = new Fun();
        v.method(20);
    }
}
Java

运算符

算术运算符

操作符描述例子
+加法 – 相加运算符两侧的值A + B 等于 30
减法 – 左操作数减去右操作数A – B 等于 -10
*乘法 – 相乘操作符两侧的值A * B等于200
/除法 – 左操作数除以右操作数B / A等于2
取余 – 左操作数除以右操作数的余数B%A等于0
++自增: 操作数的值增加1B++ 或 ++B 等于 21
自减: 操作数的值减少1B– 或 –B 等于 19

关系运算符

运算符描述例子
==检查如果两个操作数的值是否相等,如果相等则条件为真。(A == B)为假。
!=检查如果两个操作数的值是否相等,如果值不相等则条件为真。(A != B) 为真。
检查左操作数的值是否大于右操作数的值,如果是那么条件为真。(A> B)为假。
检查左操作数的值是否小于右操作数的值,如果是那么条件为真。(A <B)为真。
>=检查左操作数的值是否大于或等于右操作数的值,如果是那么条件为真。(A> = B)为假。
<=检查左操作数的值是否小于或等于右操作数的值,如果是那么条件为真。(A <= B)为真。

位运算符

操作符描述例子
如果相对应位都是1,则结果为1,否则为0(A&B),得到12,即0000 1100
|如果相对应位都是 0,则结果为 0,否则为 1(A | B)得到61,即 0011 1101
^如果相对应位值相同,则结果为0,否则为1(A ^ B)得到49,即 0011 0001
按位取反运算符翻转操作数的每一位,即0变成1,1变成0。(〜A)得到-61,即1100 0011
<< 按位左移运算符。左操作数按位左移右操作数指定的位数。A << 2得到240,即 1111 0000
>> 按位右移运算符。左操作数按位右移右操作数指定的位数。A >> 2得到15即 1111
>>> 按位右移补零操作符。左操作数的值按右操作数指定的位数右移,移动得到的空位以零填充。A>>>2得到15即0000 1111

逻辑运算符

操作符描述例子
&&称为逻辑与运算符。当且仅当两个操作数都为真,条件才为真。(A && B)为假。
| |称为逻辑或操作符。如果任何两个操作数任何一个为真,条件为真。(A | | B)为真。
称为逻辑非运算符。用来反转操作数的逻辑状态。如果条件为true,则逻辑非运算符将得到false。!(A && B)为真。

赋值运算符

操作符描述例子
=简单的赋值运算符,将右操作数的值赋给左侧操作数C = A + B将把A + B得到的值赋给C
+ =加和赋值操作符,它把左操作数和右操作数相加赋值给左操作数C + = A等价于C = C + A
– =减和赋值操作符,它把左操作数和右操作数相减赋值给左操作数C – = A等价于C = C – A
* =乘和赋值操作符,它把左操作数和右操作数相乘赋值给左操作数C * = A等价于C = C * A
/ =除和赋值操作符,它把左操作数和右操作数相除赋值给左操作数C / = A,C 与 A 同类型时等价于 C = C / A
(%)=取模和赋值操作符,它把左操作数和右操作数取模后赋值给左操作数C%= A等价于C = C%A
<< =左移位赋值运算符C << = 2等价于C = C << 2
>> =右移位赋值运算符C >> = 2等价于C = C >> 2
&=按位与赋值运算符C&= 2等价于C = C&2
^ =按位异或赋值操作符C ^ = 2等价于C = C ^ 2
| =按位或赋值操作符C | = 2等价于C = C | 2

条件运算符(?:)

条件运算符也被称为三元运算符。

该运算符有3个操作数,并且需要判断布尔表达式的值。

该运算符的主要是决定哪个值应该赋值给变量。

variable x = (expression) ? value if true : value if false
Java

instanceof 运算符

该运算符用于操作对象实例,检查该对象是否是一个特定类型(类类型或接口类型)。

instanceof运算符使用格式如下:

( Object reference variable ) instanceof (class/interface type)
Java

如果运算符左侧变量所指的对象,是操作符右侧类或接口(class/interface)的一个对象,那么结果为真。

流程控制

条件判断(if……else)

  1. if 语句至多有 1 个 else 语句,else 语句在所有的 else if 语句之后。
  2. if 语句可以有若干个 else if 语句,它们必须在 else 语句之前。
  3. 一旦其中一个 else if 语句检测为 true,其他的 else if 以及 else 语句都将跳过执行。

选择结构(switch……case1:case2:……)

switch(expression){
    case value :
       //语句
       break; //可选
    case value :
       //语句
       break; //可选
    //你可以有任意数量的case语句
    default : //可选
       //语句
}
Java
  • switch 语句中的变量类型可以是: byte、short、int 或者 char。从 Java SE 7 开始,switch 支持字符串 String 类型了,同时 case 标签必须为字符串常量或字面量。
  • switch 语句可以拥有多个 case 语句。每个 case 后面跟一个要比较的值和冒号。
  • case 语句中的值的数据类型必须与变量的数据类型相同,而且只能是常量或者字面常量。
  • 当变量的值与 case 语句的值相等时,那么 case 语句之后的语句开始执行,直到 break 语句出现才会跳出 switch 语句。
  • 当遇到 break 语句时,switch 语句终止。程序跳转到 switch 语句后面的语句执行。case 语句不必须要包含 break 语句。如果没有 break 语句出现,程序会继续执行下一条 case 语句,直到出现 break 语句。
  • switch 语句可以包含一个 default 分支,该分支一般是 switch 语句的最后一个分支(可以在任何位置,但建议在最后一个)。default 在没有 case 语句的值和变量值相等的时候执行。default 分支不需要 break 语句。

循环结构

while

while( 布尔表达式 ) {
  //循环内容
}
Java

只要布尔表达式为 true,循环就会一直执行下去。

do while

对于 while 语句而言,如果不满足条件,则不能进入循环。但有时候我们需要即使不满足条件,也至少执行一次。

do…while 循环和 while 循环相似,不同的是,do…while 循环至少会执行一次。

do {
       //代码语句
}while(布尔表达式);
Java

布尔表达式在循环体的后面,所以语句块在检测布尔表达式之前已经执行了。 如果布尔表达式的值为 true,则语句块一直执行,直到布尔表达式的值为 false。

for

for(初始化; 布尔表达式; 更新) {
    //代码语句
}
Java
  • 最先执行初始化步骤。可以声明一种类型,但可初始化一个或多个循环控制变量,也可以是空语句。
  • 然后,检测布尔表达式的值。如果为 true,循环体被执行。如果为false,循环终止,开始执行循环体后面的语句。
  • 执行一次循环后,更新循环控制变量。
  • 再次检测布尔表达式。循环执行上面的过程。

for增强

Java5 引入了一种主要用于数组的增强型 for 循环。

Java 增强 for 循环语法格式如下:

for(声明语句 : 表达式)
{
   //代码句子
}
Java

声明语句:声明新的局部变量,该变量的类型必须和数组元素的类型匹配。其作用域限定在循环语句块,其值与此时数组元素的值相等。

表达式:表达式是要访问的数组名,或者是返回值为数组的方法。

break

break 主要用在循环语句或者 switch 语句中,用来跳出整个语句块。

break 跳出最里层的循环,并且继续执行该循环下面的语句。

continue

continue 适用于任何循环控制结构中。作用是让程序立刻跳转到下一次循环的迭代。

在 for 循环中,continue 语句使程序立即跳转到更新语句。

在 while 或者 do…while 循环中,程序立即跳转到布尔表达式的判断语句。

数组

规则

  • 引用数据类型
  • 创建后,在内存中开辟一整块固定连续的空间,长度不可变
  • 初始化后数组元素默认值:整形0、浮点型0.0、字符型0、布尔型false、引用型null
  • 内存解析,栈>指针>堆
一维数组
import java.util.Arrays;

public class MyCommons {
    public static void main(String[] args) {
        //静态初始化
        //int[] arr;
        //arr=new int[]{1,2,3,4};
        int[] arr=new int[]{1,2,3,4};//简写
        //动态初始化
        int[] arr2=new int[4]
        
        //System.out.printf(arr);直接输出会隐式调用tostring方法,输出乱码(类型简写和数值哈希值)
        System.out.println(Arrays.toString(arr));
    }
}
Java
二维数组

一位数组的元素是数组

int[][] arr=new int[][]{{1,2,3},{4,5,6},{7,8,9},{10,11,12}}
arr[0][1]//第一项的第二个,2
Java
动态数组
import java.util.ArrayList; // 导入ArrayList类

ArrayList<String> myList = new ArrayList<String>();//字符型数组
ArrayList<Integer> myList = new ArrayList<Integer>();//整型数组
ArrayList<Integer> myList = new ArrayList<>();
//在Java 7及以上版本中,可以使用菱形操作符(<>)来代替显式类型实参

myList.add(1); // 向ArrayList中添加元素
Java

处理数组

public class MyCommons {
    public static void main(String[] args) {
        int[] arr=new int[]{1,2,9,4,0,7,6,4,6,8};
        int num=0;//最小值arr[0]
        for(int i=0;i<arr.length;i++){
            //最大值
            //if(arr[i]>num){
            //  num=arr[i];
            //}
            //最小值
            //if(arr[i]<=num){
            // num=arr[i];
            //}
            num+=arr[i];//和
            //反转:i<arr.length/2   arr[i]<->arr[arr.length-1-i]
        }
        System.out.println(num);
        //System.out.println((double)num/arr.length);平均值
    }
}
Java

Arryes工具类

add():将指定的元素添加到此列表的末尾。
ArrayList<String> list = new ArrayList<>();  
list.add("Apple");  
list.add("Banana");

add(int index, E element):在列表的指定位置插入指定的元素。
ArrayList<String> list = new ArrayList<>();  
list.add("Apple");  
list.add("Banana");  
list.add(1, "Orange"); // 插入后列表为 ["Apple", "Orange", "Banana"]

remove(int index):删除列表中指定位置的元素。
ArrayList<String> list = new ArrayList<>();  
list.add("Apple");  
list.add("Banana");  
list.remove(0); // 删除后列表为 ["Banana"]

get(int index):返回列表中指定位置的元素。
ArrayList<String> list = new ArrayList<>();  
list.add("Apple");  
list.add("Banana");  
String fruit = list.get(0); // fruit 将被赋值为 "Apple"

size():返回列表中的元素个数。
ArrayList<String> list = new ArrayList<>();  
list.add("Apple");  
list.add("Banana");  
int size = list.size(); // size 将被赋值为 2

contains(Object o):判断列表中是否包含指定的元素。
ArrayList<String> list = new ArrayList<>();  
list.add("Apple");  
list.add("Banana");  
boolean hasApple = list.contains("Apple"); // hasApple 将被赋值为 true

Collections.sort 数组排序
import java.util.ArrayList;  
import java.util.Collections;  
  
public class Main {  
    public static void main(String[] args) {  
        ArrayList<Integer> numbers = new ArrayList<>();  
        numbers.add(3);  
        numbers.add(1);  
        numbers.add(2);  
          
        Collections.sort(numbers);  
          
        for (int num : numbers) {  
            System.out.print(num + " ");  
        } // 输出:1 2 3  
    }  
}
Java

练习

100内的质数

import java.util.ArrayList;//引入类

public class ZhiShu {
    public static void main(String[] args) {
       ArrayList<Integer> myList = new ArrayList<>();//声明动态整数数组
        for(int a=2;a<=100;a++){//遍历2-100
            boolean n=true;//标识
            for(int b=2;b<a;b++){//遍历并比较2-a之间
                if(a%b==0){
                    n=fasle;//不是质数就更改标识
                    break;
                }
            }
            if(n){
                myList.add(a);//给数组添加元素
            }
        }
        System.out.println(myList);//输出
    }
}
Java

简单记账

import java.util.Scanner;

public class JiZhang {
    private double balance;
    public void addFun(double num){//收入方法
        balance+=num;
        System.out.printf("收入"+num+"元,当前余额:"+balance);
    }
    public void subFun(double num){//支出方法
        balance=balance-num;
        System.out.printf("支出"+num+"元,当前余额:"+balance);
    }
    public void cxFun(){//查询方法
        System.out.printf("当前余额:"+balance);
    }
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        JiZhang jiZhangInstance = new JiZhang(); // 创建JiZhang类的实例
        boolean sta=true;
        while (sta){
            System.out.print("记账系统\n1.查询余额\n2.收入\n3.支出\n4.退出");
            String sce=scanner.nextLine();
            switch (sce){
                case "1":
                    jiZhangInstance.cxFun();
                    break;
                case "2":
                    System.out.print("请输入收入金额:");
                    double income = scanner.nextDouble();
                    jiZhangInstance.addFun(income);
                    break;
                case "3":
                    System.out.print("请输入支出金额:");
                    double expense = scanner.nextDouble();
                    jiZhangInstance.subFun(expense);
                    break;
                case "4":
                    sta=false;
                    break;
                default: // 如果用户输入了无效的选择
                    System.out.println("无效的选择,请重新输入。");
            }
            scanner.nextLine(); // 消耗掉输入后的换行符
        }
    }
}
Java

面向对象编程

类及类的内部成员

属性、方法

public class Phone {//创建类
    String color = "红色";//设计类的属性
    public void Messages(String txt) {
    //设计类的方法,void指不需要方法返回,如果需要返回值,将void替换为返回值的数据类型,结尾return
    //方法必须在类里,不能独立存在
        System.out.printf("手机发出了一条短息,内容是:" + txt);
    }
}

public class PhoneText {
    public static void main(String[] args) {
        Phone iphone = new Phone();//初始化,创建类的对象(实例化)
        System.out.printf("外观:"+iphone.color);//通过创建的对象,调用其内部声明的属性和方法
        iphone.Messages("你好,对象");    }
}

Java

构造器

构造器(也称为构造函数)是一种特殊类型的方法,用于初始化对象的状态。当使用new关键字创建类的实例时,会自动调用构造器

规则:
权限修饰符 类名(形参列表){}
Java
例子:
public static void main(String[] args) {  
        // 使用无参构造器创建对象  
        Person person1 = new Person();  
        System.out.println(person1); // 输出: Person{name='Unknown', age=0}  
  
        // 使用带参构造器创建对象  
        Person person2 = new Person("Alice", 25);  
        System.out.println(person2); // 输出: Person{name='Alice', age=25}  
    } 
Java
  • 与类同名:构造器的名称必须与类名完全相同。
  • 没有返回类型:构造器没有返回类型,甚至不能是void
  • 自动调用:当你使用new关键字创建一个对象时,Java会自动调用该类的构造器。
  • 重载:一个类可以有多个构造器,只要它们的参数列表不同(这称为构造器的重载)。
  • 初始化:构造器通常用于初始化对象的属性或执行必要的设置。
作用:
  • 搭配上new创建对象
  • 初始化对象的成员变量

属性赋值

位置:

  • 默认初始化
  • 显式初始化
  • 构造器中初始化
  • 通过obj.Fun()赋值
  • 通过obj.name赋值

执行顺序:

1-2-3-4/5

代码块

//构造代码块:
{
    System.out.print("我是代码块");
}

//特点:优先于构造方法执行,每new一次就执行一次

//静态代码块
static{
  System.out.print("我是静态代码块");
}
//特点:优先于构造代码块和构造方法执行,只执行一次
Java

内部类

类里面的类

内部类访问外部类成员变量:
public class A{
  int a;//外部成员变量
  static class B{
  int b;//内部成员变量
    void Bfun(){
      this.b;//调用内部变量
      A.this.a;//调用外部变量
  }
}
Java
静态成员内部类
public class A{
  static class B{
    
  }
}

A.B name=new A.B()
Java
非静态成员内部类
public class A{
  class B{
    
  }
}

A.B name=new A().new B()
Java
局部内部类
public class A{
  void run(){
    class B{//局部内部类
      void eat(){}
    }
    new B().eat()//间接调用
  }
}

class Text{
  A name=new A();
  name.run();//调用
}
Java
匿名内部类
interface Greeting {  
    void sayHello();  
}  
  
public class Main {  
    public static void main(String[] args) {  
        //这里,创建了一个Greeting接口的匿名内部类实例,并覆盖了sayHello方法 
        Greeting greeting = new Greeting() {
            @Override  
            public void sayHello() {  
                System.out.println("Hello, World!");  
            }  
        };  
          
        // 调用匿名内部类实现的方法  
        greeting.sayHello();  
    }  
}
Java
包装类

Java包装类(Wrapper Classes)是Java提供的一种特殊类,它们将基本数据类型(如int, double, char等)包装为对象,使得基本数据类型可以像对象一样被操作。每个基本数据类型都有对应的包装类,如下所示:

  • byte 对应的包装类是 Byte
  • short 对应的包装类是 Short
  • int 对应的包装类是 Integer
  • long 对应的包装类是 Long
  • float 对应的包装类是 Float
  • double 对应的包装类是 Double
  • char 对应的包装类是 Character
  • boolean 对应的包装类是 Boolean

包装类的主要用途有:

  1. 作为集合类元素:Java集合类(如ArrayList, HashSet等)只能存储对象,不能存储基本数据类型。因此,当我们需要将基本数据类型存储到集合中时,就需要使用对应的包装类。
  2. 提升基本数据类型的操作能力:包装类提供了一系列方法,用于对基本数据类型进行各种操作,比如类型转换、比较大小等。
  3. 自动装箱和拆箱:Java 5.0之后引入了自动装箱和拆箱的特性,使得在基本数据类型和包装类之间转换时更加方便。例如,当我们将一个int值赋给一个Integer对象时,Java会自动进行装箱操作;当我们从一个Integer对象获取int值时,Java会自动进行拆箱操作。
枚举类
public enum Day{//使用enum关键字定义枚举类
  SUNDAY,  
  MONDAY,  
  TUESDAY,  
  WEDNESDAY,  
  THURSDAY,  
  FRIDAY,  
  SATURDAY
}

public class Main {  //使用
    public static void main(String[] args) {  
        Day today = Day.MONDAY;  
        switch (today) {  
            case MONDAY:  
                System.out.println("Today is Monday.");  
                break;  
            case TUESDAY:  
                System.out.println("Today is Tuesday.");  
                break;  
            // 其他情况的处理...  
            default:  
                System.out.println("Today is some other day.");  
        }  
          
        for (Day day : Day.values()) {  
            System.out.println(day);  
        }  
    }  
}
//在这个例子中,我们创建了一个Day类型的变量today,并将其设置为MONDAY。然后,我们使用switch语句根据today的值执行不同的操作。最后,我们使用for-each循环遍历Day枚举类的所有实例,并打印它们。
Java
  • 常量性:枚举类的实例在JVM中是唯一的,不能被实例化多次。
  • 类型安全:枚举常量具有类型信息,这使得它们在编译时就能进行类型检查。
  • 可遍历性:枚举类实现了java.lang.Enum接口,因此可以使用values()方法获取枚举类的所有实例,或者使用ordinal()方法获取实例在枚举声明中的位置。

面向对象的特征

封装

面向对象的开发原则要遵循:高内聚、低耦合

  • 内聚意味重用和独立。体现为类的内部数据操作细节自己完成,不允许外部干涉
  • 耦合意味多米诺效应、牵一发而动全身。体现为仅暴露少量的方法给外部使用,尽量方便外部调用
权限修饰符
  1. private
    • 私有的。只能被定义它的类本身访问。
    • 它是限制最严格的访问修饰符,用于隐藏类的内部实现细节。
    • 成员变量、方法、构造器、内部类都可以使用private修饰。
  2. default(默认,无修饰符)
    • 包内访问权限。无需任何关键字,只写成员变量名或方法名即可。
    • 它意味着该成员可以被同一个包内的其他类访问。
    • 如果不特别声明任何访问修饰符,则使用默认访问级别。
  3. protected
    • 受保护的。可以被同一个包内的其他类以及不同包中的子类访问。
    • 它提供了比默认访问级别稍宽的访问权限,常用于实现继承中的某些特性。
  4. public
    • 公共的。可以被任何类访问。
    • 它是访问级别最宽的修饰符,通常用于对外暴露类的API。

这些权限修饰符可以应用于类、接口、方法、变量等,但它们的使用场景和效果有所不同。例如:

  • 类和接口只能使用publicdefault(无修饰符)。
  • 成员变量、方法、构造器和内部类可以使用所有四种权限修饰符。
  • 局部变量不能使用访问权限修饰符(如publicprivateprotected)和非访问修饰符(如static)进行修饰,可以使用final修饰符。final修饰符用于修饰不可更改的变量,即该变量的值在初始化后不能被重新赋值。

在选择使用哪种权限修饰符时,应考虑封装性、继承性和安全性等因素。

通常,为了遵循良好的封装原则,应尽可能将成员变量设置为private

继承

规则
class 父类 {
}
 
class 子类 extends 父类 {
}
Java
类型
特点
  • 子类拥有父类非 private 的属性、方法。
  • 子类可以拥有自己的属性和方法,即子类可以对父类进行扩展。
  • 子类可以用自己的方式实现父类的方法。
  • Java 的继承是单继承,但是可以多重继承,单继承就是一个子类只能继承一个父类,多重继承就是,例如 B 类继承 A 类,C 类继承 B 类,所以按照关系就是 B 类是 C 类的父类,A 类是 B 类的父类,这是 Java 继承区别于 C++ 继承的一个特性。
  • 提高了类之间的耦合性(继承的缺点,耦合度高就会造成代码之间的联系越紧密,代码独立性越差)。
关键字
extends

默认

class 父类 {
}
 
class 子类 extends 父类 {
}
Java
implements

mplements 关键字可以变相的使java具有多继承的特性,使用范围为类继承接口的情况,可以同时继承多个接口(接口跟接口之间采用逗号分隔)

public interface A {
    public void eat();
    public void sleep();
}
 
public interface B {
    public void show();
}
 
public class C implements A,B {
}
Java
super和this

通过super关键字来实现对父类成员的访问,用来引用当前对象的父类

class Animal {
  void eat() {
    System.out.println("animal : eat");
  }
}
 
class Dog extends Animal {
  void eat() {
    System.out.println("dog : eat");
  }
  void eatTest() {
    this.eat();   // this 调用自己的方法
    super.eat();  // super 调用父类方法
  }
}
Java
final
  • final 可以用来修饰变量(包括类属性、对象属性、局部变量和形参)、方法(包括类方法和对象方法)和类。
  • final 含义为 “最终的”。
  • 使用 final 关键字声明类,就是把类定义定义为最终类,不能被继承,或者用于修饰方法,该方法不能被子类重写:
声明类:
final class 类名 {//类体}

声明方法:
修饰符(public/private/default/protected) final 返回值类型 方法名(){//方法体}
Java
构造器的继承
  • 子类是不继承父类的构造器(构造方法或者构造函数)的,它只是调用(隐式或显式)。如果父类的构造器带有参数,则必须在子类的构造器中显式地通过 super 关键字调用父类的构造器并配以适当的参数列表。
  • 如果父类构造器没有参数,则在子类的构造器中不需要使用 super 关键字调用父类构造器,系统会自动调用父类的无参构造器。
class SuperClass {
  private int n;
  SuperClass(){
    System.out.println("SuperClass()");
  }
  SuperClass(int n) {
    System.out.println("SuperClass(int n)");
    this.n = n;
  }
}
// SubClass 类继承
class SubClass extends SuperClass{
  private int n;
  
  SubClass(){ // 自动调用父类的无参数构造器
    System.out.println("SubClass");
  }  
  
  public SubClass(int n){ 
    super(300);  // 调用父类中带有参数的构造器
    System.out.println("SubClass(int n):"+n);
    this.n = n;
  }
}
Java

多态

方法的重写和重载
重写(override)

在子类存在方法与父类的方法的名字相同,而且参数的个数与类型一样,返回值也一样的方法

子类对继承过来的方法进行重写、覆盖

重载(overload)

一个类中定义了多个方法名相同,而他们的参数的数量不同或数量相同而类型和次序不同,

最常用的地方就是构造器的重载

  //以下两个参数类型顺序不同
    public String test(int a,String s){
        System.out.println("test3");
        return "returntest3";
    }   
 
    public String test(String s,int a){
        System.out.println("test4");
        return "returntest4";
    }   
Java
对象的多态性

父类类型的变量可以引用子类对象,并且可以在运行时确定实际调用的是哪个子类的方法

在Java中,当我们声明一个父类类型的引用变量并让它指向一个子类对象时,我们称之为向上转型(upcasting)。这种转型是安全的,因为子类对象包含父类所有的成员(包括属性和方法),所以父类引用可以访问子类对象中的这些成员。

然而,当我们通过这个父类引用调用一个被子类重写的方法时,实际执行的是子类中的方法,而不是父类中的方法。这种机制称为动态方法分派(dynamic method dispatch),它发生在运行时,Java虚拟机根据对象的实际类型来确定应该调用哪个方法。

public class duoTai {
    public static void main(String[] args) {
        Animal animal = new Dog(); // 向上转型:Animal引用指向Dog对象
        animal.makeSound(); // 输出 "777"

        //animal1.eat();无法直接运行
        Dog dog=(Dog)animal;//向下转型,将animal转换为Dog类型
        dog.eat();//888
    }
}
class Animal {
    public void makeSound() {
        System.out.println("666");
    }
}

class Dog extends Animal {
    public void makeSound() {  //重写了makeSound方法
        System.out.println("777");
    }
    void eat(){
        System.out.println("888");
    }
}
Java

在这个例子中,我们有一个Animal类以及两个子类DogCat。每个类都有一个makeSound方法,而DogCat类重写了这个方法以提供不同的行为。在main方法中,我们创建了两个Animal类型的引用animal1animal2,但分别让它们指向DogCat对象。当我们调用makeSound方法时,实际执行的是相应子类中的方法,这体现了多态性。

这种多态性让代码更加灵活,因为我们可以在不改变Animal类代码的情况下添加新的子类并实现新的行为。同时,这也允许我们在不知道具体子类类型的情况下处理对象,只要它们都是某个父类的类型。

抽象

抽象方法
  • 使用abstract修饰的方法,没有方法体,只有声明
  • 定义一种规范,告诉子类必须要给该方法提供具体的实现
抽象类

包含抽象方法的类

可以做到严格限制子类设计,子类间更通用

public class chouXiang extends Animal02{
    public void run(){//必须调用,不然会报错
        
    }
    public static void main(String[] args) {
        
    }
}
abstract class Animal02{
    int age;
    public abstract void run();
    public void eat(){
        System.out.print("eat");
    }
}
Java

使用要点

  1. 有抽象方法的类只能定义成抽象类
  2. 抽象类不能实例化,即不能用 new 来实例化抽象类。
  3. 抽象类可以包含属性、方法、构造方法。但是构造方法不能用来 new 实例,只能用来被子类调用。
  4. 抽象类只能用来被继承。
  5. 抽象方法必须被子类实现

其它关键字的使用

接口

一组规范,所有的类都要遵守

[权限修饰符] interface 接口名称 [extends 父类接口1,父类接口2] {
        // 定义常量
        // 抽象方法
}


interface Aanimal{//定义 动物 接口,抽象方法 跑 和 吃
    void run();
    void eat();
}

interface Cute{//定义 可爱 接口,抽象方法 看起来喜欢
    void looklike();
}

class Cat implements Aanimal,Cute{//猫类 实现 动物 和 可爱 接口,必须有 跑 和 吃 和 看起来喜欢方法
    public void run(){
        System.out.print("跑");
    }
    public void eat(){
        System.out.print("吃");
    }
    public void looklike(){
        System.out.print("看起来喜欢");
    }
}
Java
  • 权限修饰符只能是public或者默认
  • 接口名和类名相似
  • 接口可以多继承
  • 接口内只能定义常量,总是用public static final定义,不写也是
  • 接口内只能声明抽象方法,public abstract,不写也是
  • java8之后可以声明静态方法和默认方法,java9之后可以声明私有方法

object类

类似于js原型链,每个类的源头都默认继承object类

java.lang.Objact
Java
常用的方法

toString()
  • 常用程度:★★★★★
  • 用途:返回对象的字符串表示,通常用于调试和日志记录。
  • 规则:建议重写此方法以提供对象状态的简洁描述。默认实现返回类名、@符号和哈希码的组合。
equals(Object obj)
  • 常用程度:★★★★☆
  • 用途:判断两个对象是否相等。
  • 规则:通常需要重写此方法以比较对象的实际内容而非引用。重写时应遵循自反性、对称性、传递性和一致性等原则。
hashCode()
  • 常用程度:★★★★☆
  • 用途:返回对象的哈希码值,用于支持哈希表等数据结构的快速查找。
  • 规则:当重写equals方法时,通常也需要重写hashCode方法,以确保相等的对象具有相同的哈希码。
getClass()
  • 常用程度:★★★☆☆
  • 用途:获取对象所属类的Class对象,用于反射或类型检查等操作。
  • 规则:此方法返回表示该对象的运行时类的Class实例。通常不需要重写。

注解

  1. @Override
    • 作用:用于指示一个方法声明打算重写父类中的方法。如果方法签名与父类中的方法不一致,编译器会报错。
    • 示例:@Override public void myMethod() { ... }
  2. @Deprecated
    • 作用:用于标记一个已过时的方法或类。当其他代码使用这个已过时的方法或类时,编译器会发出警告。
    • 示例:@Deprecated public void myDeprecatedMethod() { ... }
  3. @SuppressWarnings
    • 作用:用于告诉编译器忽略指定的警告类型。这可以避免在编译时产生不必要的警告信息。
    • 示例:@SuppressWarnings("unchecked") public void myMethod() { ... }
  4. @FunctionalInterface
    • 作用:用于标记一个接口是函数式接口,即该接口只有一个抽象方法。这有助于编译器检查接口是否符合函数式接口的要求。
  5. @SafeVarargs
    • 作用:用于标记一个方法或构造函数使用了可变参数(varargs),并且不会产生类型安全问题。编译器会给出警告,但不会阻止使用。
  6. @Retention
    • 作用:用于指定注解的保留策略,即注解在什么时候生效。可能的值有SOURCE(仅保留在源码中,编译时丢弃)、CLASS(保留在class文件中,但JVM会忽略)和RUNTIME(保留在class文件中,且JVM会在运行时保留,因此可以通过反射读取)。
  7. @Documented
    • 作用:用于指定注解是否应被包含在JavaDoc文档中。
  8. @Inherited
    • 作用:用于指定注解是否可以被继承。如果一个类使用了某个带有@Inherited注解的注解,那么它的子类也会自动继承这个注解。
  9. @Repeatable
    • 作用:用于指定一个注解是否可以在同一个元素(如类或方法)上多次使用。这通常是通过定义一个容器注解来实现的。

单例模式

class BankTest{
  public static void main(String[] args){
    Bank name1=Bank.getfun();
  }
}

//饿汉式
class Bank{
  private Bank(){}//类构造器私有化
  private static Bank name=new Bank();//在类内部创建实例,也必须是static
  public static Bank getfun(){//使用方法获取实例,必须是static
   return name;
  }
}
//懒汉式
class Bank{
  private static Bank name=null;
  public static Bank getfun(){
    if(name==null){
      name=new Bank();
    }
    return name;
  }
}
Java

应用

异常处理

异常

这里的异常不是指代码编译后的报错

抛出机制

不同异常用不同的表示,一旦发生,创建该异常的对象并且抛出(throw),然后程序员捕获(catch)这个异常对象,如果没有捕获,会导致程序终止

体系结构

  • java.lang.Throwable
    • java.lang.Error 错误(一般不编写针对性代码处理):虚拟机无法解决的严重问题,如系统内部错误、资源耗尽等。
      • StackOverflowError
      • OutOfMenmoryError
    • java.lang.Exception 异常(可以编写代码处理):
      • 编译时异常(执行javac时,受检异常)
        • ClassNotFoundException
        • FileNotFoundException
        • IOException
      • 运行时异常(执行java时,非受检异常)
        • ArrayIndexOutOfBoundsException(数组角标越界)
        • NullPointerException(空指针)
        • ClassCastException
        • NumberFormatException
        • InputMismatchException
        • ArithmeticException

处理方式

try-chtch-finally(抓抛模型)
try{
  •••••//可能产生异常的代码
}catch(异常类型1 e){
  //当产生异常类型1型异常时的处置措施
  System.out.println("异常1原因: " + e.getMessage());
}catch(异常类型2 e){
  //当产生异常类型2型异常时的处置措施
  System.out.println("异常2详细信息: " + e.printStackTrace());
}finally{
  //无论是否发生异常,都无条件一定执行的语句
  //和直接在try-catch-finally结构下面直接写的不同,直接写的语句在有报错的情况下不会执行
  System.out.println("清理资源...");  
Java
throw+异常类型

当方法内部有代码可能抛出检查型异常,而该方法本身不处理这些异常时

public void Fun() throws 异常类型1, 异常类型2 {  
    //可能抛出异常的代码  
}
Java
class Parent {  
    public void doSomething() throws IOException {  
        // ... 可能抛出IOException的代码 ...  
    }  
}  
  
class Child extends Parent {  
    @Override  
    public void doSomething() throws FileNotFoundException { 
        // FileNotFoundException是IOException的子类  
        // ... 可能抛出FileNotFoundException的代码 ...  
    }  
}
Java

在这个例子中,Child类重写了Parent类的doSomething方法,并且声明它可能抛出一个更具体的异常FileNotFoundException,这是IOException的子类。这是合法的,因为子类方法不会比父类方法抛出更多类型的异常。如果子类方法尝试声明抛出与父类方法不相关的异常,编译器会报错。

自定义异常

除了Java内置的异常类,程序员还可以根据需要自定义异常类。自定义异常类通常继承自Exception或其子类。通过自定义异常,可以更好地描述和处理程序中的特定错误情况。

public class CustomException extends Exception {  
    public CustomException(String message) {  
        super(message);  
    }  
}  
  
// 使用自定义异常  
try {  
    throw new CustomException("自定义异常发生");  
} catch (CustomException e) {  
    System.out.println("捕获到自定义异常: " + e.getMessage());  
}
Java

多线程

创建线程

继承Thread类
public class MyThread extends Thread {  
    @Override  
    public void run() {  
        // 线程执行的代码  
        System.out.println("MyThread is running");  
    }  
  
    public static void main(String[] args) {  
        MyThread thread = new MyThread();  
        thread.start();  // 启动线程  
    }  
}
Java
  • void start()——开启线程
  • void run()——设置线程任务
  • String getName()——获取当前运行的线程名字
  • void setName(String name)——给线程设置名字
  • static Thread currentThread()——获取正在执行的线程对象
  • static void sleep(Long millis)——线程睡眠
  • ——————————————————————————————
  • void setPriority(int newPriority)——设置线程优先级(更容易优先,不是一定,newPriority默认5,最小1最大10)
  • int getPrioity()——获取线程优先级
  • void setDaemon(boolean on)——设置守护线程(伴随着被守护线程的结束而结束)
  • static void yield()——礼让线程,让当前线程让出cpu使用权(尽量平衡,交替执行)
  • void join()——插入线程 或 插队线程(a.join把线程a插到当前线程之前)
实现Runnable接口
public class MyRunnable implements Runnable {  
    @Override  
    public void run() {  
        // 线程执行的代码  
        System.out.println("MyRunnable is running");  
    }  
  
    public static void main(String[] args) {  
        Thread thread = new Thread(new MyRunnable());  
        thread.start();  // 启动线程  
    }  
}
Java

线程安全(同步)

synchronized修饰符

通过给方法或代码块加上synchronized修饰符,可以确保同一时间只有一个线程能够执行该方法或代码块。这有助于防止多个线程同时修改共享数据

//1-同步代码块
synchronized(锁对象){
  //线程可能出现不安全的代码
}
//锁对象:代表锁的一个对象,一般用this,指代当前对象实例,也就是调用这些方法的对象

//2-同步方法
修饰符 synchronized 返回值类型 方法名(){
  方法体
  return 结果
}
Java
线程状态
状态发生条件
NEW(新建)线程刚被创建,但是并未启动。还没调用start方法。
Runnable(可运行)线程可以在问虚拟机中运行的状态,可能正在运行自己代码,也可能没有,这取决于操作系统处理噐。
Blocked(锁阻塞)当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。
Waiting(无限等待)一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者notifyAl方法才能够唤醒。
Timed Waiting(计时等待)同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Jhread.sleep、 Object.wait.
Terminated(被终止)因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。或者调用过时方法stop()
wait()和notify()
  • sleep(time)和wait(time)有啥区别?
    • a.sleep(time);线程睡眠,在睡眠的过程中,线程是不会释放锁,此时其他线程抢不到锁,设置的时间一旦超时,自动醒来,继续执行 。
    • b.wait(time):线程等待,在等待的过程中会释放锁,其他线程就有可能抢到锁如果在等待的过程中被唤醒或者时间超时,会和其他的线程重新抢锁,如果抢到了继续执行,抢不到,锁阻塞。
  • wait()和notify():
    • a.wait():空参wait.线程进入到无限等待状态,会释放锁需要其他线程调用。notify()(一次唤醒一条等待的线程,唤醒是随机的)或者notifyAII方法(将所有等待线程全唤醒),被唤醒之后,会和其他的线程里新抢锁,抢到了,继续执行;抢不到,锁阻塞。
    • b.notify():notify会唤醒正在等待的线程,一次只能唤醒—条等待的线程;如果要是多条线程在等待,notify会随机一条唤醒;
    • c.notifyAII():晚醒所有等待的线程
  • wait和notify两个方法的用法:
    • 两个方法都需要锁对象调用,所以两个方法需要用到同步代码块,同步方法中
    • 两个方法必须是同一个锁对象调用
    • 可以理解为用同一个锁对象,将多条线程分到了一组中,这样notify就知道唤醒的是自己本组的等待线程
死锁

简单实例代码:

public class delLockText{
    final Object lock1=new Object();
    final Object lock2=new Object();

    public static void main(String[] args) {
        delLockText delLockText=new delLockText();

        Thread thread1=new Thread(delLockText.new Thread1());
        Thread thread2=new Thread(delLockText.new Thread2());

        thread1.start();
        thread2.start();
    }

    class Thread1 extends Thread{
        @Override
        public void run() {
            synchronized (lock1){
                System.out.println("Thread1获取lock1");
                synchronized (lock2){
                    System.out.println("Thread1获取lock2");
                }
            }
        }
    }
    class Thread2 extends Thread{
        @Override
        public void run() {
            synchronized (lock2){
                System.out.println("Thread2获取lock2");
                synchronized (lock1){
                    System.out.println("Thread2获取lock1");
                }
            }
        }
    }
}
Java
lock锁

主要方法和特点:

  • lock():获取锁。如果锁被其他线程持有,则当前线程将阻塞,直到获得锁。
  • tryLock():尝试获取锁,如果锁被其他线程持有,则立即返回false,不会阻塞当前线程。
  • unlock():释放锁。调用此方法的前提是当前线程持有该锁,否则会抛出IllegalMonitorStateException
  • tryLock(long time, TimeUnit unit):尝试获取锁,如果在指定的时间内没有获得锁,则返回false。
  • newCondition():返回与此锁关联的Condition实例,用于线程间的等待/通知机制。
import java.util.concurrent.locks.Lock;  
import java.util.concurrent.locks.ReentrantLock; 

Lock lock = new ReentrantLock(); 

public void increment() {  
        lock.lock();  
        try {  
            count++;  
        } finally {  
            lock.unlock();  
        }  
    }  
Java
Callable<V>接口
public class MyCS implements Callable<String>{
    @Override
    public String call() throws Exception {
        return “涛哥和金莲...的故事”;


public class Test {
    public static void main(Stringl] args){
          MyCS my_cs = new MyCS();
          //FutureTask (Callable<V> callable)
          FutureTask<String> futureTask = new FutureTask<>(my_cs);
          //创建Thread对象->Thread(Runnabletarget)
          Thread t1 = new Thread (futureTask);
          t1. start;
          //调用get方法获取ca11方法返回值
          System.out.println(futureTask.get);
    }
}
Java

v call()——设置线程任务,类似于Runable的run方法

  • 相同点:都是设置线程任务
  • 不同点:
    • call 有返回值,且有异常可以throws
    • run没有返回值,有异常不能throws
volatile关键字

volatile用于修饰变量,确保多线程对变量的操作具有可见性,即当一个线程修改了一个volatile变量的值,其他线程能够立即看到这个修改。

public volatile int sharedVariable = 0;
Java

线程池

  1. 创建线程对象:工具类-Executors
  2. 获取线程对象:Executors中的静态方法
    • static ExecutorService newFixedThreadPool(int nThreads)
    • 参数:指定线程池中最多创建的线程对象数量
    • 返回值ExecutorService时线程池,用来管理线程对象
  3. 执行线程任务:ExecutorService中的方法
    • Future<?> submit(Runnable task)提交一个runnable任务用于执行
    • Future<T> submit(Callable<T> task)提交一个callable任务用于执行
  4. submit方法的返回值:Future接口
    • 用于接收run或call方法返回值,但是run没有返回值,所以可以不用Future接收
    • Future有一个方法V get() 用于获取call返回值
  5. ExecutorService中的方法:
    • void shutdown()启动有序关闭,之前提交的任务执行,不会接受新任务
public class Text01 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executor_service= Executors.newFixedThreadPool(2);
        //MyRunnable
        executor_service.submit(new MyRunnable());
        //MyCallable
        Future future=executor_service.submit(new MyCallable());
        System.out.println(future.get());
        //关闭线程池
        executor_service.shutdown();
    }
}
//MyRunnable
public class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"线程,执行了");
    }
}
//Callable
public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "执行";
    }
}
Java

定时器Timer

构造:Timer()

方法:void schedule(TimerTask task,Date firstTime,long period)

  • task:抽象类,Runnable的实现类
  • firstTime:执行的起始时间
  • period:执行间隔(毫秒)
public class DemoOlTimer {
  public static void main (String[] args) {
    Timer timer = new Timer ();
    timer.schedule (new TimerTask {
      @Override
      public void run () {
        system.out.println"起床了~~~");
      }
    },new Date(),2000L);
  }
}
Java

集合

动态的容器

  • 单列集合:元素只有一个组成部分
  • 双列集合:元素有两个组成部分,key,value

接口

  1. Collection:这是集合框架的根接口,它定义了集合的基本操作,如添加、删除、检查元素是否存在等。
  2. List:有序的集合(元素可重复)。
  3. Set:无序的集合(元素不重复)。
  4. Queue:队列,一种特殊的线性表,它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作。
  5. Deque:双端队列,支持在两端插入和移除元素。
  6. Map:存储键值对的集合。

  1. ArrayList:基于动态数组实现的List。
  2. LinkedList:基于链表实现的List。
  3. HashSet:基于哈希表实现的Set。
  4. TreeSet:基于红黑树实现的Set,可以对元素进行排序。
  5. PriorityQueue:基于优先级堆的队列,元素根据其自然顺序或者创建的Comparator进行排序。
  6. ArrayDeque:基于数组实现的双端队列。
  7. HashMap:基于哈希表实现的Map。
  8. TreeMap:基于红黑树实现的Map,可以对键进行排序。
  9. LinkedHashMap:HashMap的子类,维护了一个运行于所有条目的双向链表。此链表定义了迭代顺序,通常是按照将元素插入到映射中的顺序(插入顺序)进行迭代。

Collection接口

定义

单列集合的顶级接口

使用:

创建:Collection<E> name=new 实现类对象<E>()

  • <E>泛型,决定集合中能存储什么类型的数据,可以统一元素类型
  • 泛型中只能写引用数据类型,如果不写默认object,什么类型都可以存储了
  • 等号前面的<>必须写,后面的可省略

常见方法:

  1. add(Object obj): 向集合中添加一个元素。
  2. addAll(Collection c): 将指定集合中的所有元素添加到此集合中。
  3. remove(Object obj): 从集合中移除一个元素。
  4. removeAll(Collection c): 移除集合c中的所有元素。
  5. retainAll(Collection c): 仅保留集合c中的元素,其他元素将被移除。
  6. clear(): 清空集合中的所有元素。
  7. contains(Object obj): 判断集合中是否包含元素obj。
  8. containsAll(Collection c): 判断集合中是否包含集合c中的所有元素。
  9. isEmpty(): 判断集合是否为空。
  10. size(): 获取集合中元素的个数。
  11. toArray(): 将集合转换为数组。

迭代器

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class iteratorCS {
    public static void main(String[] args) {
        //Collection<String> arr=new ArrayList<>();
        ArrayList<String> arr=new ArrayList<>();
        
        arr.add("001");
        arr.add("002");
        arr.add("003");
        arr.add("004");

        Iterator<String> iterator= arr.iterator();

        while (iterator.hasNext()){//检查集合中是否还有更多的元素           
             String t=iterator.next();//返回集合中的下一个元素
            //System.out.println(t);
            if("003".equals(t)){//匹配003并删除
                arr.remove("003");//从集合中删除上一次通过next()方法返回的元素
                System.out.println(arr);
            }
        }
        for(String i:arr){//for-each遍历
            //System.out.println(i);
        }
    }
}
Java

I0流

网絡编程

反射

新特性

其他常用api