java基础

1.jdk 是Java开发程序包

2.jre 是Java的运行时环境

3.jvm是java虚拟机,

4.常见的cmd命令 

cmd命令
cd切换目录
切换盘符是大写的盘符加上冒号
E:
D:
查看目录文件
dir
创建目录
mk  目录名
删除目录
rd  目录名
清除屏幕
cls
复制文件
copy 路径/文件名  路径/文件名
删除文件
del 文件名
测试网络是否畅通
ping ip(对应的ip地址)
查看网络连接状态
netstat -ano
查看
netstat -ano|find “.8”

 5.Java环境的安装

jdk的下载

java的环境变量的配置

6.java的工具

notepad++,idea

7.Java的语法

注释的作用用于解释对应的代码,在对应的编译不处理注释代码或者文字

8.Java的数据类型

基本数据类型 int,byte,char,long,double,float,boolean

引用数据类型string,

9.键盘录入的命令

导入scanner包

Scaner  sc = new Scanner(System.in);

int i = sc.nextInt()

10.运算符

运算符
算数运算符 加减乘除
自增自减运算符  ++,--
a++与++a 在左边是先赋值在++,在右边是先++在赋值
赋值运算符是= 将等号右边的赋值给左边
关系运算符是
大于小于,等于 
逻辑运算符
与或非  ! || &&
三元运算符  
String result = (condition) ? "条件为真" : "条件为假";
三元运算符的嵌套使用
int value = (condition1) ? ((condition2) ? value1 : value2) : value3;

11.数据类型的转换

对应的int 转为long,char,byte的使用

自动类型转换(隐式类型转换):当数据类型范围小的变量赋值给数据类型范围大的变量时,系统会自动进行类型转换。这种转换是安全的,不会导致数据丢失。
		
java

		
int numInt = 10;
double numDouble = numInt; // 自动将int类型转换为double类型

    
	
强制类型转换(显式类型转换):当数据类型范围大的变量赋值给数据类型范围小的变量时,需要进行强制类型转换。这种转换可能会导致数据丢失或溢出,因此需要进行显式的转换操作。
		
java

		
double numDouble = 10.5;
int numInt = (int) numDouble; // 强制将double类型转换为int类型,可能导致小数部分丢失

    
	
需要注意的是,在进行强制类型转换时,可能会导致数据精度丢失或溢出,因此需要谨慎使用。另外,对于不同数据类型之间的转换,需要遵循一定的规则:

从低精度到高精度的转换是安全的,系统会自动进行类型转换。
从高精度到低精度的转换可能会导致数据丢失,需要使用强制类型转换,并且可能需要进行范围检查。

 12.对应的+的使用

字符串连接
当 + 运算符用于两个字符串字面量或字符串对象时,它会执行字符串连接操作,返回一个新的字符串,其中包含了两个字符串的内容。

		
java

		
String str1 = "Hello, ";
String str2 = "World!";
String result = str1 + str2; // 结果是 "Hello, World!"

    
	
字符串与数值连接
如果 + 运算符用于字符串与数值(int、double 等)之间,Java 会自动将这些数值转换为字符串,然后再执行连接操作。

		
java

		
String numberStr = "Value is: ";
int number = 42;
String result = numberStr + number; // 结果是 "Value is: 42"

    
	
字符串与对象连接
当 + 运算符用于字符串与其他类型的对象时,对象会被调用 toString() 方法,该方法返回对象的字符串表示形式,然后再进行连接。

		
java

		
String objStr = "Object is: " + new Object(); // 调用 new Object() 的 toString() 方法

    
	
字符串连接的性能问题
需要注意的是,频繁使用 + 运算符进行字符串连接可能会导致性能问题。这是因为每次使用 + 连接字符串时,都会创建一个新的 String 对象,并且在连接过程中会复制原始字符串的内容。为了提高性能,建议使用 StringBuilder 或 StringBuffer 类来构建长字符串,这两个类提供了 append() 方法来高效地连接字符串。

		
java

		
StringBuilder sb = new StringBuilder();
sb.append("Hello, ");
sb.append("World!");
String result = sb.toString(); // 使用 toString() 方法获取最终的字符串

13.条件判断的语句

switch与if的使用

switch 语句
switch 语句用于根据变量的值来执行不同的代码块。它通常用于离散的值,例如整数、枚举或字符串。

		
java

		
int dayOfWeek = 3;
switch (dayOfWeek) {
    case 1:
        System.out.println("Monday");
        break;
    case 2:
        System.out.println("Tuesday");
        break;
    case 3:
        System.out.println("Wednesday");
        break;
    case 4:
        System.out.println("Thursday");
        break;
    case 5:
        System.out.println("Friday");
        break;
    case 6:
        System.out.println("Saturday");
        break;
    case 7:
        System.out.println("Sunday");
        break;
    default:
        System.out.println("Invalid day");
        break;
}

    
	
if 语句
if 语句用于根据条件判断执行不同的代码块。它可以处理任何类型的比较操作,包括等于、不等于、大于、小于等。

		
java

		
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 if (score >= 60) {
    System.out.println("D");
} else {
    System.out.println("F");
}

switch的case穿透

switch 语句中的“穿透”效应(也称为“fall-through”)是指当匹配到某个 case 后,如果没有 break 语句终止当前 case 的执行,程序将继续执行下一个 case 块的代码。

以下是一个包含穿透效应的 switch 语句的例子:

		
java

		
int number = 2;
switch (number) {
    case 1:
        System.out.println("Number is 1");
    case 2:
        System.out.println("Number is 2");
    case 3:
        System.out.println("Number is 3");
        break; // 添加break语句以避免穿透
    default:
        System.out.println("Number is not 1, 2, or 3");
}

// 输出:
// Number is 2
// Number is 3

    
	
在上述代码中,如果没有 break 语句,当 number 为 2 时,它将首先匹配到 case 2 并执行其后的代码。由于没有 break 语句来终止 case 2 的执行,程序会继续执行 case 3 的代码,即使 number 并不等于 3。

穿透效应在某些情况下可能是有用的,比如当多个 case 块需要执行相同的操作时。例如:

		
java

		
switch (dayOfWeek) {
    case 1:
    case 2:
    case 3:
        System.out.println("It's the weekend.");
        break;
    default:
        System.out.println("It's a weekday.");
}

 switch的简化写法

Java 12 引入了一个新的特性,允许使用简化写法的 switch 语句,它使得 switch 语句更加简洁和易于阅读。这种简化写法允许将 switch 表达式的值赋给一个变量,然后根据该变量的值来执行不同的代码块。

简化写法的语法
		
java

		
int dayOfWeek = 3;
switch (dayOfWeek) {
    case 1 -> System.out.println("Monday");
    case 2 -> System.out.println("Tuesday");
    case 3 -> System.out.println("Wednesday");
    case 4 -> System.out.println("Thursday");
    case 5 -> System.out.println("Friday");
    case 6 -> System.out.println("Saturday");
    case 7 -> System.out.println("Sunday");
    default -> System.out.println("Invalid day");
}

    
	
在这个例子中,每个 case 后面直接跟的是一个箭头 (->) 和一个代码块,该代码块包含了要执行的语句。

使用简化写法的优势
简洁性:这种写法使得 switch 语句更加简洁,特别是当每个 case 语句只有一行代码时。
可读性:对于简单的 switch 语句,这种写法可以提高代码的可读性。
注意事项
不能有多个语句:与传统的 switch 语句不同,简化写法中的每个代码块只能包含一个语句或表达式。
不能有 fall-through:简化写法不支持 break 语句,因为每个 case 后面的代码块后面都有一个隐式的 break。
只能使用单一变量:简化写法只能用于单一变量的 switch 表达式。
示例:使用简化写法处理枚举
		
java

		
enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

Day today = Day.WEDNESDAY;
switch (today) {
    case MONDAY, FRIDAY -> System.out.println("Workday");
    case SATURDAY, SUNDAY -> System.out.println("Weekend");
    default -> System.out.println("Invalid day");
}

14. 循环的使用

1. for 循环
for 循环是最常见的循环语句之一,它适用于已知循环次数的情况。

		
java

		
for (初始化; 条件; 迭代) {
    // 循环体
}

    
	
初始化:在循环开始前执行一次,通常用于设置循环计数器。
条件:在每次迭代开始前检查,如果条件为 true,则执行循环体;如果为 false,则退出循环。
迭代:在每次循环体执行后执行,通常用于更新循环计数器。
示例:打印从 1 到 5 的数字。

		
java

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

    
	
2. while 循环
while 循环适用于当条件成立时重复执行代码的情况。

		
java

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

    
	
条件:在每次迭代开始前检查,如果条件为 true,则执行循环体;如果为 false,则退出循环。
示例:打印从 1 到 5 的数字。

		
java

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

    
	
3. do-while 循环
do-while 循环至少执行一次循环体,然后检查条件是否成立。

		
java

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

    
	
条件:在每次循环体执行后检查,如果条件为 true,则继续执行循环;如果为 false,则退出循环。
示例:打印从 1 到 5 的数字。

		
java

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

    
	
使用循环的注意事项
避免无限循环:确保循环条件最终会变为 false 以避免无限循环。
循环变量更新:在循环体中更新循环变量,否则可能会导致逻辑错误或无限循环。
循环嵌套:循环可以嵌套在其他循环中,但要小心管理循环的嵌套深度,以避免代码难以理解和维护。

 死循环

循环(Infinite Loop)是一个在编程中无限重复执行的循环。当死循环发生时,程序会不断地执行相同的代码块,而不会按照预期退出循环。以下是一些导致死循环的常见原因和解决方案:

常见原因
条件永远为真:循环的条件始终为 true,没有变为 false 的机会。

		
java

		
while (true) {
    // 代码块
}

    
	
条件未更新:循环条件依赖于某个变量,但该变量在循环体内没有更新,导致条件始终为 true。

		
java

		
int i = 0;
while (i < 10) {
    // 代码块
    // i 没有增加,所以循环永远不会结束
}

    
	
条件计算错误:循环的条件计算有误,导致循环无法正常结束。

		
java

		
int i = 10;
while (i <= 10) { // 条件错误,因为 i 总是等于 10
    // 代码块
}

    
	
解决方案
检查循环条件:确保循环条件能够根据循环的执行情况适当地变为 false。

更新循环变量:在循环体内更新循环变量,以确保循环能够正常结束。

使用 break 语句:在循环体内使用 break 语句,当满足特定条件时跳出循环。

调试工具:使用调试工具来帮助定位和修复死循环。

示例
以下是一个死循环的示例及其解决方案:

死循环示例
		
java

		
int i = 0;
while (true) {
    System.out.println("This is a dead loop.");
    // 循环条件永远为 true,因此循环体将无限执行
}

    
	
解决方案
		
java

		
int i = 0;
while (true) {
    System.out.println("This is a dead loop.");
    if (i == 5) {
        break; // 当 i 等于 5 时,使用 break 语句退出循环
    }
    i++; // 更新循环变量
}

    
	
在这个解决方案中,我们添加了一个 if 语句来检查 i 的值,并在达到某个条件时使用 break 语句退出循环。同时,我们更新了循环变量 i 来确保循环能够结束。

 15.数组

数组是编程中用于存储一系列相同类型数据的一种数据结构。在 Java 中,数组是固定大小的,一旦创建,其大小就不能改变。以下是数组的一些基本概念和使用方法:

数组的特点
固定大小:数组的大小在创建时确定,不能动态更改。
相同类型:数组中的所有元素必须是相同的数据类型。
索引访问:数组中的每个元素都有一个唯一的索引,从 0 开始。
创建和初始化数组
声明数组:使用数据类型后跟方括号 [] 来声明数组。
		
java

		
int[] numbers;

    
	
创建数组:使用 new 关键字创建数组实例。
		
java

		
numbers = new int[5]; // 创建一个包含 5 个整数的数组

    
	
初始化数组:可以在声明时直接初始化数组。
		
java

		
int[] numbers = {1, 2, 3, 4, 5}; // 创建并初始化一个包含 5 个整数的数组

    
	
访问和修改数组元素
使用索引访问数组元素,索引从 0 开始。
		
java

		
int firstElement = numbers[0]; // 获取第一个元素
numbers[2] = 10; // 设置第三个元素的值为 10

    
	
数组的方法
length 属性:返回数组的长度。
		
java

		
int arrayLength = numbers.length;

    
	
Arrays 类:Java 提供了 java.util.Arrays 类,其中包含各种操作数组的静态方法。
		
java

		
Arrays.fill(numbers, 0); // 将数组中所有元素设置为 0
Arrays.sort(numbers); // 对数组进行排序

    
	
数组的限制
固定大小:不能改变数组的大小,但可以添加额外的数组来存储更多的元素。
类型限制:数组必须是同一数据类型,不能存储不同类型的元素。
多维数组
Java 还支持多维数组,如二维数组、三维数组等。二维数组可以看作是数组的数组。

		
java

		
int[][] matrix = new int[3][4]; // 创建一个 3x4 的二维数组

    
	
多维数组中的每个元素可以通过两个索引来访问。

		
java

		
matrix[0][1] = 5; // 设置第一个数组中第二个元素的值为 5

    
	

16.Arrays的使用

在 Java 中,Arrays 类是 java.util 包的一部分,它提供了一系列静态方法来操作数组。以下是一些常用的 Arrays 类的方法及其用途:

1. fill 方法
fill 方法用于将一个数组中的所有元素设置为指定的值。

		
java

		
int[] array = new int[10];
Arrays.fill(array, 5); // 将数组中的所有元素设置为 5

    
	
2. sort 方法
sort 方法用于对数组中的元素进行排序。对于基本数据类型(如 int、double 等),Java 会使用双轴快速排序算法。对于对象数组,它使用合并排序算法。

		
java

		
Integer[] numbers = {3, 1, 4, 1, 5, 9};
Arrays.sort(numbers); // 对数组进行排序

    
	
3. binarySearch 方法
binarySearch 方法用于在排好序的数组中查找一个特定的元素。如果找到,返回元素的索引;如果没有找到,返回 -(插入点),其中插入点是元素应该被插入以保持数组排序的地方。

		
java

		
int[] numbers = {1, 2, 3, 4, 5};
int index = Arrays.binarySearch(numbers, 3); // 返回 2,因为 3 在索引 2 处

    
	
4. toString 方法
toString 方法用于返回数组的字符串表示形式。

		
java

		
int[] array = {1, 2, 3, 4, 5};
String arrayString = Arrays.toString(array); // 返回 "[1, 2, 3, 4, 5]"

    
	
5. clone 方法
clone 方法创建数组的一个副本。

		
java

		
int[] original = {1, 2, 3, 4, 5};
int[] cloned = original.clone(); // 克隆数组

    
	
6. equals 方法
equals 方法用于比较两个数组是否相等。

		
java

		
int[] array1 = {1, 2, 3};
int[] array2 = {1, 2, 3};
boolean areEqual = Arrays.equals(array1, array2); // 返回 true

    
	
7. hashCode 方法
hashCode 方法用于返回数组的哈希码。

		
java

		
int[] array = {1, 2, 3};
int hash = Arrays.hashCode(array); // 返回数组的哈希码

    
	
注意事项
Arrays 类的方法不适用于对象数组,除非它们是原始类型(如 Integer 而不是 int)或实现了 Comparable 接口并且数组的元素被排序。
对于对象数组,如果元素是自定义类,确保自定义类覆盖了 equals 和 hashCode 方法,以便 Arrays.equals 和 hashCode 可以正确工作。

17.方法

方法定义
一个方法由以下部分组成:

访问修饰符:例如 public、private、protected 或 default,用于控制方法的访问级别。
返回类型:表示方法返回值的类型,可以是任何有效的 Java 数据类型,包括 void(表示无返回值)。
方法名:遵循 Java 命名约定(通常是动词开头,小写字母)。
参数列表:包含方法参数(如果有),参数之间用逗号分隔,每个参数包含数据类型和变量名。
方法体:大括号 {} 内的代码块,包含方法的实际逻辑。
		
java

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

    
	
方法重载(Overloading)
方法重载允许你在同一个类中定义多个方法,只要它们的签名不同(方法名相同,但参数列表不同)。

		
java

		
public void printMessage(String message) {
    System.out.println(message);
}

public void printMessage(String message, int times) {
    for (int i = 0; i < times; i++) {
        System.out.println(message);
    }
}

    
	
方法重写(Overriding)
方法重写发生在子类中,当子类有一个与父类方法签名相同的方法时。子类的方法必须与父类的方法有相同的返回类型和参数列表。

		
java

		
class Parent {
    public void print() {
        System.out.println("Parent class");
    }
}

class Child extends Parent {
    @Override
    public void print() {
        System.out.println("Child class");
    }
}

    
	
方法参数
值传递(Pass-by-value):Java 中所有参数都是按值传递的。这意味着传递给方法的参数的副本被传递,而不是原始变量。
引用传递(Pass-by-reference):虽然 Java 本身不支持引用传递,但当传递的是对象引用时,实际上传递的是引用的副本,这个副本指向同一个对象。
方法的异常处理
使用 try 块捕获可能抛出异常的代码。
使用 catch 块处理捕获到的异常。
使用 finally 块(可选)执行任何必要的清理工作,无论是否发生异常。
		
java

		
public void divide(int a, int b) {
    try {
        int result = a / b;
        System.out.println("Result: " + result);
    } catch (ArithmeticException e) {
        System.out.println("Cannot divide by zero.");
    } finally {
        System.out.println("Division operation attempted.");
    }
}

    
	
方法的作用域
方法的访问修饰符决定了它可以在代码库的哪些部分被访问。
如果没有指定访问修饰符,则方法默认为包私有(default)。
方法在 Java 编程中扮演着核心角色,它们使得代码模块化、可重用,并有助于创建清晰和可维护的程序结构。

 18.方法重写与方法重载

方法重写(Overriding)
发生在子类中:子类继承自父类,并重写父类中的方法。
运行时多态:重写的方法在运行时根据对象的实际类型被调用。
必须具有相同的签名:重写的方法必须与父类中的方法具有相同的名字、返回类型和参数列表。
访问修饰符:重写的方法的访问修饰符不能比父类中方法的访问修饰符更低。例如,如果父类方法是 public,子类中重写的方法不能是 protected 或 private。
不能声明为 final 或 static:这些关键字修饰的方法不能被重写。
不能抛出比父类方法更多的异常:重写的方法可以抛出相同的异常或其子类的异常,但不能抛出新的异常。
		
java

		
class Parent {
    public void display() {
        System.out.println("Parent class display method");
    }
}

class Child extends Parent {
    @Override
    public void display() {
        System.out.println("Child class display method");
    }
}

    
	
方法重载(Overloading)
发生在同一个类中:同一个类中可以定义多个同名的方法,只要它们的参数列表不同。
编译时多态:方法重载在编译时通过参数列表来区分。
参数列表不同:重载的方法必须有不同的参数列表,包括参数的数量、类型或顺序。
返回类型可以不同:重载的方法可以有相同的返回类型,也可以不同。
没有访问修饰符的限制:重载的方法可以有不同的访问修饰符。
		
java

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

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

    
	
总结
重写用于继承和多态,确保子类以与父类兼容的方式实现方法。
重载用于在同一类中提供相同的方法名,但具有不同参数列表的多个变体,以提供更灵活的接口。

 19..二维数组

定义和初始化
二维数组可以通过以下方式定义和初始化:

		
java

		
// 定义一个二维数组
int[][] twoDimArray;

// 初始化一个二维数组
int[][] twoDimArray = new int[3][3]; // 创建一个3x3的二维数组

    
	
访问元素
要访问二维数组中的特定元素,可以使用两个索引:第一个索引表示行,第二个索引表示列。

		
java

		
int element = twoDimArray[rowIndex][columnIndex];

    
	
例如,twoDimArray[1][2] 将访问位于第二行第三列的元素。

遍历二维数组
可以通过嵌套循环来遍历二维数组:

		
java

		
for (int i = 0; i < twoDimArray.length; i++) {
    for (int j = 0; j < twoDimArray[i].length; j++) {
        // 访问或操作元素
    }
}

    
	
多维数组
二维数组可以视为一种特殊的多维数组,其中只有一个维度。如果需要,可以创建三维或更高维度的数组,通过在初始化时指定更多的尺寸。

		
java

		
int[][][] threeDimArray = new int[3][4][5]; // 创建一个3x4x5的三维数组

    
	
常用方法
length 属性:用于获取二维数组的行数或列数。
toString() 方法:用于返回二维数组的字符串表示形式。
		
java

		
System.out.println(twoDimArray.length); // 获取行数
System.out.println(twoDimArray[0].length); // 获取列数

System.out.println(Arrays.deepToString(twoDimArray)); // 获取二维数组的字符串表示

    
	
注意事项
对于多维数组,第一个维度的大小决定了数组的行数,后续的维度大小决定了每一行的列数。
在处理多维数组时,要注意索引的正确性,以避免数组越界异常。

20.数组的遍历方式

1. 使用 for 循环
使用传统的 for 循环可以遍历数组,并通过索引访问数组元素:

		
java

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

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

    
	
2. 使用增强型 for 循环(foreach 循环)
增强型 for 循环是 Java 5 引入的语法糖,用于遍历数组或集合,更简洁易读:

		
java

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

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

    
	
3. 使用 Arrays 类的 toString 方法
Arrays 类的 toString 方法可以将数组转换为字符串,并方便地打印出数组元素:

		
java

		
int[] array = {1, 2, 3, 4, 5};
System.out.println(Arrays.toString(array));

    
	
4. 使用 Arrays 类的 asList 方法
Arrays 类的 asList 方法可以将数组转换为 List,然后使用增强型 for 循环遍历:

		
java

		
int[] array = {1, 2, 3, 4, 5};
List<Integer> list = Arrays.asList(array);

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

    
	
5. 使用 Stream API
Java 8 引入的 Stream API 提供了函数式编程的方式来操作集合和数组。可以使用 Stream API 来遍历数组:

		
java

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

Arrays.stream(array).forEach(System.out::println);

    
	
注意事项
在遍历数组时,要确保索引不越界,避免 ArrayIndexOutOfBoundsException 异常。
选择合适的遍历方式取决于具体的需求和代码风格,可以根据情况选择最适合的方式来遍历数组。

21.面向对象

1. 封装(Encapsulation)
封装是将数据和操作这些数据的方法捆绑在一起的过程。在面向对象编程中,这通常通过创建类来实现,类是对象的蓝图。

属性(Attributes):类中的变量,代表对象的属性。
方法(Methods):类中的函数,定义了可以对该对象执行的操作。
通过将属性设置为私有(private),可以隐藏对象的内部状态,只通过公共(public)的方法来访问和修改它们,从而保护数据不被外部直接访问和修改。

		
java

		
public class BankAccount {
    private double balance;

    public BankAccount(double initialBalance) {
        balance = initialBalance;
    }

    public void deposit(double amount) {
        balance += amount;
    }

    public void withdraw(double amount) {
        if (amount <= balance) {
            balance -= amount;
        }
    }

    public double getBalance() {
        return balance;
    }
}

    
	
2. 继承(Inheritance)
继承允许一个类(子类)继承另一个类(父类)的特性。子类可以继承父类的属性和方法,也可以添加新的属性和方法。

单继承:Java 只支持单继承,即一个类只能有一个父类。
多态:通过继承,可以创建一个方法签名,不同的子类可以有不同的实现。
		
java

		
public class SavingsAccount extends BankAccount {
    private double interestRate;

    public SavingsAccount(double initialBalance, double interestRate) {
        super(initialBalance);
        this.interestRate = interestRate;
    }

    public void applyInterest() {
        double interest = getBalance() * interestRate / 100;
        deposit(interest);
    }
}

    
	
3. 多态(Polymorphism)
多态是指同一个方法在不同的对象上可以有不同的行为。它通过继承和接口来实现。

方法重写(Method Overriding):子类可以覆盖父类中定义的方法,以提供不同的实现。
接口(Interfaces):接口定义了方法签名,不包含实现,可以允许多态。
		
java

		
public interface Animal {
    void makeSound();
}

public class Dog implements Animal {
    public void makeSound() {
        System.out.println("Woof!");
    }
}

public class Cat implements Animal {
    public void makeSound() {
        System.out.println("Meow!");
    }
}

    
	
总结

22.类与对象

类(Class)
类是创建对象的蓝图或模板。它定义了对象的属性(数据)和方法(行为)。类包含以下元素:

属性(Attributes):类的属性,也称为字段或成员变量,它们存储了对象的状态信息。
方法(Methods):类的方法,也称为成员函数,定义了对象可以执行的操作。
构造函数(Constructors):用于创建对象实例的特殊方法,它们有相同的名字作为类名,没有返回类型。
例如:

		
java

		
public class Car {
    // 属性
    private String brand;
    private int year;

    // 方法
    public void start() {
        System.out.println("Car starts");
    }

    // 构造函数
    public Car(String brand, int year) {
        this.brand = brand;
        this.year = year;
    }
}

    
	
在这个例子中,Car 类定义了两个属性(brand 和 year)和一个方法(start),以及一个构造函数用于初始化这些属性。

对象(Object)
对象是类的实例。当我们使用类创建一个对象时,我们实际上是在创建这个类的特定实例。每个对象都有自己的状态和行为。

		
java

		
Car myCar = new Car("Toyota", 2020);

    
	
在这个例子中,myCar 是 Car 类的一个对象。通过调用构造函数 new Car("Toyota", 2020),我们创建了一个具有特定品牌和年份的 Car 对象。

关系
类是抽象的,定义了对象的结构和行为。
对象是具体的,是类的具体实例。
以下是对类和对象关系的总结:

一个类可以创建多个对象。
每个对象都是其类的一个实例。
对象可以访问其类中定义的方法和属性。
类的构造函数用于创建对象时初始化对象的状态。

23.标准的JavaBean

JavaBean 是一种符合特定规范的 Java 类,用于封装数据和提供访问和修改数据的方法。JavaBean 的命名规范和设计约定有助于在 Java 程序中创建可重用的组件。以下是标准的 JavaBean 的特征和规范:

特征
无参构造函数:JavaBean 必须提供一个无参构造函数,以便在实例化时使用。
属性:JavaBean 的属性应该是私有的,并通过公共的访问方法(getter 和 setter 方法)来访问和修改。
序列化:JavaBean 应该实现 Serializable 接口,以支持对象的序列化和反序列化。
事件:JavaBean 可以支持事件处理,通过添加事件监听器和触发事件。
规范
类名:类名应该使用驼峰命名法,并且首字母大写。
属性:属性应该是私有的,并且通过公共的 getter 和 setter 方法来访问和修改。
getter 和 setter 方法:getter 方法用于获取属性的值,setter 方法用于设置属性的值。
equals 和 hashCode 方法:通常建议重写 equals() 和 hashCode() 方法,以便正确比较对象的内容。
toString 方法:通常建议重写 toString() 方法,以便返回对象的易读字符串表示。
示例
以下是一个简单的 JavaBean 示例:

		
java

		
import java.io.Serializable;

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

    public Person() {
    }

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

    
	
在这个示例中,Person 类符合 JavaBean 的规范:拥有私有属性、公共的 getter 和 setter 方法,实现了 Serializable 接口,并重写了 toString() 方法。

通过遵循 JavaBean 的规范,可以使 Java 类更加模块化、可重用和易于维护,从而提高代码的质量和可读性。

24.基本数据类型与引用数据类型

基本数据类型(Primitive Data Types)
基本数据类型是 Java 语言内部定义的数据类型,它们是原生的,直接存储在栈(Stack)内存中。Java 中有 8 种基本数据类型:

byte:8位,有符号的整数类型,范围是 -128 到 127。
short:16位,有符号的整数类型,范围是 -32,768 到 32,767。
int:32位,有符号的整数类型,范围是 -2^31 到 2^31-1。
long:64位,有符号的整数类型,范围是 -2^63 到 2^63-1。
float:32位,单精度浮点数。
double:64位,双精度浮点数。
char:16位,Unicode 字符。
boolean:表示真(true)或假(false)。
引用数据类型(Reference Data Types)
引用数据类型不是直接存储值,而是存储对某个对象的引用。这意味着它们指向存储在堆(Heap)内存中的对象。引用数据类型包括:

类(Classes):自定义的复杂数据结构,如 String、ArrayList 等。
接口(Interfaces):定义了类应该实现的方法,如 Runnable、Comparable 等。
数组(Arrays):一组相同类型的数据集合,如 int[]、String[] 等。
关键区别
存储位置:基本数据类型存储在栈上,引用数据类型存储在堆上。
内存占用:基本数据类型占用的空间是固定的,而引用数据类型的大小取决于引用的对象。
null值:基本数据类型不能为 null,而引用数据类型可以。
复制:基本数据类型的变量复制是值复制,而引用数据类型的变量复制是引用复制。

基本数据类型的默认值

在 Java 中,基本数据类型在声明但没有被初始化时,会有默认的值。以下是每种基本数据类型的默认值:

byte、short、int 和 long:默认值为 0。
float 和 double:默认值为 0.0。
char:默认值为 '\u0000',即空字符。
boolean:默认值为 false。
这里有一些具体的例子来说明:

		
java

		
byte b; // 默认值为 0
short s; // 默认值为 0
int i; // 默认值为 0
long l; // 默认值为 0
float f; // 默认值为 0.0
double d; // 默认值为 0.0
char c; // 默认值为 '\u0000'
boolean bool; // 默认值为 false

    
	
在 Java 中,理解这些默认值是非常重要的,因为如果你在声明一个变量但没有显式初始化它,那么使用这个变量可能会导致不可预料的结果。例如,如果你尝试使用未初始化的 boolean 变量进行逻辑运算,可能会得到错误的结果,因为它的默认值是 false。

25.this与super

this
this 关键字用于引用当前对象实例。以下是一些使用 this 的常见情况:

区分局部变量和成员变量:当局部变量和成员变量名称相同时,可以使用 this 来指定使用的是对象的哪个成员变量。

		
java

		
public class Example {
    private int x;

    public void setX(int x) {
        this.x = x; // 使用 this 指向类的成员变量
    }
}

    
	
调用当前对象的构造函数:在类的构造函数中,可以使用 this() 来调用同一个类中的另一个构造函数。

		
java

		
public class Example {
    private int x;

    public Example() {
        this(0); // 调用同一个类中参数为 0 的构造函数
    }

    public Example(int x) {
        this.x = x;
    }
}

    
	
返回当前对象引用:this 可以用来返回当前对象的引用,这在调用对象的非静态方法时特别有用。

		
java

		
public class Example {
    public Example getNext() {
        return this; // 返回当前对象的引用
    }
}

    
	
super
super 关键字用于引用当前对象的父类(超类)。以下是一些使用 super 的常见情况:

调用父类构造函数:在子类构造函数中,可以使用 super() 来调用父类的无参构造函数。如果父类没有无参构造函数,则需要调用父类的有参构造函数。

		
java

		
public class Parent {
    public Parent() {
        System.out.println("Parent constructor");
    }
}

public class Child extends Parent {
    public Child() {
        super(); // 调用父类构造函数
        System.out.println("Child constructor");
    }
}

    
	
访问父类成员:当子类和父类有相同名称的成员变量或方法时,可以使用 super 来访问父类的成员。

		
java

		
public class Parent {
    public int x = 10;

    public void printX() {
        System.out.println("Parent x: " + x);
    }
}

public class Child extends Parent {
    public int x = 20;

    public void printX() {
        System.out.println("Child x: " + x);
        System.out.println("Super x: " + super.x);
    }
}

    
	
在上述 Child 类中,printX 方法中使用了 super.x 来访问父类 Parent 的 x 变量。

26.数组的增删改查

增(Add)
在 Java 中,数组的大小在创建时就已经确定,不能动态更改。因此,如果你需要增加数组元素,通常需要创建一个新的、更大的数组,并将旧数组的元素复制到新数组中。

		
java

		
int[] oldArray = {1, 2, 3, 4, 5};
int[] newArray = new int[oldArray.length + 1];

System.arraycopy(oldArray, 0, newArray, 0, oldArray.length);
newArray[newArray.length - 1] = 6; // 添加新元素

    
	
删(Delete)
同样,数组的大小固定,不能直接删除元素。但你可以选择忽略某些元素,或者创建一个新数组,包含你想要保留的元素。

		
java

		
int[] array = {1, 2, 3, 4, 5};
int[] newArray = new int[array.length - 1];

System.arraycopy(array, 0, newArray, 0, newArray.length);

    
	
改(Update)
更新数组中的元素相对简单,只需要使用索引来访问元素并赋新值。

		
java

		
int[] array = {1, 2, 3, 4, 5};
array[2] = 10; // 将索引为2的元素更新为10

    
	
查(Retrieve)
要获取数组中的某个元素,同样使用索引。

		
java

		
int[] array = {1, 2, 3, 4, 5};
int element = array[2]; // 获取索引为2的元素,值为3

    
	
数组的动态操作 - 使用 ArrayList
如果你需要频繁地增删元素,并且不想每次都手动管理数组的大小,你可以使用 ArrayList,它是一个可以动态调整大小的数组。

		
java

		
import java.util.ArrayList;
import java.util.List;

List<Integer> list = new ArrayList<>();
list.add(1); // 添加元素
list.remove(0); // 删除元素
list.set(0, 10); // 更新元素
int element = list.get(0); // 获取元素

 27.string

字符串是不可变的(Immutable)
这意味着一旦创建了 String 对象,其内容就不能被更改。例如,你不能改变字符串中的一个字符或者替换字符串的一部分。每次对字符串进行修改操作时,实际上都会创建一个新的 String 对象。

创建字符串
使用双引号直接创建字符串字面量:

		
java

		
String str = "Hello, World!";

    
	
使用 new 关键字创建字符串对象:

		
java

		
String str = new String("Hello, World!");

    
	
第二种方式在一般情况下是不必要的,因为字符串字面量会自动被缓存。

字符串常量池
Java 有一个字符串常量池,用于存储所有字符串字面量。如果两个字符串字面量具有相同的值,它们将引用常量池中的同一个 String 对象。

方法
String 类提供了大量的方法来处理字符串,以下是一些常用的方法:

length():返回字符串的长度。

		
java

		
String str = "Hello";
int len = str.length(); // len = 5

    
	
charAt(int index):返回指定索引处的字符。

		
java

		
char ch = str.charAt(1); // ch = 'e'

    
	
equals(Object anObject):比较字符串内容是否相等。

		
java

		
String str1 = "Hello";
String str2 = "Hello";
boolean isEqual = str1.equals(str2); // isEqual = true

    
	
toLowerCase() 和 toUpperCase():将字符串转换为小写或大写。

		
java

		
String str = "Hello, World!";
String lowerCaseStr = str.toLowerCase(); // lowerCaseStr = "hello, world!"
String upperCaseStr = str.toUpperCase(); // upperCaseStr = "HELLO, WORLD!"

    
	
replace(char oldChar, char newChar):将一个字符替换为另一个字符。

		
java

		
String str = "Hello, World!";
String replacedStr = str.replace('o', 'a'); // replacedStr = "Hella, Warld!"

    
	
split(String regex):将字符串分割成字符串数组。

		
java

		
String str = "apple, banana, cherry";
String[] fruits = str.split(", "); // fruits[0] = "apple", fruits[1] = "banana", fruits[2] = "cherry"

    
	
字符串连接
字符串连接可以通过 + 运算符或 StringBuilder 类来完成。使用 + 运算符会创建一个新的字符串对象,因此当连接大量字符串时,使用 StringBuilder 会更高效。

		
java

		
String str1 = "Hello";
String str2 = "World";
String result1 = str1 + str2; // result1 = "HelloWorld"
// 或者使用StringBuilder
StringBuilder sb = new StringBuilder();
sb.append(str1).append(str2);
String result2 = sb.toString(); // result2 = "HelloWorld"

    
	
这些只是 String 类的一些基本用法,实际上它提供了更多的方法和功能。

28.string 与StringBulid与StringBuffer

String
String 是 Java 的基本字符串类型,它代表不可变的字符序列。这意味着一旦创建了一个 String 对象,它的内容就不能更改。任何修改字符串的操作实际上都会创建一个新的 String 对象。

StringBuilder
StringBuilder 类用于创建一个可变的字符序列。它是一个可增长的字符串缓冲区,适用于需要频繁修改字符串的场景。StringBuilder 不是线程安全的,因此它在单线程环境中性能更好。

常用方法
append(xxx):将指定值追加到字符串末尾。
delete(int start, int end):删除指定范围内的字符。
replace(int start, int end, String str):替换指定范围内的字符。
reverse():反转字符串。
示例
		
java

		
StringBuilder sb = new StringBuilder();
sb.append("Hello");
sb.append(", World!");
System.out.println(sb.toString()); // 输出: Hello, World!

    
	
StringBuffer
StringBuffer 与 StringBuilder 类似,也是一个可变的字符序列,但它是线程安全的。这意味着 StringBuffer 可以被多个线程安全地访问。由于线程安全机制的实现,StringBuffer 的性能通常低于 StringBuilder。

常用方法
StringBuffer 的方法与 StringBuilder 相同,包括 append、delete、replace 和 reverse 等。

示例
		
java

		
StringBuffer sbf = new StringBuffer();
sbf.append("Hello");
sbf.append(", World!");
System.out.println(sbf.toString()); // 输出: Hello, World!

    
	
StringJoiner
StringJoiner 类是 Java 8 引入的,用于将元素连接成一个字符串,并且在元素之间插入指定的分隔符。它主要用于连接集合中的元素,如 List 或 Set。

常用方法
add(value):将元素添加到 StringJoiner。
setEmptyValue(value):设置当 StringJoiner 为空时的值。
toString():返回连接后的字符串。
示例
		
java

		
StringJoiner joiner = new StringJoiner(", ");
joiner.add("Apple");
joiner.add("Banana");
joiner.add("Cherry");
System.out.println(joiner.toString()); // 输出: Apple, Banana, Cherry

    
	
总结
如果你的操作是在单线程环境中,且不涉及线程安全,那么 StringBuilder 是最好的选择,因为它提供了更高的性能。
如果你的操作需要线程安全,那么 StringBuffer 是合适的,尽管它的性能较低。
如果你需要连接集合中的元素,并且想要在元素之间插入分隔符,那么 StringJoiner 是一个很好的选择。

28.集合

集合框架的接口
List: 元素有序且可以重复的集合。主要实现类包括 ArrayList、LinkedList 和 Vector。

ArrayList: 基于动态数组实现,快速访问但插入和删除操作较慢。
LinkedList: 基于双向链表实现,插入和删除操作较快但访问速度较慢。
Vector: 类似于 ArrayList,但它是线程安全的。
Set: 不允许重复元素的集合。主要实现类包括 HashSet、LinkedHashSet 和 TreeSet。

HashSet: 基于哈希表实现,提供良好的性能,但不保持元素的顺序。
LinkedHashSet: 类似于 HashSet,但维护了一个运行于所有条目的双重链接列表,因此它还支持有序遍历。
TreeSet: 基于红黑树实现,元素处于排序状态。
Queue: 用于队列操作,如元素插入、移除和检查元素等。主要实现类包括 LinkedList、PriorityQueue 和 ArrayDeque。

LinkedList: 可以用作栈、队列或双端队列。
PriorityQueue: 基于优先队列实现的,元素按照自然排序或者构造时指定的比较器排序。
ArrayDeque: 类似于 ArrayList,但它是双端队列,支持在两端进行插入和删除操作。
Map: 键值对集合,键是唯一的,值可以重复。主要实现类包括 HashMap、LinkedHashMap、TreeMap 和 ConcurrentHashMap。

HashMap: 基于哈希表实现,提供快速的查找、插入和删除操作。
LinkedHashMap: 类似于 HashMap,但维护了元素的插入顺序。
TreeMap: 基于红黑树实现,保持元素的排序。
ConcurrentHashMap: 类似于 HashMap,但它是线程安全的。
集合的继承结构
Java 集合框架的类层次结构如下:

		

		
Collection
├── List
│   ├── ArrayList
│   ├── LinkedList
│   └── Vector
├── Set
│   ├── HashSet
│   ├── LinkedHashSet
│   └── TreeSet
└── Queue
    ├── LinkedList
    ├── PriorityQueue
    └── ArrayDeque

    
	
Collection 是所有集合类的父接口。
Map 接口与 Collection 接口是并列的,因为它们提供不同的功能。
注意事项
集合不保证元素的顺序。
一些集合类(如 HashSet 和 HashMap)不保证元素的唯一性。
线程安全的集合(如 Vector、Collections.synchronizedList、ConcurrentHashMap 等)在多线程环境中使用时需要谨慎

29.集合的增删改查

List
List 是一个有序且允许重复的集合。

增(Add)
add(int index, E element): 在指定位置插入元素。
add(E e): 将元素添加到集合的末尾。
删(Remove)
remove(int index): 移除指定位置的元素。
remove(Object o): 移除指定的元素。
改(Set)
set(int index, E element): 替换指定位置的元素。
查(Get)
get(int index): 返回指定位置的元素。
indexOf(Object o): 返回元素首次出现的索引,如果不存在则返回 -1。
lastIndexOf(Object o): 返回元素最后一次出现的索引,如果不存在则返回 -1。
Set
Set 是一个不包含重复元素的集合。

增(Add)
add(E e): 将元素添加到集合中。
删(Remove)
remove(Object o): 移除指定的元素。
查(Contains)
contains(Object o): 检查集合中是否包含指定的元素。
Queue
Queue 是一个用于元素插入、移除和检查元素的操作的先进先出(FIFO)集合。

增(Offer)
offer(E e): 将元素添加到队列的末尾。
删(Poll)
poll(): 移除并返回队列的头部元素,如果没有元素则返回 null。
remove(): 移除并返回队列的头部元素,如果没有元素则抛出异常。
查看(Peek)
peek(): 返回队列的头部元素,如果没有元素则返回 null。
Map
Map 是一个存储键值对的对象,其中键是唯一的。

增(Put)
put(K key, V value): 使用指定的键值对存储在映射中。
删(Remove)
remove(Object key): 移除指定键的映射。
改(Replace)
put(K key, V value): 用指定的值替换指定键的值。
查(Get)
get(Object key): 返回指定键的值,如果没有则返回 null。
以下是这些操作的示例代码:

		
java

		
// List 示例
List<String> list = new ArrayList<>();
list.add("Apple"); // 增
list.set(0, "Banana"); // 改
String fruit = list.get(0); // 查
list.remove("Banana"); // 删

// Set 示例
Set<String> set = new HashSet<>();
set.add("Apple"); // 增
set.remove("Apple"); // 删
boolean containsApple = set.contains("Apple"); // 查

// Queue 示例
Queue<String> queue = new LinkedList<>();
queue.offer("Apple"); // 增
String fruitFromQueue = queue.poll(); // 删

// Map 示例
Map<String, String> map = new HashMap<>();
map.put("Apple", "Fruit"); // 增
String typeOfApple = map.get("Apple"); // 查
map.remove("Apple"); // 删

30.static

静态字段(变量)
静态字段是类的成员,不属于任何一个对象实例。这意味着所有实例共享同一个静态字段的值。

公共访问:可以在不创建对象的情况下通过类名直接访问。
初始化:必须在类初始化时进行,通常在静态初始化块中完成。
		
java

		
public class MyClass {
    public static int staticField = 42;
    
    static {
        staticField = 100; // 静态初始化块,在类加载时执行
    }
}
int value = MyClass.staticField; // 不需要创建对象

    
	
静态方法
静态方法不依赖于类的任何实例,可以直接通过类名调用。

无 this 参数:静态方法中没有 this 参数,因为它不与任何对象实例相关联。
访问静态字段:静态方法可以访问静态字段,但不能直接访问非静态字段。
		
java

		
public class MyClass {
    public static void staticMethod() {
        System.out.println("Static method called");
        // 可以访问静态字段
        System.out.println(MyClass.staticField);
        // 不能访问非静态字段(会报错)
        // System.out.println(this.nonStaticField);
    }
}
MyClass.staticMethod(); // 不需要创建对象

    
	
静态初始化块
静态初始化块是类的一部分,用于初始化静态字段。当类被加载到 JVM 中时,这些块将被执行。

		
java

		
public class MyClass {
    static {
        // 静态初始化块
        System.out.println("Static block executed");
    }

    public static void main(String[] args) {
        System.out.println("Main method executed");
    }
}

    
	
静态内部类
静态内部类是定义在另一个类内部的类,它与外部类是平级的。静态内部类不依赖于外部类的实例,因此它有自己独立的构造器。

		
java

		
public class OuterClass {
    public static class StaticInnerClass {
        // 静态内部类可以访问外部类的静态成员
    }
    
    class NonStaticInnerClass {
        // 非静态内部类可以访问外部类的所有成员
    }
}

    
	
总结
static 关键字主要用于创建类级别的成员,这些成员不依赖于类的实例,并且可以在不创建实例的情况下通过类名直接访问。这在设计单例模式、工具类或与资源管理相关的类时非常有用。

31.继承

在面向对象的编程中,继承是描述类之间的关系的一种机制。一个类可以继承另一个类的属性和方法,这被称为父类(或超类)和子类(或派生类)的关系。Java 支持单继承,即一个子类只能有一个直接父类,但可以通过多层继承实现多级继承。

继承的基本概念
父类(Superclass):被继承的类,提供属性和方法给子类使用。
子类(Subclass):继承父类的类,可以添加新的属性和方法,也可以重写(Override)父类的方法。
继承的特点
代码复用:子类可以继承父类的方法和属性,减少代码冗余。
多态性:子类对象可以被视为父类对象,实现多态。
扩展性:可以在不修改现有代码的情况下添加新的功能。
继承语法
		
java

		
public class ParentClass {
    // 父类的属性、方法和构造器
}

public class ChildClass extends ParentClass {
    // 子类可以添加新的属性、方法和构造器
}

    
	
继承的类型
单继承:一个子类只能继承一个父类。
多继承:Java 不支持多继承,但可以通过接口来实现类似多继承的效果。
重写(Override)
子类可以重写(Override)父类的方法,当调用该方法时,将执行子类中的版本。

		
java

		
public class ParentClass {
    public void show() {
        System.out.println("Parent show");
    }
}

public class ChildClass extends ParentClass {
    @Override
    public void show() {
        System.out.println("Child show");
    }
}

    
	
覆盖(Covering)
在继承关系中,子类可以覆盖父类的方法,但也可以选择“覆盖”而不是“重写”。当子类的方法与父类的方法具有相同的签名(返回类型、方法名和参数列表)时,它就是“覆盖”。

构造器继承
子类会自动调用父类的构造器来初始化父类的部分。如果父类没有无参构造器,子类必须显式调用父类的有参构造器。

		
java

		
public class ParentClass {
    public ParentClass() {
        System.out.println("Parent constructor called");
    }
}

public class ChildClass extends ParentClass {
    public ChildClass() {
        super(); // 调用父类的无参构造器
        System.out.println("Child constructor called");
    }
}

    
	
注意事项
子类不能直接访问父类的私有(private)成员。
子类可以访问父类的保护(protected)成员和公共(public)成员。
子类不能比父类有更严格的访问控制。
子类可以添加新的属性和方法,也可以重写父类的方法。
继承是面向对象编程中的一个核心概念,它有助于创建可重用和可扩展的代码。

32.多态

多态的类型
编译时多态(静态多态):

使用函数重载或方法重载来实现。
在编译阶段就能确定调用哪个方法。
运行时多态(动态多态):

使用继承和接口来实现。
在运行阶段根据对象的实际类型来调用对应的方法。
多态的实现
多态通常通过以下方式实现:

继承:

子类继承父类,并重写父类的方法。
当调用这些方法时,Java 虚拟机(JVM)会根据对象的实际类型来决定调用哪个方法。
接口:

通过接口定义方法签名。
实现类实现接口,并实现接口中的方法。
使用接口的引用变量指向实现类的对象,从而实现多态。
多态的示例
以下是一个简单的多态示例:

		
java

		
// 父类
class Animal {
    void makeSound() {
        System.out.println("Some sound");
    }
}

// 子类
class Dog extends Animal {
    void makeSound() {
        System.out.println("Bark");
    }
}

class Cat extends Animal {
    void makeSound() {
        System.out.println("Meow");
    }
}

public class PolymorphismExample {
    public static void main(String[] args) {
        Animal myAnimal = new Dog(); // 父类引用指向子类对象
        myAnimal.makeSound(); // 输出: Bark

        myAnimal = new Cat();
        myAnimal.makeSound(); // 输出: Meow
    }
}

    
	
在这个例子中,Animal 类是父类,Dog 和 Cat 是子类。makeSound 方法在 Dog 和 Cat 类中被重写。通过 Animal 类型的引用 myAnimal,我们可以调用 makeSound 方法,但在运行时,根据 myAnimal 实际指向的对象类型(Dog 或 Cat),会调用相应子类的方法。

多态的益处
代码可扩展性:当添加新的子类时,不需要修改使用父类引用的地方。
代码可维护性:通过使用父类引用,可以更容易地维护和扩展代码。
提高代码的灵活性:可以通过父类引用来处理不同类型的对象,代码更加灵活。

33.包

包的基本概念
包的作用:用于组织和管理相关的类和接口,避免命名冲突,提供命名空间。
包的命名规范:包名通常使用小写字母,多个单词之间使用点(.)分隔,例如 com.example.myproject。
包的层级结构:包可以有多级层次结构,例如 com.example.myproject.subpackage。
包的声明:在 Java 源文件的开头使用 package 关键字声明所属的包。
包的声明
在 Java 源文件的开头使用 package 关键字来声明所属的包。一个 Java 源文件只能属于一个包。

		
java

		
package com.example.myproject;

public class MyClass {
    // 类的代码
}

    
	
包的导入
在 Java 中,可以使用 import 关键字来导入其他包中的类,以便在当前类中直接使用这些类,而无需使用完整的类名。

		
java

		
package com.example.myproject;

import java.util.ArrayList;

public class MyClass {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        // 使用 ArrayList 类
    }
}

    
	
包的层级结构
包可以有多级层次结构,例如 com.example.myproject 中的 com 是顶级包,example 是其子包,myproject 是 example 的子包。

包的命名规范:通常使用逆域名(Reverse Domain Name)的方式来命名包,确保包名的唯一性。
包的路径
在文件系统中,Java 包通常与文件夹结构对应,每个包对应一个文件夹,子包对应子文件夹。例如,包 com.example.myproject 对应文件夹 com/example/myproject。

包的访问控制
Java 中的包访问控制有四种访问权限:private、default、protected 和 public。包访问控制规则如下:

private:只能在当前类中访问。
default(包访问权限):只能在同一个包中访问。
protected:可以在同一个包中和子类中访问。
public:可以在任何地方访问。
示例
假设有以下文件结构:

		

		
src
│
└───com
    └───example
        └───myproject
            │   MyClass.java
            │
            └───subpackage
                │   AnotherClass.java

    
	
在 MyClass.java 中声明包:

		
java

		
package com.example.myproject;

public class MyClass {
    // 类的代码
}

    
	
在 AnotherClass.java 中导入 MyClass 类:

		
java

		
package com.example.myproject.subpackage;

import com.example.myproject.MyClass;

public class AnotherClass {
    // 类的代码
}

34.final

final 关键字的不同应用
用于变量:

当一个变量被声明为 final 时,它的值只能被赋值一次,之后不能再被改变。
这通常用于声明常量,如数学常数或配置值。
		
java

		
public class MyClass {
    public static final double PI = 3.14159;
}

    
	
用于方法:

当一个方法被声明为 final 时,它不能被覆盖(override)。
这通常用于防止子类改变父类方法的行为。
		
java

		
public class ParentClass {
    public final void doSomething() {
        // 方法实现
    }
}

    
	
用于类:

当一个类被声明为 final 时,它不能被继承。
这通常用于防止类的状态被继承或修改。
		
java

		
public final class FinalClass {
    // 类的实现
}

    
	
final 变量的特点
不可变性:一旦 final 变量被赋值,其值就不能再改变。
初始化:final 变量必须在声明时立即初始化,或者在构造器中初始化,或者在之后的一个初始化块中初始化。
示例
以下是一些 final 关键字的使用示例:

		
java

		
public class FinalExample {

    // 声明一个不可变的常量
    public static final int MAX_VALUE = 100;

    // 声明一个不可变对象
    public final String message = "This is a final variable";

    // 声明一个不可变的方法
    public final void displayMessage() {
        System.out.println(message);
    }

    // 声明一个不可继承的类
    public static final class FinalClass {
        // 类的实现
    }
}

    
	
在上述示例中,MAX_VALUE 是一个常量,message 是一个不可变的对象引用,displayMessage 是一个不可变的方法,而 FinalClass 是一个不可继承的类。

使用 final 关键字可以帮助程序员编写更清晰、更安全、更易于维护的代码。

35.权限修饰符

在 Java 编程语言中,权限修饰符(也称为访问控制符)用于定义类、接口、字段(成员变量)和方法的可访问性。它们控制了代码的不同部分如何被其他类访问。Java 中有四种主要的权限修饰符:

public:

公共的访问权限,允许任何类访问。
如果一个类或成员被声明为 public,它可以在任何其他类中访问。
		
java

		
public class PublicClass {
    public int publicVar = 1;
}

    
	
protected:

受保护的访问权限,允许同一个包中的所有类以及子类访问。
如果一个类或成员被声明为 protected,它可以在同一个包中的任何类中访问,也可以在所有继承了这个类或实现了这个接口的子类中访问。
		
java

		
protected class ProtectedClass {
    protected int protectedVar = 2;
}

    
	
默认(无修饰符):

默认的访问权限,也称为包私有(package-private)。
如果一个类或成员没有明确的权限修饰符,它只能在同一个包中访问。
这对于在一个包内部组织类和接口非常有用。
		
java

		
class DefaultClass {
    int defaultVar = 3;
}

    
	
private:

私有的访问权限,允许只有定义它的类访问。
如果一个类或成员被声明为 private,它只能在声明它的类内部访问。
		
java

		
class PrivateClass {
    private int privateVar = 4;
}

    
	
权限修饰符的规则
类:默认情况下,类是公开的,除非特别声明为 private 或 protected。
字段和方法:字段和方法可以声明为 public、protected、默认 或 private。
构造函数:构造函数可以声明为 public、protected、默认 或 private。
接口:接口默认是公开的,不能声明为 private。
权限修饰符的层次结构
权限修饰符的层次结构如下:

public > protected > 默认 > private
这意味着 public 允许最广泛的访问,而 private 允许最有限的访问。

使用权限修饰符可以帮助隐藏实现细节,确保类的封装性,并提高代码的安全性和可维护性。

36.代码块

代码块的类型
声明代码块:

用于声明变量和初始化资源,通常在 try 语句中使用,以初始化可能需要清理的资源。
		
java

		
try {
    // 代码执行
} finally {
    // 资源清理
}

    
	
循环代码块:

用于循环语句中,如 for、while 和 do-while 循环。
		
java

		
for (int i = 0; i < 10; i++) {
    // 循环体
}

    
	
条件代码块:

用于 if-else 语句中,根据条件执行不同的代码块。
		
java

		
if (condition) {
    // 条件为真时执行的代码块
} else {
    // 条件为假时执行的代码块
}

    
	
语句代码块:

可以将任何语句组合成一个代码块,即使它只包含一个语句。
		
java

		
{
    int result = 5 + 3;
    System.out.println(result);
}

    
	
代码块的作用域
代码块创建了一个新的作用域,意味着在代码块内部声明的变量只能在这个代码块内部访问。
这对于控制变量的生命周期和作用域非常有用。
示例
以下是一些代码块的示例:

try-finally 代码块
		
java

		
try {
    // 尝试执行的代码
    // 可能会抛出异常
} finally {
    // 无论是否发生异常,都会执行的代码
    // 通常用于释放资源
}

    
	
for 循环代码块
		
java

		
for (int i = 0; i < 5; i++) {
    // 循环体
    System.out.println(i);
}

    
	
if-else 代码块
		
java

		
int number = 10;
if (number > 0) {
    // 条件为真时执行的代码块
    System.out.println("The number is positive.");
} else {
    // 条件为假时执行的代码块
    System.out.println("The number is not positive.");
}

    
	
单语句代码块
		
java

		
{
    int result = 5 + 3;
    System.out.println(result);
}

    
	
代码块是 Java 中的一个强大工具,可以用于组织代码、控制作用域和资源管理。

37.abtract

抽象类
抽象类是一个不能被实例化的类,它包含抽象方法和具体方法。
抽象方法是没有实现体的方法,即它只声明了方法签名,没有方法体。
抽象类至少有一个抽象方法,但也可以有具体方法(有方法体的方法)。
抽象类通常用作其他类的基类,用于定义通用行为和属性,同时允许子类提供特定的实现。
抽象类的示例:
		
java

		
public abstract class Animal {
    // 抽象方法
    public abstract void makeSound();

    // 具体方法
    public void eat() {
        System.out.println("This animal eats food.");
    }
}

    
	
在这个例子中,Animal 类是一个抽象类,它有一个抽象方法 makeSound() 和一个具体方法 eat()。

抽象方法
抽象方法是在抽象类中声明的方法,没有方法体。
它们要求任何继承自该抽象类的子类必须实现这些方法。
抽象方法不能被声明为 final、static 或 private,因为这样做将阻止子类覆盖它们。
抽象方法的示例:
		
java

		
public abstract class Vehicle {
    // 抽象方法
    public abstract void startEngine();
}

    
	
在这个例子中,Vehicle 类中有一个抽象方法 startEngine(),任何继承自 Vehicle 的子类都必须提供这个方法的具体实现。

使用规则
抽象类不能被实例化,只能被继承。
一个类只能有一个父类,但可以实现多个接口。
如果一个类包含一个或多个抽象方法,那么这个类也必须是抽象的。
抽象类的目的
抽象类用于在基类中定义一个概念框架,具体实现留给子类去完成。
它允许程序员定义一个通用接口,同时允许子类实现不同的行为。
抽象类可以包含成员变量和具体方法,这些都可以在子类中被继承或覆盖。
通过使用 abstract 关键字,Java 支持了面向对象编程中的抽象概念,使得代码更加模块化和可重用。

38.抽象类与抽象方法

抽象类
定义:抽象类是一个不能被实例化的类,它至少包含一个抽象方法。它通常用作其他类的基类,用来提供一种框架或模板,子类可以在此基础上实现具体的功能。
用途:抽象类通常用于以下情况:
当设计一个基类,它应该有某些默认实现,同时还需要有抽象方法来要求子类提供特定实现。
当基类中包含逻辑,但某些方法的具体实现需要根据子类的不同而有所不同。
特性:
抽象类可以包含抽象方法、具体方法、成员变量和构造函数。
抽象类不能被实例化,即不能直接创建其对象。
抽象类的示例:
		
java

		
public abstract class Animal {
    // 成员变量
    protected String name;

    // 构造函数
    public Animal(String name) {
        this.name = name;
    }

    // 抽象方法
    public abstract void makeSound();

    // 具体方法
    public void eat() {
        System.out.println(name + " is eating.");
    }
}

    
	
抽象方法
定义:抽象方法是在抽象类中声明的方法,它没有方法体(即没有大括号包围的实现代码)。
用途:抽象方法强制子类提供具体的实现,这样每个子类都必须定义这个方法。
特性:
抽象方法不能有访问修饰符(除了 public 和 protected),并且不能声明为 final、static 或 private。
抽象方法的使用是强制性的,任何继承自抽象类的子类都必须实现这个方法。
抽象方法的示例:
		
java

		
public abstract class Animal {
    // 抽象方法
    public abstract void makeSound();
}

    
	
在这个例子中,makeSound 是一个抽象方法,它要求任何继承自 Animal 类的子类都必须提供一个 makeSound 方法的具体实现。

关系
抽象类可以包含抽象方法,但也可以包含具体方法。
抽象方法总是存在于抽象类中,但抽象类不一定要有抽象方法。
如果一个类包含至少一个抽象方法,那么这个类就必须是抽象的。

39.抽象类的使用

场景
定义通用接口:当多个子类具有相似的方法签名,但具体的实现细节有所不同时,可以使用抽象类来定义一个通用的接口。

提供默认行为:抽象类可以包含一些具体方法,这些方法为子类提供了默认的行为或实现。

约束子类:抽象类可以强制子类实现某些抽象方法,确保所有子类都遵循特定的接口。

作为基类:抽象类可以作为其他类的基类,提供一些共有的属性和方法。

使用步骤
声明抽象类:使用 abstract 关键字声明一个类为抽象类。

添加抽象方法:在抽象类中声明至少一个抽象方法。这些方法没有方法体,只包含返回类型和方法名。

实现具体方法:根据需要,在抽象类中实现具体方法。这些方法可以有方法体,提供默认的实现。

创建子类:创建抽象类的子类,并实现所有抽象方法。

使用子类:通过子类创建对象,并使用它们。

示例
以下是一个使用抽象类的示例:

		
java

		
// 抽象类
public abstract class Animal {
    // 构造函数
    public Animal(String name) {
        this.name = name;
    }

    // 抽象方法
    public abstract void makeSound();

    // 具体方法
    public void eat() {
        System.out.println(name + " is eating.");
    }

    // 成员变量
    protected String name;
}

// 子类
public class Dog extends Animal {
    // 构造函数
    public Dog(String name) {
        super(name);
    }

    // 实现抽象方法
    @Override
    public void makeSound() {
        System.out.println(name + " says: Woof!");
    }
}

// 子类
public class Cat extends Animal {
    // 构造函数
    public Cat(String name) {
        super(name);
    }

    // 实现抽象方法
    @Override
    public void makeSound() {
        System.out.println(name + " says: Meow!");
    }
}

// 主类
public class Main {
    public static void main(String[] args) {
        Dog dog = new Dog("Buddy");
        Cat cat = new Cat("Kitty");

        dog.makeSound(); // 输出: Buddy says: Woof!
        cat.makeSound(); // 输出: Kitty says: Meow!
    }
}

    
	
在这个例子中,Animal 是一个抽象类,它定义了一个抽象方法 makeSound() 和一个具体方法 eat()。Dog 和 Cat 类继承自 Animal 类,并提供了 makeSound() 方法的具体实现。在 Main 类的 main 方法中,我们创建了 Dog 和 Cat 的对象,并调用了它们的 makeSound() 方法。

注意事项
抽象类不能被实例化,只能被继承。
子类必须实现所有继承自抽象类的抽象方法,除非它是抽象类本身。
抽象类中的具体方法可以被任何子类继承,也可以被子类覆盖以提供不同的实现。

40.接口

接口的特点
抽象性:接口完全抽象,只包含抽象方法(没有方法体的方法)和静态常量。

多态性:通过实现接口,不同的类可以表现出相同的方法行为,实现了多态。

契约:接口定义了类必须实现的方法,实现了类间的一种约定。

灵活性:接口允许类实现多个接口,增加了代码的灵活性。

接口的定义
		
java

		
public interface InterfaceName {
    // 抽象方法
    void method1();

    // 静态常量
    int CONSTANT = 1;

    // 默认方法(Java 8 及以后版本)
    default void method2() {
        // 方法体
    }

    // 静态方法(Java 8 及以后版本)
    static void method3() {
        // 方法体
    }
}

    
	
接口的实现
一个类通过实现接口来提供接口中定义的方法的具体实现。使用 implements 关键字来声明一个类实现了某个接口。

		
java

		
public class ClassName implements InterfaceName {
    @Override
    public void method1() {
        // 方法实现
    }

    // 如果类不需要覆盖默认方法,可以省略 @Override 注解
    public void method2() {
        // 方法实现
    }
}

    
	
接口与抽象类的比较
继承:一个类只能继承自一个抽象类,但可以实现多个接口。
抽象方法:抽象类可以包含抽象方法和具体方法,而接口只能包含抽象方法(Java 8 及以后版本允许接口有默认方法和静态方法)。
目的:抽象类通常用于提供部分实现和共享代码,接口用于定义公共行为和契约。
示例
以下是一个简单的接口示例:

		
java

		
// 定义一个名为 "Shape" 的接口
public interface Shape {
    double area(); // 定义一个抽象方法,计算形状的面积
}

// 实现该接口的类
public class Circle implements Shape {
    private double radius;

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

    @Override
    public double area() {
        return Math.PI * radius * radius; // 返回圆的面积
    }
}

// 使用 Circle 类
public class TestShape {
    public static void main(String[] args) {
        Shape circle = new Circle(5);
        System.out.println("Circle area: " + circle.area());
    }
}

    
	
在这个例子中,Shape 接口定义了一个抽象方法 area(),Circle 类实现了这个接口,并提供了 area() 方法的具体实现。最后,在 TestShape 类的 main 方法中,我们创建了一个 Circle 对象,并调用了它的 area() 方法来计算圆的面积。

41.接口与抽象类

接口与抽象类在 Java 中都是用来实现抽象和定义契约的工具,但它们之间存在一些关键的区别:

相同点
抽象性:两者都可以包含抽象方法,即没有具体实现的方法。
多态性:两者都支持多态,允许通过引用类型来调用对象的实现类型的方法。
继承:两者都可以被继承。一个类可以继承自一个抽象类,也可以实现多个接口。
不同点
抽象方法与具体方法的数量:

抽象类:可以包含抽象方法(没有具体实现的方法)和具体方法(有具体实现的方法)。
接口:只能包含抽象方法(Java 8 及以后版本允许接口包含默认方法和静态方法)。
继承和实现:

抽象类:一个类只能继承自一个抽象类,但可以实现多个接口。
接口:一个类可以实现多个接口。
设计目的:

抽象类:通常用于当子类之间有共通的行为时,提供一些默认实现,同时也可以定义一些抽象方法让子类实现。
接口:通常用于定义一组公共的契约,一个类可以实现多个接口,这允许类表现出多种不同的行为。
访问修饰符:

抽象类:可以包含不同访问级别的成员变量和方法(例如 public, protected, private)。
接口:接口中的所有方法和变量默认都是 public 的,除非显式指定。
构造函数:

抽象类:可以包含构造函数。
接口:不能包含构造函数。
使用场景
当设计一个基类,希望它有一些默认方法实现,同时要求子类实现一些方法时,可以使用抽象类。
当需要定义一组公共方法,但不提供具体实现,且希望类能够实现多个这样的接口时,可以使用接口。
以下是一个简化的例子来说明两者的区别:

抽象类示例
		
java

		
public abstract class Vehicle {
    // 抽象方法
    public abstract void start();
    
    // 具体方法
    public void stop() {
        System.out.println("Vehicle stopped.");
    }
}

public class Car extends Vehicle {
    @Override
    public void start() {
        System.out.println("Car started.");
    }
}

    
	
在这个例子中,Vehicle 是一个抽象类,它有一个抽象方法 start() 和一个具体方法 stop()。

接口示例
		
java

		
public interface Movable {
    // 抽象方法
    void move();
}

public class Car implements Movable {
    @Override
    public void move() {
        System.out.println("Car moved.");
    }
}

    
	
在这个例子中,Movable 是一个接口,它定义了一个抽象方法 move()。Car 类实现了这个接口,并提供了 move() 方法的具体实现。

总结来说,抽象类和接口在 Java 中各有用途,开发者应根据具体的设计需求和场景选择合适的工具。

42.内部类

在 Java 中,内部类(Inner Class)是定义在其他类内部的类。根据它们定义的位置和用途,内部类可以分为几种类型:成员内部类(Member Inner Class)、局部内部类(Local Inner Class)、匿名内部类(Anonymous Inner Class)和静态内部类(Static Inner Class)。

成员内部类
成员内部类是定义在另一个类的非静态成员内部,它可以访问外部类的所有成员(包括私有成员)。

		
java

		
public class OuterClass {
    private int outerVar;

    public class InnerClass {
        public void printOuterVar() {
            System.out.println(outerVar);
        }
    }
}

    
	
局部内部类
局部内部类是在一个方法或代码块内部定义的类。它只能在该代码块或方法内部访问,无法被外部类访问。

		
java

		
public class OuterClass {
    public void outerMethod() {
        class LocalInnerClass {
            public void printOuterVar() {
                System.out.println(outerVar);
            }
        }

        // 使用局部内部类
        LocalInnerClass localInner = new LocalInnerClass();
        localInner.printOuterVar();
    }
}

    
	
匿名内部类
匿名内部类是没有名字的内部类,通常用于实现那些只需要一次使用的类。它通常与接口或抽象类一起使用,用于创建一个实现接口或继承抽象类的对象。

		
java

		
public class OuterClass {
    public void outerMethod() {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("Hello from anonymous inner class!");
            }
        };
        new Thread(runnable).start();
    }
}

    
	
静态内部类
静态内部类是定义在外部类的静态成员内部,它与外部类的非静态成员没有直接关联。静态内部类可以访问外部类的静态成员,但不能访问非静态成员。

		
java

		
public class OuterClass {
    private static int staticVar;

    public static class StaticInnerClass {
        public void printStaticVar() {
            System.out.println(staticVar);
        }
    }
}

    
	
内部类的使用场景
封装:内部类可以封装外部类的实现细节,提供对内部状态的保护。
逻辑分组:将相关的功能或数据组合在一起,使得代码更加模块化和可读。
访问权限:内部类可以访问外部类的私有成员,这对于实现复杂的类层次结构非常有用。
注意事项
内部类可以访问创建它的外部类的所有成员,包括私有成员。
局部内部类和匿名内部类通常用于实现单例模式、监听器模式或工厂模式等设计模式。
静态内部类类似于一个普通的顶层类,它没有访问外部类的非静态成员的能力。

43.内部类的使用


    public Worker(String name) {
        this.name = name;
        new Task().execute();
    }

    private class Task implements Runnable {
        @Override
        public void run() {
            System.out.println(name + " is working.");
        }
    }
}

    
	
在这个例子中,Task 类是一个局部内部类,它与 Worker 类紧密相关,用于在 Worker 对象创建时执行一些工作。

3. 设计模式
内部类常用于实现设计模式,例如单例模式、适配器模式等。

单例模式
		
java

		
public class Database {
    private static class InstanceHolder {
        private static final Database INSTANCE = new Database();
    }

    private Database() {}

    public static Database getInstance() {
        return InstanceHolder.INSTANCE;
    }
}

    
	
在这个单例模式实现中,InstanceHolder 是一个静态内部类,它持有单例实例。

适配器模式
		
java

		
public class AudioPlayer {
    public void play(String audioType, String fileName) {
        if ("mp3".equalsIgnoreCase(audioType)) {
            new MP3Player().play(fileName);
        } else if ("vlc".equalsIgnoreCase(audioType)) {
            new VLCPlayer().play(fileName);
        } else if ("mp4".equalsIgnoreCase(audioType)) {
            new MP4Player().play(fileName);
        } else {
            System.out.println("Invalid audio type");
        }
    }

    private class MP3Player {
        public void play(String fileName) {
            System.out.println("Playing mp3 file. Name: " + fileName);
        }
    }

    private class VLCPlayer {
        public void play(String fileName) {
            System.out.println("Playing vlc file. Name: " + fileName);
        }
    }

    private class MP4Player {
        public void play(String fileName) {
            System.out.println("Playing mp4 file. Name: " + fileName);
        }
    }
}

    
	
在这个例子中,MP3Player、VLCPlayer 和 MP4Player 都是 AudioPlayer 的内部类,它们各自实现了播放不同类型音频文件的功能。

4. 访问控制
内部类可以访问外部类的私有成员,这对于实现复杂的类层次结构和继承关系非常有用。

		
java

		
public class OuterClass {
    private int value;

    public class InnerClass {
        public void accessPrivateVariable() {
            System.out.println("Outer class's private value: " + value);
        }
    }
}

    
	
在这个例子中,InnerClass 可以访问 OuterClass 的私有成员 value。

44.API-Math

Java
Java 的 Math 类提供了大量的数学函数,包括:

基本数学运算:例如 sin()、cos()、tan()、sqrt()(平方根)、pow()(幂运算)等。
取整:例如 round()、floor()、ceil()、rint() 等。
随机数生成:例如 random()、nextInt()、nextDouble() 等。
最大值和最小值:例如 max()、min() 等。
绝对值:例如 abs()。
Python
Python 的 math 模块提供了类似的功能:

		
python

		
import math

# 常用数学函数
math.sin(x)
math.cos(x)
math.tan(x)
math.sqrt(x)
math.pow(x, y)

# 取整
math.floor(x)
math.ceil(x)
math.round(x)

# 随机数
math.random()
math.randint(a, b)

# 最大值和最小值
math.max(x, y)
math.min(x, y)

# 绝对值
math.fabs(x)

    
	
C++
C++ 的 <cmath> 库也提供了广泛的数学函数:

		
cpp

		
#include <cmath>

// 常用数学函数
std::sin(x)
std::cos(x)
std::tan(x)
std::sqrt(x)
std::pow(x, y)

// 取整
std::floor(x)
std::ceil(x)
std::round(x)

// 随机数
std::rand()
std::srand(seed)

// 最大值和最小值
std::max(x, y)
std::min(x, y)

// 绝对值
std::fabs(x)

    
	
JavaScript
JavaScript 的 Math 对象也提供了丰富的数学方法:

		
javascript

		
// 常用数学函数
Math.sin(x)
Math.cos(x)
Math.tan(x)
Math.sqrt(x)
Math.pow(x, y)

// 取整
Math.floor(x)
Math.ceil(x)
Math.round(x)

// 随机数
Math.random()
Math.min(x, y)
Math.max(x, y)

// 绝对值
Math.abs(x)

    
	
这些数学库都提供了处理数学运算的基本工具,使得在程序中进行数学计算变得简单。使用时,应根据具体编程语言和需求选择合适的方法。
常用数学方法
三角函数

sin(double a):返回参数 a 的正弦值。
cos(double a):返回参数 a 的余弦值。
tan(double a):返回参数 a 的正切值。
		
java

		
double radians = Math.toRadians(90); // 将角度转换为弧度
System.out.println("sin(90 degrees): " + Math.sin(radians)); // 应该输出 1.0

    
	
平方根

sqrt(double a):返回参数 a 的平方根。
		
java

		
double sqrtValue = Math.sqrt(16); // 16 的平方根
System.out.println("Square root of 16: " + sqrtValue); // 应该输出 4.0

    
	
幂运算

pow(double a, double b):返回 a 的 b 次幂。
		
java

		
double powerValue = Math.pow(2, 3); // 2 的 3 次幂
System.out.println("2 to the power of 3: " + powerValue); // 应该输出 8.0

    
	
最大值和最小值

max(double a, double b):返回两个数中较大的一个。
min(double a, double b):返回两个数中较小的一个。
		
java

		
double maxValue = Math.max(5, 10); // 输出较大的值
double minValue = Math.min(5, 10); // 输出较小的值
System.out.println("Max value: " + maxValue); // 输出 10
System.out.println("Min value: " + minValue); // 输出 5

    
	
四舍五入

round(double a):返回最接近参数 a 的整数。
ceil(double a):返回大于或等于参数 a 的最小整数。
floor(double a):返回小于或等于参数 a 的最大整数。
		
java

		
double roundedValue = Math.round(3.6); // 四舍五入到最接近的整数
double ceilingValue = Math.ceil(3.3); // 向上取整
double floorValue = Math.floor(3.7); // 向下取整
System.out.println("Rounded value: " + roundedValue); // 输出 4
System.out.println("Ceiling value: " + ceilingValue); // 输出 4
System.out.println("Floor value: " + floorValue); // 输出 3

    
	
随机数生成

random():返回一个大于等于 0.0 且小于 1.0 的伪随机数。
nextInt(int n):返回一个介于 0(包含)到 n(不包含)之间的伪随机数。
		
java

		
double randomValue = Math.random();
int randomInt = Math.nextInt(100); // 生成一个 0 到 99 之间的随机数
System.out.println("Random value: " + randomValue);
System.out.println("Random integer: " + randomInt);

    
	
注意事项
Math 类中的所有方法都接受和返回 double 类型的值。
Math 类中的大多数方法都是静态的,因此可以直接使用类名调用,无需创建 Math 类的实例。

45.System

1. 标准输入输出
System.out.println():用于打印信息到标准输出(通常是控制台)。

		
java

		
System.out.println("Hello, World!");

    
	
System.out.print():用于打印信息到标准输出,但不自动换行。

		
java

		
System.out.print("Hello, ");
System.out.println("World!");

    
	
System.out.printf():用于格式化输出。

		
java

		
System.out.printf("Today is %tc%n", new Date());

    
	
System.err.println():用于打印错误信息到标准错误流(通常也是控制台,但可以重定向)。

		
java

		
System.err.println("This is an error message.");

    
	
2. 读取输入
System.in.read():从标准输入读取一个字节。

		
java

		
int b;
while ((b = System.in.read()) != -1) {
    // 处理读取的字节
}

    
	
Scanner 类:Java 5 引入了一个更高级的输入读取类 Scanner,它封装了 System.in。

		
java

		
Scanner scanner = new Scanner(System.in);
System.out.print("Enter your name: ");
String name = scanner.nextLine();
System.out.println("Hello, " + name + "!");
scanner.close();

    
	
3. 获取环境变量
System.getenv(String key):返回与指定键关联的值。

		
java

		
String os = System.getenv("OS");
System.out.println("Operating system: " + os);

    
	
4. 获取系统属性
System.getProperty(String key):返回与指定键关联的系统属性值。

		
java

		
String javaVersion = System.getProperty("java.version");
System.out.println("Java version: " + javaVersion);

    
	
5. 执行命令
System.exec(String command):执行一个命令并返回一个 Process 对象。

		
java

		
try {
    Process process = Runtime.getRuntime().exec("notepad");
    // 可以使用 process.getInputStream() 等方法来处理命令的输出
} catch (IOException e) {
    e.printStackTrace();
}

    
	
注意事项
System.in、System.out 和 System.err 都是 final 类型的,这意味着它们不能被继承或修改。
在调用 System.exec() 方法时,要处理可能抛出的 IOException。

46.Runtime

1. 运行外部程序
exec(String command):在单独的进程中执行指定的命令。

		
java

		
try {
    Runtime runtime = Runtime.getRuntime();
    Process process = runtime.exec("notepad.exe");
    // 可以使用 process.getInputStream() 等方法来处理命令的输出
} catch (IOException e) {
    e.printStackTrace();
}

    
	
exec(String[] cmdarray):使用指定的命令和参数数组执行命令。

		
java

		
try {
    Runtime runtime = Runtime.getRuntime();
    Process process = runtime.exec(new String[]{"notepad.exe", "file.txt"});
    // 可以使用 process.getInputStream() 等方法来处理命令的输出
} catch (IOException e) {
    e.printStackTrace();
}

    
	
2. 获取内存信息
totalMemory():返回 Java 虚拟机的总内存量。

		
java

		
Runtime runtime = Runtime.getRuntime();
long totalMemory = runtime.totalMemory();
System.out.println("Total memory: " + totalMemory + " bytes");

    
	
freeMemory():返回 Java 虚拟机的空闲内存量。

		
java

		
Runtime runtime = Runtime.getRuntime();
long freeMemory = runtime.freeMemory();
System.out.println("Free memory: " + freeMemory + " bytes");

    
	
3. 执行垃圾回收
gc():运行垃圾回收器。

		
java

		
Runtime runtime = Runtime.getRuntime();
runtime.gc();

    
	
4. 终止虚拟机
exit(int status):终止当前正在运行的 Java 虚拟机。

		
java

		
Runtime runtime = Runtime.getRuntime();
runtime.exit(0);

    
	
注意事项
Runtime 类是一个单例类,通过 Runtime.getRuntime() 方法获取实例。
在调用 exec() 方法时,要处理可能抛出的 IOException。
使用 exec() 方法执行外部程序时,需要注意处理命令的输出和错误流。

47.object

在Java中,Object 类是所有类的根类,也是 Java 类层次结构的顶级类。由于所有类都直接或间接地继承自 Object 类,因此 Object 类提供了一些通用的方法和功能,可以在所有对象上使用。以下是一些常用的 Object 类的方法:

1. toString()
toString() 方法返回对象的字符串表示形式。默认情况下,toString() 方法返回对象的类名和哈希码的十六进制表示。

		
java

		
public String toString() {
    return getClass().getName() + "@" + Integer.toHexString(hashCode());
}

    
	
可以根据需要在自定义类中重写 toString() 方法,以返回更有意义的字符串表示形式。

2. equals()
equals() 方法用于比较两个对象是否相等。默认情况下,equals() 方法比较的是对象的引用是否相等,即是否指向同一个内存地址。

		
java

		
public boolean equals(Object obj) {
    return (this == obj);
}

    
	
可以根据需要在自定义类中重写 equals() 方法,以根据对象的内容比较它们是否相等。

3. hashCode()
hashCode() 方法返回对象的哈希码。默认情况下,hashCode() 方法返回对象的内存地址的哈希码。

		
java

		
public int hashCode() {
    return super.hashCode();
}

    
	
可以根据需要在自定义类中重写 hashCode() 方法,以根据对象的内容计算哈希码。

4. getClass()
getClass() 方法返回对象的运行时类。

		
java

		
public final Class<?> getClass() {
    return Reflection.getCallerClass();
}

    
	
5. 其他方法
finalize():在对象被垃圾回收之前调用。
notify() 和 notifyAll():用于线程间的协调与通信。
wait():使当前线程进入等待状态,直到其他线程调用对象的 notify() 或 notifyAll() 方法。
Object 类还提供了一些其他方法,如 clone()(用于创建对象的副本)、finalize()(在对象被垃圾回收之前调用)等。这些方法在需要时可以在自定义类中进行重写或使用。

48.BigInterger

创建 BigInteger 对象
可以使用以下方式创建 BigInteger 对象:

BigInteger(String val):使用给定的字符串创建一个 BigInteger 对象。

		
java

		
BigInteger num1 = new BigInteger("1234567890");

    
	
BigInteger(int val):使用给定的整数值创建一个 BigInteger 对象。

		
java

		
BigInteger num2 = new BigInteger(1234567890);

    
	
基本操作和方法
add(BigInteger val):将当前 BigInteger 对象与给定的 BigInteger 对象相加。

		
java

		
BigInteger sum = num1.add(num2);

    
	
subtract(BigInteger val):从当前 BigInteger 对象中减去给定的 BigInteger 对象。

		
java

		
BigInteger diff = num1.subtract(num2);

    
	
multiply(BigInteger val):将当前 BigInteger 对象与给定的 BigInteger 对象相乘。

		
java

		
BigInteger product = num1.multiply(num2);

    
	
divide(BigInteger val):将当前 BigInteger 对象除以给定的 BigInteger 对象。

		
java

		
BigInteger quotient = num1.divide(num2);

    
	
mod(BigInteger val):计算当前 BigInteger 对象除以给定的 BigInteger 对象的余数。

		
java

		
BigInteger remainder = num1.mod(num2);

    
	
compareTo(BigInteger val):将当前 BigInteger 对象与给定的 BigInteger 对象进行比较。

		
java

		
int comparison = num1.compareTo(num2);

    
	
toString():将 BigInteger 对象转换为字符串。

		
java

		
String str = num1.toString();

    
	
BigInteger 类还提供了其他一些方法,如 abs()(返回绝对值)、pow()(计算幂运算)、gcd()(计算最大公约数)等。可以根据需要查阅 Java 文档以获取更详细的信息。

49.BigDecimal

BigDecimal 是 Java 中提供的一个类,用于处理任意精度的十进制数。它可以处理比 double 或 float 类型更高精度的数值,并提供了一系列方法来执行基本的数值运算、比较和转换等操作。

以下是一些 BigDecimal 类的常用操作和方法:

创建 BigDecimal 对象
可以使用以下方式创建 BigDecimal 对象:

BigDecimal(String val):使用给定的字符串创建一个 BigDecimal 对象。

		
java

		
BigDecimal num1 = new BigDecimal("123.456");

    
	
BigDecimal(double val):使用给定的双精度浮点数值创建一个 BigDecimal 对象。

		
java

		
BigDecimal num2 = new BigDecimal(123.456);

    
	
基本操作和方法
add(BigDecimal val):将当前 BigDecimal 对象与给定的 BigDecimal 对象相加。

		
java

		
BigDecimal sum = num1.add(num2);

    
	
subtract(BigDecimal val):从当前 BigDecimal 对象中减去给定的 BigDecimal 对象。

		
java

		
BigDecimal diff = num1.subtract(num2);

    
	
multiply(BigDecimal val):将当前 BigDecimal 对象与给定的 BigDecimal 对象相乘。

		
java

		
BigDecimal product = num1.multiply(num2);

    
	
divide(BigDecimal val, int scale, RoundingMode roundingMode):将当前 BigDecimal 对象除以给定的 BigDecimal 对象,并指定精度和舍入模式。

		
java

		
BigDecimal quotient = num1.divide(num2, 2, RoundingMode.HALF_UP);

    
	
compareTo(BigDecimal val):将当前 BigDecimal 对象与给定的 BigDecimal 对象进行比较。

		
java

		
int comparison = num1.compareTo(num2);

    
	
toString():将 BigDecimal 对象转换为字符串。

		
java

		
String str = num1.toString();

    
	
BigDecimal 类还提供了其他一些方法,如 abs()(返回绝对值)、pow()(计算幂运算)、setScale()(设置精度)等。可以根据需要查阅 Java 文档以获取更详细的信息。

50.正则表达式

正则表达式(Regular Expression)是一种用于描述、匹配和操作字符串的强大工具。它使用一种模式来定义字符串的特征,可以用于验证输入、搜索替换文本、提取信息等操作。

正则表达式由普通字符(字母、数字、符号)和元字符(具有特殊含义的字符)组成,可以使用不同的元字符来表示特定的匹配规则。以下是一些常用的正则表达式元字符和其含义:

.:匹配任意单个字符。
*:匹配前面的元素零次或多次。
+:匹配前面的元素一次或多次。
?:匹配前面的元素零次或一次。
[]:匹配方括号中的任意一个字符。
[^]:匹配除方括号中字符之外的任意一个字符。
():创建一个捕获组,用于提取匹配的子字符串。
\:转义字符,用于匹配特殊字符本身。
^:匹配字符串的开始位置。
$:匹配字符串的结束位置。
除了元字符,正则表达式还支持一些特殊的字符类别:

\d:匹配任意一个数字字符。
\D:匹配任意一个非数字字符。
\w:匹配任意一个字母、数字或下划线字符。
\W:匹配任意一个非字母、数字或下划线字符。
\s:匹配任意一个空白字符。
\S:匹配任意一个非空白字符。
正则表达式的使用可以通过 Java 的 Pattern 和 Matcher 类来实现。以下是一个简单的示例:

		
java

		
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegexExample {
    public static void main(String[] args) {
        String text = "Hello, 123456!";
        String pattern = "\\d+"; // 匹配一个或多个数字

        Pattern regex = Pattern.compile(pattern);
        Matcher matcher = regex.matcher(text);

        while (matcher.find()) {
            System.out.println("Matched: " + matcher.group());
        }
    }
}

    
	
上述示例中,使用正则表达式 \\d+ 匹配字符串中的一个或多个数字。通过 Pattern 类的 compile() 方法将正则表达式编译成模式,然后使用 Matcher 类的 matcher() 方法创建一个匹配器。最后,通过 find() 方法遍历匹配到的结果,并使用 group() 方法获取匹配到的子字符串。

51.爬虫

网络爬虫(Web Crawler)是一种自动化程序,用于从互联网上的网页中提取信息。它们通常被用于搜索引擎、数据挖掘、内容聚合等应用中,可以帮助用户快速地收集和分析大量的网络数据。

网络爬虫的工作原理:
发现网页链接:网络爬虫从一个或多个起始网页开始,首先下载该网页的内容,然后解析其中的链接,将这些链接添加到待访问的列表中。

下载网页内容:网络爬虫依次访问待访问列表中的链接,下载每个网页的内容,通常使用 HTTP 请求来获取网页的 HTML 内容。

解析网页内容:网络爬虫解析下载的网页内容,提取其中的文本、图像、链接等信息,以便后续处理和分析。

存储数据:爬虫将提取的信息存储在数据库、文件或内存中,以便后续处理和展示。

网络爬虫的实现方式:
编程语言:网络爬虫可以用多种编程语言实现,如 Python、Java、JavaScript 等。Python 的 requests 和 BeautifulSoup 库、Java 的 Jsoup 等常用工具可以帮助实现网络爬虫。

爬取策略:爬虫可以根据深度优先搜索(DFS)、广度优先搜索(BFS)等方式来遍历网页链接。同时,需要考虑爬取速度、重复页面处理、反爬虫机制等问题。

数据处理:爬虫可以对提取的数据进行清洗、去重、分析等处理,以便生成有用的信息或报告。

合法性和道德性:在实现网络爬虫时,需要遵守网站的爬取规则,尊重网站的隐私政策和版权法律,避免对目标网站造成不必要的负担。

网络爬虫是一个强大且有用的工具,但也需要谨慎使用,以避免滥用和侵犯他人的权益。在使用网络爬虫时,建议遵循合法合规的原则,并尊重网站所有者的权益和规定。

Java中爬虫的使用

在 Java 中实现网络爬虫可以使用各种库和框架来简化开发过程。以下是一些常用的 Java 爬虫库和框架:

Jsoup:Jsoup 是一款基于 Java 的 HTML 解析器,可以方便地从 HTML 文档中提取数据。它提供了类似于 jQuery 的选择器语法,使得解析和操作 HTML 文档变得简单和直观。

HttpClient:HttpClient 是 Apache 提供的一个强大的 HTTP 客户端库,可以用于发送 HTTP 请求、下载网页内容等操作。它提供了丰富的功能和配置选项,可以方便地处理各种网络请求和响应。

Selenium:Selenium 是一个用于自动化浏览器操作的工具,可以模拟用户在网页上的行为。它可以用于爬取动态网页、执行 JavaScript、填写表单等操作。

WebMagic:WebMagic 是一个开源的 Java 爬虫框架,提供了高度灵活的配置和扩展性。它支持多线程、分布式爬取、自动重试、代理设置等功能,并提供了简洁的 API 和注解,使得爬虫的开发变得更加简单。

使用这些库和框架,可以根据具体需求和实际情况来选择适合的工具。以下是一个使用 Jsoup 解析网页的示例:

		
java

		
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;

public class WebCrawlerExample {
    public static void main(String[] args) {
        try {
            // 下载网页内容
            Document doc = Jsoup.connect("https://example.com").get();

            // 解析网页内容
            Elements links = doc.select("a[href]");
            for (Element link : links) {
                String url = link.attr("href");
                System.out.println(url);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

    
	
上述示例中,使用 Jsoup 的 connect() 方法下载指定网页的内容,并使用 select() 方法选择所有的链接元素。然后,遍历每个链接元素,提取其中的 href 属性值,即网页链接。

52.api的时间

时间 API(Time API)是指提供时间相关功能和服务的应用程序接口(API)。它可以用于获取当前时间、转换时区、计算时间差、执行时间格式化等操作。

时间 API 可以提供以下功能:

获取当前时间:通过调用 API,可以获取当前的日期和时间,以及时区信息。

时区转换:可以根据需要将时间从一个时区转换到另一个时区,以便在不同地区正确显示时间。

时间计算:可以进行日期和时间的加减运算,计算时间差或在特定日期上增加或减少一定的时间。

时间格式化:可以将时间对象格式化为特定的字符串表示,或将字符串解析为时间对象。

常用的时间 API 包括 Java 的 java.time 包中的类、JavaScript 的 Date 对象、Python 的 datetime 模块等。这些 API 提供了丰富的方法和功能,使得时间处理变得更加简单和方便。

以下是一个使用 Java 的 java.time 包中的时间 API 的示例:

		
java

		
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class TimeAPIExample {
    public static void main(String[] args) {
        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();
        System.out.println("当前时间:" + now);

        // 时间格式化
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formattedTime = now.format(formatter);
        System.out.println("格式化后的时间:" + formattedTime);

        // 时间计算
        LocalDateTime futureTime = now.plusDays(7);
        System.out.println("一周后的时间:" + futureTime);
    }
}

    
	
上述示例中,使用 LocalDateTime.now() 方法获取当前时间,然后使用 DateTimeFormatter 对象将时间格式化为指定的字符串表示。接着,使用 plusDays() 方法在当前时间上增加了 7 天,得到一周后的时间。

53.包装类

包装类(Wrapper Class)是在面向对象编程中用于包装基本数据类型的类。它们提供了一种将基本数据类型转换为对象的方式,并且可以在对象中执行更多的操作,如调用方法、使用泛型等。

在 Java 中,每个基本数据类型都对应有一个对应的包装类,如下所示:

byte 对应的包装类是 Byte
short 对应的包装类是 Short
int 对应的包装类是 Integer
long 对应的包装类是 Long
float 对应的包装类是 Float
double 对应的包装类是 Double
char 对应的包装类是 Character
boolean 对应的包装类是 Boolean
包装类提供了一些常用的方法和属性,用于操作和处理基本数据类型的值。例如,可以使用包装类来进行数值的转换、比较、求绝对值等操作。

以下是一个示例,展示如何使用包装类来操作基本数据类型:

		
java

		
Integer num1 = new Integer(10); // 使用构造函数创建 Integer 对象
Integer num2 = Integer.valueOf(20); // 使用 valueOf() 方法创建 Integer 对象

int result1 = num1.intValue() + num2.intValue(); // 将 Integer 对象转换为 int 类型进行相加
System.out.println("Result: " + result1);

int result2 = Integer.parseInt("30"); // 将字符串转换为 int 类型
System.out.println("Parsed result: " + result2);

boolean isEqual = num1.equals(num2); // 比较两个 Integer 对象是否相等
System.out.println("Is equal: " + isEqual);

    
	
在上述示例中,我们使用 Integer 类的构造函数和静态方法 valueOf() 来创建 Integer 对象。然后,使用 intValue() 方法将 Integer 对象转换为 int 类型进行相加。还可以使用 parseInt() 方法将字符串转换为 int 类型,使用 equals() 方法比较两个 Integer 对象是否相等。

54.常见算法

排序算法:
冒泡排序(Bubble Sort):通过多次比较和交换来将最小(或最大)的元素逐步移动到数组的一端。

快速排序(Quick Sort):通过选择一个基准值,将数组分为两部分,分别比基准值小和大,然后递归地对两部分进行排序。

插入排序(Insertion Sort):将未排序的元素逐个插入到已排序的部分中,直到整个数组有序。

选择排序(Selection Sort):每次从未排序的部分中选择最小(或最大)的元素,放到已排序的部分的末尾。

搜索算法:
线性搜索(Linear Search):逐个遍历数组或列表中的元素,找到目标值的位置。

二分搜索(Binary Search):对有序数组进行二分查找,通过比较目标值与中间值的大小来缩小搜索范围。

广度优先搜索(Breadth-First Search,BFS):从起始节点开始,逐层遍历图中的节点,直到找到目标节点。

深度优先搜索(Depth-First Search,DFS):从起始节点开始,沿着一条路径一直深入直到找到目标节点或无法继续为止。

数据结构:
数组(Array):一组连续存储的元素,通过索引访问元素,适合随机访问。

链表(Linked List):由节点组成的线性数据结构,每个节点包含数据和指向下一个节点的指针。

栈(Stack):先进后出(FILO)的数据结构,只能在栈顶进行插入和删除操作。

队列(Queue):先进先出(FIFO)的数据结构,只能在队尾插入,在队头删除。

动态规划算法:
最长公共子序列(Longest Common Subsequence):用于比较两个序列的相似度,找到它们之间的最长公共子序列。

背包问题(Knapsack Problem):给定一组物品的重量和价值,找到一个背包容量限制下能装下的最大价值物品的组合。

55.集合collection

以下是Java中常见的集合类:

List:有序集合,允许重复元素。常见的实现类有ArrayList、LinkedList和Vector。

Set:无序集合,不允许重复元素。常见的实现类有HashSet、LinkedHashSet和TreeSet。

Queue:队列集合,按照先进先出(FIFO)的顺序处理元素。常见的实现类有LinkedList和PriorityQueue。

Map:键值对集合,存储具有唯一键的元素。常见的实现类有HashMap、LinkedHashMap和TreeMap。

集合类提供了一系列方法来添加、删除、查询和操作集合中的元素。它们还提供了迭代器来遍历集合中的元素。

以下是一个示例,展示如何使用集合类:

		
java

		
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CollectionExample {
    public static void main(String[] args) {
        // List示例
        List<String> list = new ArrayList<>();
        list.add("Apple");
        list.add("Banana");
        list.add("Orange");
        System.out.println("List: " + list);

        // Set示例
        Set<String> set = new HashSet<>();
        set.add("Apple");
        set.add("Banana");
        set.add("Orange");
        System.out.println("Set: " + set);

        // Queue示例
        Queue<String> queue = new LinkedList<>();
        queue.add("Apple");
        queue.add("Banana");
        queue.add("Orange");
        System.out.println("Queue: " + queue);

        // Map示例
        Map<Integer, String> map = new HashMap<>();
        map.put(1, "Apple");
        map.put(2, "Banana");
        map.put(3, "Orange");
        System.out.println("Map: " + map);

        // 迭代集合
        for (String item : list) {
            System.out.println(item);
        }
    }
}

    
	
上述示例中,我们使用了ArrayList、HashSet、LinkedList和HashMap等集合类创建了不同类型的集合,并向其中添加元素。然后,我们使用循环遍历集合中的元素,并打印出来。

56.list遍历的方式

在Java中,有多种方式可以遍历List集合中的元素。以下是常见的几种遍历方式:

使用for循环遍历:通过索引访问List中的元素。
		
java

		
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Orange");

for (int i = 0; i < list.size(); i++) {
    String item = list.get(i);
    System.out.println(item);
}

    
	
使用增强for循环遍历:直接遍历List中的元素,无需索引。
		
java

		
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Orange");

for (String item : list) {
    System.out.println(item);
}

    
	
使用迭代器遍历:使用迭代器对象来遍历List中的元素。
		
java

		
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Orange");

Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
    String item = iterator.next();
    System.out.println(item);
}

    
	
使用Java 8的Stream API遍历:使用Stream流来遍历List中的元素。
		
java

		
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Orange");

list.stream().forEach(item -> System.out.println(item));

57.泛型

在Java中,泛型(Generics)是一种强类型编程的机制,它允许类、接口和方法在定义时使用类型参数,从而提高代码的灵活性和安全性。通过泛型,可以编写更加通用和类型安全的代码,减少类型转换的需要。

泛型的基本概念是在编写类、接口或方法时,使用一个或多个类型参数来表示具体的数据类型。在使用泛型时,可以指定具体的数据类型,使代码更加灵活和通用。

以下是泛型的基本语法示例:

		
java

		
// 定义一个泛型类
class Box<T> {
    private T value;

    public void setValue(T value) {
        this.value = value;
    }

    public T getValue() {
        return value;
    }
}

// 使用泛型类
Box<Integer> intBox = new Box<>();
intBox.setValue(10);
System.out.println("Integer Value: " + intBox.getValue());

Box<String> stringBox = new Box<>();
stringBox.setValue("Hello");
System.out.println("String Value: " + stringBox.getValue());

    
	
在上面的示例中,我们定义了一个泛型类 Box<T>,其中 T 是类型参数,表示一个占位符,可以在使用时指定具体的数据类型。通过使用泛型类 Box<T>,我们可以创建一个整型类型的 intBox 和一个字符串类型的 stringBox,并分别设置和获取对应的值。

58.数据结构

Java提供了许多内置的数据结构,用于存储和操作数据。以下是Java中常见的数据结构:

数组(Array):是一种线性数据结构,可以存储多个相同类型的元素。数组的长度是固定的,一旦创建后无法改变。

链表(LinkedList):是一种线性数据结构,由一系列节点组成,每个节点包含数据和指向下一个节点的引用。

栈(Stack):是一种后进先出(LIFO)的数据结构,可以通过push和pop操作在栈的顶部插入和删除元素。

队列(Queue):是一种先进先出(FIFO)的数据结构,可以通过enqueue和dequeue操作在队列的尾部插入和删除元素。

集合(Collection):是一组对象的容器,用于存储和操作多个对象。常见的集合类有List、Set和Map。

树(Tree):是一种非线性数据结构,由一系列节点组成,每个节点可以有多个子节点。常见的树结构有二叉树、二叉搜索树和平衡树等。

图(Graph):是一种非线性数据结构,由一组节点和边组成,用于表示各个节点之间的关系。

堆(Heap):是一种特殊的树结构,通常用于实现优先队列。

哈希表(Hashtable):是一种使用哈希函数进行快速查找的数据结构,常用于实现Map接口。

59.集合常见的底层原理

Java中常用的集合框架包括List、Set、Queue和Map。以下是它们的常见实现类以及底层原理:

List:有序集合,允许重复元素。常见的实现类有ArrayList、LinkedList和Vector。

ArrayList:基于数组实现,支持动态扩容,通过索引快速访问元素。
LinkedList:基于双向链表实现,支持快速插入和删除元素,但访问元素需要遍历链表。
Vector:类似于ArrayList,但是线程安全,性能相对较低。
Set:无序集合,不允许重复元素。常见的实现类有HashSet、LinkedHashSet和TreeSet。

HashSet:基于哈希表实现,通过哈希函数快速查找元素。
LinkedHashSet:在HashSet的基础上,使用链表维护元素的插入顺序。
TreeSet:基于红黑树(自平衡二叉搜索树)实现,元素按照自然顺序或自定义顺序排序。
Queue:队列集合,按照先进先出(FIFO)的顺序处理元素。常见的实现类有LinkedList和PriorityQueue。

LinkedList:可以当作队列或双端队列使用。
PriorityQueue:基于堆实现的优先队列,元素按照优先级排序。
Map:键值对集合,存储具有唯一键的元素。常见的实现类有HashMap、LinkedHashMap和TreeMap。

HashMap:基于哈希表实现,通过键的哈希值快速查找元素。
LinkedHashMap:在HashMap的基础上,使用链表维护元素的插入顺序。
TreeMap:基于红黑树实现,键按照自然顺序或自定义顺序排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值