Java常见代码大全:从基础语法到设计模式的实用指南
一、Java基础语法
(一)变量与数据类型
1. 基本数据类型
Java是一种强类型语言,每种数据类型都有明确的定义和范围。基本数据类型是Java中最基础的部分,它们是直接存储在栈内存中的简单数据类型,具有固定的大小和格式。
-
整数类型
byte:占用1个字节(8位),范围是-128到127。适用于存储占用空间较小的整数。byte b = 10;short:占用2个字节(16位),范围是-32768到32767。比byte范围大,但仍然比int小。short s = 1000;int:占用4个字节(32位),范围是-2^31到2^31-1,即-2147483648到2147483647。这是最常用的整数类型。int i = 100000;long:占用8个字节(64位),范围是-2^63到2^63-1,即-9223372036854775808到9223372036854775807。当需要存储较大的整数时使用。long l = 10000000000L; // 注意:以L结尾表示是long类型
-
浮点类型
float:占用4个字节(32位),表示单精度浮点数。它的精度较低,但占用空间小。float f = 3.14f; // 注意:以f结尾表示是float类型double:占用8个字节(64位),表示双精度浮点数。它的精度高,是浮点数的默认类型。double d = 3.141592653589793;
-
字符类型
char:占用2个字节(16位),表示一个Unicode字符。它的范围是'\u0000'(即0)到'\uffff'(即65535)。char c = 'A'; char c1 = '\u0041'; // Unicode表示法,等同于'A'
-
布尔类型
boolean:只有两个值:true和false。它通常用于逻辑判断。boolean flag = true;
2. 包装类
Java为每种基本数据类型都提供了一个对应的包装类(Wrapper Class),这些包装类是类,而不是原始数据类型。包装类允许我们将基本数据类型当作对象来处理。
-
包装类的作用
- 自动装箱:将基本数据类型自动转换为对应的包装类。例如:
Integer i = 10; // 自动装箱,将int转换为Integer - 自动拆箱:将包装类自动转换为对应的基本数据类型。例如:
int j = i; // 自动拆箱,将Integer转换为int
- 自动装箱:将基本数据类型自动转换为对应的包装类。例如:
-
包装类的使用场景
- 当需要将基本数据类型作为对象存储在集合中时,必须使用包装类。例如:
List<Integer> list = new ArrayList<>(); list.add(10); // 自动装箱 int num = list.get(0); // 自动拆箱
- 当需要将基本数据类型作为对象存储在集合中时,必须使用包装类。例如:
-
包装类与基本数据类型的区别
- 包装类是对象,而基本数据类型是原始类型。包装类可以为
null,而基本数据类型不能为null。 - 包装类在性能上比基本数据类型稍差,因为它们需要额外的内存空间来存储对象的元数据。
- 包装类是对象,而基本数据类型是原始类型。包装类可以为
3. 类型转换
在Java中,类型转换分为自动类型转换和强制类型转换。
-
自动类型转换
- 当从较小范围的类型向较大范围的类型转换时,Java会自动进行类型转换。例如:
int i = 10; long l = i; // 自动将int转换为long double d = l; // 自动将long转换为double
- 当从较小范围的类型向较大范围的类型转换时,Java会自动进行类型转换。例如:
-
强制类型转换
- 当需要从较大范围的类型向较小范围的类型转换时,必须使用强制类型转换。强制类型转换可能会导致数据丢失。例如:
double d = 3.141592653589793; int i = (int) d; // 强制将double转换为int,小数部分会被截断
- 当需要从较大范围的类型向较小范围的类型转换时,必须使用强制类型转换。强制类型转换可能会导致数据丢失。例如:
4. 常见代码示例
public class DataTypeExample {
public static void main(String[] args) {
// 基本数据类型
byte b = 10;
short s = 1000;
int i = 100000;
long l = 10000000000L;
float f = 3.14f;
double d = 3.141592653589793;
char c = 'A';
boolean flag = true;
// 包装类
Integer integer = 10; // 自动装箱
int num = integer; // 自动拆箱
// 类型转换
long longValue = i; // 自动类型转换
int intValue = (int) l; // 强制类型转换
// 输出
System.out.println("byte: " + b);
System.out.println("short: " + s);
System.out.println("int: " + i);
System.out.println("long: " + l);
System.out.println("float: " + f);
System.out.println("double: " + d);
System.out.println("char: " + c);
System.out.println("boolean: " + flag);
System.out.println("包装类Integer: " + integer);
System.out.println("自动拆箱后的int: " + num);
System.out.println("自动类型转换后的long: " + longValue);
System.out.println("强制类型转换后的int: " + intValue);
}
}
(二)运算符
Java提供了多种运算符,用于执行各种数学和逻辑运算。运算符是Java编程中不可或缺的一部分,掌握它们的使用方法对于编写高效的代码至关重要。
1. 算术运算符
算术运算符用于执行基本的数学运算,如加法、减法、乘法、除法和取模。
-
加法运算符
+- 用于两个数值相加。
int a = 10; int b = 20; int sum = a + b; // 结果为30
- 用于两个数值相加。
-
减法运算符
-- 用于两个数值相减。
int a = 20; int b = 10; int difference = a - b; // 结果为10
- 用于两个数值相减。
-
乘法运算符
*- 用于两个数值相乘。
int a = 10; int b = 20; int product = a * b; // 结果为200
- 用于两个数值相乘。
-
除法运算符
/- 用于两个数值相除。如果两个操作数都是整数,则结果也是整数;如果有一个操作数是浮点数,则结果是浮点数。
int a = 20; int b = 10; int quotient = a / b; // 结果为2 double c = 20.0; double d = 10.0; double quotientDouble = c / d; // 结果为2.0
- 用于两个数值相除。如果两个操作数都是整数,则结果也是整数;如果有一个操作数是浮点数,则结果是浮点数。
-
取模运算符
%- 用于计算两个数值相除的余数。
int a = 20; int b = 3; int remainder = a % b; // 结果为2
- 用于计算两个数值相除的余数。
2. 关系运算符
关系运算符用于比较两个数值的大小,结果是一个布尔值(true或false)。
-
等于
==- 用于比较两个值是否相等。
int a = 10; int b = 20; boolean isEqual = a == b; // 结果为false
- 用于比较两个值是否相等。
-
不等于
!=- 用于比较两个值是否不相等。
int a = 10; int b = 20; boolean isNotEqual = a != b; // 结果为true
- 用于比较两个值是否不相等。
-
大于
>- 用于比较一个值是否大于另一个值。
int a = 20; int b = 10; boolean isGreaterThan = a > b; // 结果为true
- 用于比较一个值是否大于另一个值。
-
小于
<- 用于比较一个值是否小于另一个值。
int a = 10; int b = 20; boolean isLessThan = a < b; // 结果为true
- 用于比较一个值是否小于另一个值。
-
大于等于
>=- 用于比较一个值是否大于或等于另一个值。
int a = 20; int b = 10; boolean isGreaterThanOrEqual = a >= b; // 结果为true
- 用于比较一个值是否大于或等于另一个值。
-
小于等于
<=- 用于比较一个值是否小于或等于另一个值。
int a = 10; int b = 20; boolean isLessThanOrEqual = a <= b; // 结果为true
- 用于比较一个值是否小于或等于另一个值。
3. 逻辑运算符
逻辑运算符用于组合多个条件,结果是一个布尔值(true或false)。
-
逻辑与
&&- 用于表示“并且”的关系。只有当两个条件都为
true时,结果才为true。int a = 10; int b = 20; boolean result = (a > 5) && (b > 15); // 结果为true
- 用于表示“并且”的关系。只有当两个条件都为
-
逻辑或
||- 用于表示“或者”的关系。只要有一个条件为
true,结果就为true。int a = 10; int b = 20; boolean result = (a > 15) || (b > 15); // 结果为true
- 用于表示“或者”的关系。只要有一个条件为
-
逻辑非
!- 用于对一个布尔值取反。如果原值为
true,则结果为false;如果原值为false,则结果为true。boolean flag = true; boolean result = !flag; // 结果为false
- 用于对一个布尔值取反。如果原值为
4. 赋值运算符
赋值运算符用于将一个值赋给一个变量。
-
简单赋值
=- 用于将一个值赋给一个变量。
int a = 10;
- 用于将一个值赋给一个变量。
-
复合赋值运算符
-
加法赋值
+=:将变量与另一个值相加后赋值给变量。int a = 10; a += 5; // 等同于a = a + 5,结果a为15 -
减法赋值
-=:将变量与另一个值相减后赋值给变量。int a = 10; a -= 5; // 等同于a = a - 5,结果a为5 -
乘法赋值
*=:将变量与另一个值相乘后赋值给变量。int a = 10; a *= 5; // 等同于a = a * 5,结果a为50 -
除法赋值
/=:将变量与另一个值相除后赋值给变量。int a = 10; a /= 5; // 等同于a = a / 5,结果a为2 -
取模赋值
%=:将变量与另一个值取模后赋值给变量。int a = 10; a %= 3; // 等同于a = a % 3,结果a为1
-
5. 常见代码示例
public class OperatorExample {
public static void main(String[] args) {
// 算术运算符
int a = 10;
int b = 3;
int sum = a + b; // 加法
int difference = a - b; // 减法
int product = a * b; // 乘法
int quotient = a / b; // 除法
int remainder = a % b; // 取模
// 关系运算符
boolean isEqual = a == b; // 等于
boolean isNotEqual = a != b; // 不等于
boolean isGreaterThan = a > b; // 大于
boolean isLessThan = a < b; // 小于
boolean isGreaterThanOrEqual = a >= b; // 大于等于
boolean isLessThanOrEqual = a <= b; // 小于等于
// 逻辑运算符
boolean flag1 = true;
boolean flag2 = false;
boolean andResult = flag1 && flag2; // 逻辑与
boolean orResult = flag1 || flag2; // 逻辑或
boolean notResult = !flag1; // 逻辑非
// 赋值运算符
int x = 10;
x += 5; // 加法赋值
x -= 3; // 减法赋值
x *= 2; // 乘法赋值
x /= 4; // 除法赋值
x %= 3; // 取模赋值
// 输出结果
System.out.println("加法结果: " + sum);
System.out.println("减法结果: " + difference);
System.out.println("乘法结果: " + product);
System.out.println("除法结果: " + quotient);
System.out.println("取模结果: " + remainder);
System.out.println("等于: " + isEqual);
System.out.println("不等于: " + isNotEqual);
System.out.println("大于: " + isGreaterThan);
System.out.println("小于: " + isLessThan);
System.out.println("大于等于: " + isGreaterThanOrEqual);
System.out.println("小于等于: " + isLessThanOrEqual);
System.out.println("逻辑与结果: " + andResult);
System.out.println("逻辑或结果: " + orResult);
System.out.println("逻辑非结果: " + notResult);
System.out.println("加法赋值后的x: " + x);
System.out.println("减法赋值后的x: " + x);
System.out.println("乘法赋值后的x: " + x);
System.out.println("除法赋值后的x: " + x);
System.out.println("取模赋值后的x: " + x);
}
}
(三)控制流程
控制流程语句用于控制程序的执行顺序。Java提供了多种控制流程语句,包括条件语句和循环语句。
1. 条件语句
条件语句用于根据条件的真假来决定程序的执行路径。
-
if-else语句if语句用于判断一个条件是否为true。如果条件为true,则执行if块中的代码;如果条件为false,则可以执行else块中的代码。int a = 10; if (a > 5) { System.out.println("a大于5"); } else { System.out.println("a不大于5"); }
-
if-else if-else语句- 当需要判断多个条件时,可以使用
if-else if-else语句。int score = 85; if (score >= 90) { System.out.println("优秀"); } else if (score >= 80) { System.out.println("良好"); } else if (score >= 60) { System.out.println("及格"); } else { System.out.println("不及格"); }
- 当需要判断多个条件时,可以使用
-
switch-case语句switch-case语句用于根据一个变量的值来选择执行不同的代码块。它通常用于替代多个if-else语句。int month = 3; switch (month) { case 1: System.out.println("一月"); break; case 2: System.out.println("二月"); break; case 3: System.out.println("三月"); break; // 其他月份... default: System.out.println("无效的月份"); break; }
2. 循环语句
循环语句用于重复执行一段代码,直到满足某个条件为止。
-
for循环for循环是最常用的循环语句之一。它通常用于已知循环次数的场景。for (int i = 0; i < 5; i++) { System.out.println("循环次数: " + i); }
-
while循环while循环用于在条件为true时重复执行一段代码。它在循环开始前先判断条件。int i = 0; while (i < 5) { System.out.println("循环次数: " + i); i++; }
-
do-while循环do-while循环与while循环类似,但它在循环开始后先执行一次代码,然后再判断条件。因此,do-while循环至少会执行一次。int i = 0; do { System.out.println("循环次数: " + i); i++; } while (i < 5);
3. 跳转语句
跳转语句用于在循环中改变程序的执行流程。
-
break语句break语句用于终止循环或switch-case语句。for (int i = 0; i < 10; i++) { if (i == 5) { break; // 终止循环 } System.out.println("循环次数: " + i); }
-
continue语句continue语句用于跳过当前循环的剩余部分,并继续执行下一次循环。for (int i = 0; i < 10; i++) { if (i % 2 == 0) { continue; // 跳过偶数 } System.out.println("循环次数: " + i); }
4. 常见代码示例
public class ControlFlowExample {
public static void main(String[] args) {
// if-else语句
int a = 10;
if (a > 5) {
System.out.println("a大于5");
} else {
System.out.println("a不大于5");
}
// if-else if-else语句
int score = 85;
if (score >= 90) {
System.out.println("优秀");
} else if (score >= 80) {
System.out.println("良好");
} else if (score >= 60) {
System.out.println("及格");
} else {
System.out.println("不及格");
}
// switch-case语句
int month = 3;
switch (month) {
case 1:
System.out.println("一月");
break;
case 2:
System.out.println("二月");
break;
case 3:
System.out.println("三月");
break;
// 其他月份...
default:
System.out.println("无效的月份");
break;
}
// for循环
for (int i = 0; i < 5; i++) {
System.out.println("for循环次数: " + i);
}
// while循环
int j = 0;
while (j < 5) {
System.out.println("while循环次数: " + j);
j++;
}
// do-while循环
int k = 0;
do {
System.out.println("do-while循环次数: " + k);
k++;
} while (k < 5);
// break语句
for (int i = 0; i < 10; i++) {
if (i == 5) {
break; // 终止循环
}
System.out.println("break循环次数: " + i);
}
// continue语句
for (int i = 0; i < 10; i++) {
if (i % 2 == 0) {
continue; // 跳过偶数
}
System.out.println("continue循环次数: " + i);
}
}
}
(四)数组
数组是一种可以存储多个相同类型数据的容器。在Java中,数组的大小是固定的,一旦创建后不能改变。
1. 数组的声明与初始化
-
声明数组
- 声明数组时,需要指定数组的类型和名称。
int[] array; // 声明一个整型数组
- 声明数组时,需要指定数组的类型和名称。
-
初始化数组
-
静态初始化:在声明数组时直接指定数组的元素。
int[] array = {1, 2, 3, 4, 5}; -
动态初始化:指定数组的大小,然后逐个赋值。
int[] array = new int[5]; // 创建一个长度为5的数组 array[0] = 1; array[1] = 2; array[2] = 3; array[3] = 4; array[4] = 5;
-
2. 数组的遍历
-
使用
for循环遍历数组int[] array = {1, 2, 3, 4, 5}; for (int i = 0; i < array.length; i++) { System.out.println(array[i]); } -
使用
for-each循环遍历数组int[] array = {1, 2, 3, 4, 5}; for (int num : array) { System.out.println(num); }
3. 多维数组
多维数组是数组的数组,可以用来存储更复杂的数据结构。
-
二维数组
-
静态初始化
int[][] matrix = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; -
动态初始化
int[][] matrix = new int[3][3]; matrix[0][0] = 1; matrix[0][1] = 2; matrix[0][2] = 3; matrix[1][0] = 4; matrix[1][1] = 5; matrix[1][2] = 6; matrix[2][0] = 7; matrix[2][1] = 8; matrix[2][2] = 9;
-
-
遍历二维数组
int[][] matrix = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} }; for (int i = 0; i < matrix.length; i++) { for (int j = 0; j < matrix[i].length; j++) { System.out.print(matrix[i][j] + " "); } System.out.println(); }
4. 常见代码示例
public class ArrayExample {
public static void main(String[] args) {
// 一维数组
int[] array = {1, 2, 3, 4, 5};
System.out.println("一维数组的元素:");
for (int num : array) {
System.out.println(num);
}
// 二维数组
int[][] matrix = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
System.out.println("二维数组的元素:");
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
}
System.out.println();
}
// 动态初始化一维数组
int[] dynamicArray = new int[5];
for (int i = 0; i < dynamicArray.length; i++) {
dynamicArray[i] = i + 1;
}
System.out.println("动态初始化的一维数组:");
for (int num : dynamicArray) {
System.out.println(num);
}
// 动态初始化二维数组
int[][] dynamicMatrix = new int[3][3];
for (int i = 0; i < dynamicMatrix.length; i++) {
for (int j = 0; j < dynamicMatrix[i].length; j++) {
dynamicMatrix[i][j] = i * 3 + j + 1;
}
}
System.out.println("动态初始化的二维数组:");
for (int i = 0; i < dynamicMatrix.length; i++) {
for (int j = 0; j < dynamicMatrix[i].length; j++) {
System.out.print(dynamicMatrix[i][j] + " ");
}
System.out.println();
}
}
}
(五)方法
方法是一段可以重复使用的代码块,用于完成特定的功能。在Java中,方法是类的一部分,通过方法可以实现代码的封装和复用。
1. 方法的定义
方法的定义包括方法的返回类型、方法名、参数列表和方法体。
- 返回类型:方法执行完成后返回的值的类型。如果方法不返回任何值,则返回类型为
void。 - 方法名:方法的名称,用于标识方法。
- 参数列表:方法的输入参数,可以有多个参数,也可以没有参数。
- 方法体:方法的具体实现部分,包含一系列的语句。
public class MethodExample {
// 定义一个无参方法
public void sayHello() {
System.out.println("Hello, World!");
}
// 定义一个有参方法
public int add(int a, int b) {
return a + b;
}
// 定义一个带返回值的方法
public String getGreeting(String name) {
return "Hello, " + name + "!";
}
public static void main(String[] args) {
MethodExample example = new MethodExample();
// 调用无参方法
example.sayHello();
// 调用有参方法
int result = example.add(10, 20);
System.out.println("加法结果: " + result);
// 调用带返回值的方法
String greeting = example.getGreeting("Kimi");
System.out.println(greeting);
}
}
2. 方法的重载
方法重载是指在同一个类中,允许定义多个同名的方法,但这些方法的参数列表必须不同(参数的类型、个数或顺序不同)。方法重载允许我们根据不同的输入参数调用不同的方法实现。
public class MethodOverloadingExample {
// 方法重载:无参数
public void print() {
System.out.println("无参数的方法");
}
// 方法重载:一个参数
public void print(String message) {
System.out.println("字符串参数的方法: " + message);
}
// 方法重载:两个参数
public void print(String message, int num) {
System.out.println("字符串和整数参数的方法: " + message + ", " + num);
}
public static void main(String[] args) {
MethodOverloadingExample example = new MethodOverloadingExample();
// 调用重载方法
example.print(); // 调用无参数的方法
example.print("Hello"); // 调用一个参数的方法
example.print("Hello", 123); // 调用两个参数的方法
}
}
3. 方法的递归
递归是一种方法调用自身的技术。递归通常用于解决可以分解为相同问题的子问题的场景。
public class RecursiveExample {
// 定义一个递归方法:计算阶乘
public int factorial(int n) {
if (n == 1) {
return 1; // 递归终止条件
} else {
return n * factorial(n - 1); // 递归调用
}
}
public static void main(String[] args) {
RecursiveExample example = new RecursiveExample();
// 调用递归方法
int result = example.factorial(5);
System.out.println("5的阶乘是: " + result);
}
}
(六)类与对象
类是Java中最重要的概念之一,它是对象的模板,定义了对象的结构和行为。对象是类的实例,是类的具体实现。
1. 类的定义
类的定义包括类的名称、成员变量和成员方法。
- 成员变量:类的属性,用于存储对象的状态。
- 成员方法:类的行为,用于定义对象的操作。
public class Person {
// 成员变量
private String name;
private int age;
// 构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 成员方法:获取姓名
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;
}
// 成员方法:打印个人信息
public void printInfo() {
System.out.println("姓名: " + name + ", 年龄: " + age);
}
}
2. 对象的创建与使用
对象是类的实例,可以通过new关键字创建对象。
public class ObjectExample {
public static void main(String[] args) {
// 创建Person对象
Person person = new Person("Kimi", 25);
// 调用对象的方法
person.printInfo(); // 输出:姓名: Kimi, 年龄: 25
// 修改对象的属性
person.setName("Alice");
person.setAge(30);
// 再次调用方法
person.printInfo(); // 输出:姓名: Alice, 年龄: 30
}
}
3. this关键字
this关键字用于引用类的当前实例。它通常用于区分同名的成员变量和局部变量。
public class ThisExample {
private int num;
public ThisExample(int num) {
this.num = num; // 使用this区分成员变量和局部变量
}
public void printNum() {
System.out.println("num的值是: " + this.num); // 使用this引用成员变量
}
public static void main(String[] args) {
ThisExample example = new ThisExample(100);
example.printNum(); // 输出:num的值是: 100
}
}
4. 构造方法
构造方法是类的一种特殊方法,用于在创建对象时初始化对象。构造方法的名称必须与类名相同,并且没有返回值。
-
无参构造方法
- 如果没有显式定义构造方法,Java会提供一个默认的无参构造方法。
public class Person { private String name; private int age; // 无参构造方法 public Person() { } // 有参构造方法 public Person(String name, int age) { this.name = name; this.age = age; } }
- 如果没有显式定义构造方法,Java会提供一个默认的无参构造方法。
-
有参构造方法
- 有参构造方法用于在创建对象时直接初始化对象的属性。
Person person = new Person("Kimi", 25);
- 有参构造方法用于在创建对象时直接初始化对象的属性。
5. 常见代码示例
public class ClassAndObjectExample {
// 定义一个类
public static class Person {
private String name;
private int age;
// 无参构造方法
public Person() {
}
// 有参构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// 成员方法:获取姓名
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;
}
// 成员方法:打印个人信息
public void printInfo() {
System.out.println("姓名: " + name + ", 年龄: " + age);
}
}
public static void main(String[] args) {
// 创建对象
Person person1 = new Person(); // 使用无参构造方法
person1.setName("Kimi");
person1.setAge(25);
person1.printInfo(); // 输出:姓名: Kimi, 年龄: 25
Person person2 = new Person("Alice", 30); // 使用有参构造方法
person2.printInfo(); // 输出:姓名: Alice, 年龄: 30
}
}
(七)继承
继承是面向对象编程的核心概念之一,它允许一个类继承另一个类的属性和方法。通过继承,可以实现代码的复用和扩展。
1. 继承的语法
在Java中,继承使用extends关键字来实现。子类继承父类后,可以访问父类的非私有成员变量和方法。
public class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + "正在吃东西");
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name); // 调用父类的构造方法
}
public void bark() {
System.out.println(name + "正在叫");
}
}
2. 方法的重写
方法重写是指子类可以重新定义父类的方法。重写的方法必须与父类的方法具有相同的方法名、参数列表和返回类型。
public class Animal {
public void makeSound() {
System.out.println("动物发出声音");
}
}
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("狗汪汪叫");
}
}
3. super关键字
super关键字用于引用父类的成员变量和方法。它通常用于调用父类的构造方法或访问父类的成员变量。
public class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class Dog extends Animal {
private String breed;
public Dog(String name, String breed) {
super(name); // 调用父类的构造方法
this.breed = breed;
}
public void printInfo() {
System.out.println("名字: " + super.getName() + ", 品种: " + breed);
}
}
4. 常见代码示例
public class InheritanceExample {
// 定义父类
public static class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public void eat() {
System.out.println(name + "正在吃东西");
}
public void makeSound() {
System.out.println(name + "发出声音");
}
}
// 定义子类
public static class Dog extends Animal {
private String breed;
public Dog(String name, String breed) {
super(name); // 调用父类的构造方法
this.breed = breed;
}
@Override
public void makeSound() {
System.out.println(name + "汪汪叫");
}
public void printInfo() {
System.out.println("名字: " + super.getName() + ", 品种: " + breed);
}
}
public static void main(String[] args) {
// 创建父类对象
Animal animal = new Animal("动物");
animal.eat(); // 输出:动物正在吃东西
animal.makeSound(); // 输出:动物发出声音
// 创建子类对象
Dog dog = new Dog("小狗", "哈士奇");
dog.eat(); // 输出:小狗正在吃东西(继承自父类)
dog.makeSound(); // 输出:小狗汪汪叫(重写的方法)
dog.printInfo(); // 输出:名字: 小狗, 品种: 哈士奇
}
}
(八)多态
多态是指同一个方法在不同的对象上调用时,可以有不同的行为。多态是面向对象编程的三大特性之一,它允许我们编写更通用的代码。
1. 方法重载与方法覆盖的区别
-
方法重载(Overloading)
- 在同一个类中,允许定义多个同名的方法,但这些方法的参数列表必须不同。
- 方法重载是编译时多态的体现。
-
方法覆盖(Overriding)
- 在子类中重新定义父类的方法。被覆盖的方法必须具有相同的方法名、参数列表和返回类型。
- 方法覆盖是运行时多态的体现。
2. 动态绑定与静态绑定
-
静态绑定(Static Binding)
- 在编译时确定方法的调用。静态绑定通常用于方法重载。
-
动态绑定(Dynamic Binding)
- 在运行时确定方法的调用。动态绑定通常用于方法覆盖。
3. instanceof运算符
instanceof运算符用于判断一个对象是否是某个类的实例。
public class PolymorphismExample {
// 定义父类
public static class Animal {
public void makeSound() {
System.out.println("动物发出声音");
}
}
// 定义子类
public static class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("狗汪汪叫");
}
}
public static void main(String[] args) {
// 创建父类对象
Animal animal = new Animal();
animal.makeSound(); // 输出:动物发出声音
// 创建子类对象
Animal dog = new Dog();
dog.makeSound(); // 输出:狗汪汪叫(动态绑定)
// 使用instanceof判断对象类型
if (dog instanceof Dog) {
System.out.println("dog是Dog类的实例");
} else {
System.out.println("dog不是Dog类的实例");
}
}
}
(九)接口与抽象类
接口和抽象类是Java中用于实现抽象编程的两种机制。它们都允许我们定义方法的签名,但接口和抽象类在实现细节上有很大的不同。
1. 接口
接口是一种特殊的类,它只能包含常量和抽象方法。接口中的方法默认是public和abstract的,而接口中的变量默认是public、static和final的。
-
接口的定义
public interface Animal { void makeSound(); // 默认是public abstract } -
接口的实现
public class Dog implements Animal { @Override public void makeSound() { System.out.println("狗汪汪叫"); } }
2. 抽象类
抽象类是一种不能被实例化的类,它允许我们定义抽象方法。抽象方法没有实现,必须在子类中被实现。
-
抽象类的定义
public abstract class Animal { public abstract void makeSound(); // 抽象方法 } -
抽象类的继承
public class Dog extends Animal { @Override public void makeSound() { System.out.println("狗汪汪叫"); } }
3. 接口与抽象类的区别
-
接口
- 接口只能包含常量和抽象方法。
- 接口中的方法默认是
public和abstract的。 - 接口中的变量默认是
public、static和final的。 - 一个类可以实现多个接口。
-
抽象类
- 抽象类可以包含抽象方法和具体方法。
- 抽象类中的方法可以有实现。
- 抽象类中的变量可以是任意修饰符。
- 一个类只能继承一个抽象类。
4. 常见代码示例
public class InterfaceAndAbstractClassExample {
// 定义接口
public static interface Animal {
void makeSound();
}
// 定义抽象类
public static abstract class AbstractAnimal {
public abstract void makeSound();
}
// 实现接口
public static class Dog implements Animal {
@Override
public void makeSound() {
System.out.println("狗汪汪叫");
}
}
// 继承抽象类
public static class Cat extends AbstractAnimal {
@Override
public void makeSound() {
System.out.println("猫喵喵叫");
}
}
public static void main(String[] args) {
// 创建接口的实例
Animal dog = new Dog();
dog.makeSound(); // 输出:狗汪汪叫
// 创建抽象类的实例
AbstractAnimal cat = new Cat();
cat.makeSound(); // 输出:猫喵喵叫
}
}
(十)内部类
内部类是定义在另一个类
内部的类。内部类可以访问外部类的成员变量和方法,而外部类也可以访问内部类的成员变量和方法。
1. 成员内部类
成员内部类是定义在类的成员位置的类。它可以直接访问外部类的成员变量和方法。
public class OuterClass {
private String name = "Kimi";
public class InnerClass {
public void printName() {
System.out.println("外部类的名称: " + name);
}
}
}
2. 局部内部类
局部内部类是定义在方法内部的类。它只能在该方法中使用。
public class OuterClass {
public void printInfo() {
class LocalInnerClass {
public void printMessage() {
System.out.println("这是一个局部内部类");
}
}
LocalInnerClass localInner = new LocalInnerClass();
localInner.printMessage();
}
}
3. 匿名内部类
匿名内部类是没有名称的内部类。它通常用于创建接口或抽象类的实例。
public class OuterClass {
public void printInfo() {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("这是一个匿名内部类");
}
};
runnable.run();
}
}
4. 静态内部类
静态内部类是定义在外部类内部的静态类。它不能访问外部类的非静态成员变量和方法,但可以访问静态成员变量和方法。
public class OuterClass {
private static String name = "Kimi";
public static class StaticInnerClass {
public void printName() {
System.out.println("外部类的名称: " + name);
}
}
}
5. 常见代码示例
public class InnerClassExample {
// 成员内部类
public static class OuterClass {
private String name = "Kimi";
public class InnerClass {
public void printName() {
System.out.println("外部类的名称: " + name);
}
}
}
// 局部内部类
public static class LocalInnerClassExample {
public void printInfo() {
class LocalInnerClass {
public void printMessage() {
System.out.println("这是一个局部内部类");
}
}
LocalInnerClass localInner = new LocalInnerClass();
localInner.printMessage();
}
}
// 匿名内部类
public static class AnonymousInnerClassExample {
public void printInfo() {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("这是一个匿名内部类");
}
};
runnable.run();
}
}
// 静态内部类
public static class StaticInnerClassExample {
private static String name = "Kimi";
public static class StaticInnerClass {
public void printName() {
System.out.println("外部类的名称: " + name);
}
}
}
public static void main(String[] args) {
// 成员内部类
OuterClass outer = new OuterClass();
OuterClass.InnerClass inner = outer.new InnerClass();
inner.printName(); // 输出:外部类的名称: Kimi
// 局部内部类
LocalInnerClassExample example1 = new LocalInnerClassExample();
example1.printInfo(); // 输出:这是一个局部内部类
// 匿名内部类
AnonymousInnerClassExample example2 = new AnonymousInnerClassExample();
example2.printInfo(); // 输出:这是一个匿名内部类
// 静态内部类
StaticInnerClassExample.StaticInnerClass staticInner = new StaticInnerClassExample.StaticInnerClass();
staticInner.printName(); // 输出:外部类的名称: Kimi
}
}
(十一)Java集合框架
Java集合框架提供了一系列的接口和实现类,用于存储和管理对象集合。集合框架的主要接口包括Collection、List、Set和Map。
1. 集合接口与实现类
-
Collection接口Collection是集合框架的根接口,它定义了集合的基本操作,如添加、删除和遍历元素。
-
List接口List接口继承自Collection接口,它是一个有序的集合,允许重复的元素。ArrayList:基于动态数组实现的List,适合频繁的随机访问。LinkedList:基于双向链表实现的List,适合频繁的插入和删除操作。
-
Set接口Set接口继承自Collection接口,它是一个不包含重复元素的集合。HashSet:基于哈希表实现的Set,元素无序。TreeSet:基于红黑树实现的Set,元素有序。
-
Map接口Map接口是一个键值对的集合,键是唯一的,但值可以重复。HashMap:基于哈希表实现的Map,键值对无序。TreeMap:基于红黑树实现的Map,键值对有序。
2. 集合的遍历
-
for-each循环for-each循环是一种简化的循环,用于遍历集合中的元素。List<String> list = Arrays.asList("Kimi", "Alice", "Bob"); for (String name : list) { System.out.println(name); }
-
Iterator迭代器Iterator是一个用于遍历集合的接口,它提供了一种通用的方式来访问集合中的元素。List<String> list = Arrays.asList("Kimi", "Alice", "Bob"); Iterator<String> iterator = list.iterator(); while (iterator.hasNext()) { String name = iterator.next(); System.out.println(name); }
-
StreamAPIStreamAPI是Java 8引入的一种新的集合操作方式,它提供了一种更简洁的方式来处理集合。List<String> list = Arrays.asList("Kimi", "Alice", "Bob"); list.stream() .filter(name -> name.startsWith("A")) // 过滤以A开头的名字 .forEach(System.out::println); // 输出过滤后的结果
3. 常见代码示例
public class CollectionExample {
// List示例
public static void listExample() {
List<String> list = new ArrayList<>();
list.add("Kimi");
list.add("Alice");
list.add("Bob");
System.out.println("List中的元素:");
for (String name : list) {
System.out.println(name);
}
}
// Set示例
public static void setExample() {
Set<String> set = new HashSet<>();
set.add("Kimi");
set.add("Alice");
set.add("Bob");
System.out.println("Set中的元素:");
for (String name : set) {
System.out.println(name);
}
}
// Map示例
public static void mapExample() {
Map<String, Integer> map = new HashMap<>();
map.put("Kimi", 25);
map.put("Alice", 30);
map.put("Bob", 35);
System.out.println("Map中的元素:");
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
public static void main(String[] args) {
listExample();
setExample();
mapExample();
}
}
(十二)Java常用类库
Java提供了丰富的类库,用于处理常见的编程任务,如字符串操作、日期时间处理、数学计算等。
1. 字符串类
String类是Java中最常用的类之一,它用于表示字符串。字符串是不可变的,一旦创建后不能修改。
- 常用方法
-
length():返回字符串的长度。String str = "Hello"; int length = str.length(); // 结果为5 -
charAt(int index):返回指定索引处的字符。char c = str.charAt(0); // 结果为'H' -
substring(int beginIndex, int endIndex):返回字符串的子串。String subStr = str.substring(0, 3); // 结果为"Hel" -
equals(Object anObject):比较两个字符串是否相等。boolean isEqual = str.equals("Hello"); // 结果为true -
compareTo(String anotherString):比较两个字符串的字典顺序。int comparison = str.compareTo("Hello"); // 结果为0
-
2. 包装类
包装类是基本数据类型的类版本,它们允许我们将基本数据类型作为对象处理。
- 自动装箱与自动拆箱
-
自动装箱:将基本数据类型自动转换为对应的包装类。
Integer num = 10; // 自动装箱 -
自动拆箱:将包装类自动转换为对应的基本数据类型。
int value = num; // 自动拆箱
-
3. 日期与时间类
Java提供了多种日期和时间类,用于处理日期和时间。
-
java.util.DateDate类用于表示日期和时间。Date date = new Date(); System.out.println(date.toString());
-
java.time包java.time包是Java 8引入的新的日期和时间API,它提供了更强大的日期和时间处理功能。LocalDate:表示日期(年、月、日)。LocalTime:表示时间(时、分、秒)。LocalDateTime:表示日期和时间。DateTimeFormatter:用于格式化日期和时间。LocalDate localDate = LocalDate.now(); LocalTime localTime = LocalTime.now(); LocalDateTime localDateTime = LocalDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); String formattedDate = localDateTime.format(formatter); System.out.println(formattedDate);
4. 数学类
Math类提供了各种数学计算方法。
- 常用方法
-
abs(double a):返回参数的绝对值。double absValue = Math.abs(-10.5); // 结果为10.5 -
sqrt(double a):返回参数的平方根。double sqrtValue = Math.sqrt(16); // 结果为4.0 -
pow(double a, double b):返回a的b次幂。double powValue = Math.pow(2, 3); // 结果为8.0 -
random():返回一个随机数。double randomValue = Math.random(); // 返回一个0到1之间的随机数
-
5. IO流
Java的IO流用于处理输入和输出操作。IO流分为字节流和字符流。
-
字节流
InputStream:输入字节流。OutputStream:输出字节流。// 读取文件 try (InputStream inputStream = new FileInputStream("example.txt")) { int data; while ((data = inputStream.read()) != -1) { System.out.print((char) data); } } catch (IOException e) { e.printStackTrace(); } // 写入文件 try (OutputStream outputStream = new FileOutputStream("example.txt")) { String str = "Hello, World!"; outputStream.write(str.getBytes()); } catch (IOException e) { e.printStackTrace(); }
-
字符流
Reader:输入字符流。Writer:输出字符流。// 读取文件 try (Reader reader = new FileReader("example.txt")) { int data; while ((data = reader.read()) != -1) { System.out.print((char) data); } } catch (IOException e) { e.printStackTrace(); } // 写入文件 try (Writer writer = new FileWriter("example.txt")) { String str = "Hello, World!"; writer.write(str); } catch (IOException e) { e.printStackTrace(); }
6. 异常处理
异常处理用于处理程序运行时可能出现的错误。
-
try-catch块try块用于包裹可能抛出异常的代码,catch块用于捕获和处理异常。try { int result = 10 / 0; } catch (ArithmeticException e) { System.out.println("发生了算术异常: " + e.getMessage()); }
-
finally块finally块用于在try块和catch块执行完毕后执行,无论是否发生异常都会执行。try { int result = 10 / 0; } catch (ArithmeticException e) { System.out.println("发生了算术异常: " + e.getMessage()); } finally { System.out.println("finally块被执行"); }
-
自定义异常
- 自定义异常可以通过继承
Exception类或其子类来实现。public class CustomException extends Exception { public CustomException(String message) { super(message); } } public class ExceptionExample { public static void main(String[] args) { try { throw new CustomException("这是一个自定义异常"); } catch (CustomException e) { System.out.println("捕获到自定义异常: " + e.getMessage()); } } }
- 自定义异常可以通过继承
7. 常见代码示例
public class CommonClassesExample {
// 字符串操作
public static void stringExample() {
String str = "Hello";
int length = str.length();
char c = str.charAt(0);
String subStr = str.substring(0, 3);
boolean isEqual = str.equals("Hello");
int comparison = str.compareTo("Hello");
System.out.println("字符串长度: " + length);
System.out.println("字符串第一个字符: " + c);
System.out.println("字符串子串: " + subStr);
System.out.println("字符串是否相等: " + isEqual);
System.out.println("字符串比较结果: " + comparison);
}
// 日期时间操作
public static void dateTimeExample() {
Date date = new Date();
System.out.println("当前日期和时间: " + date.toString());
LocalDate localDate = LocalDate.now();
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formattedDate = localDateTime.format(formatter);
System.out.println("格式化后的日期和时间: " + formattedDate);
}
// 数学计算
public static void mathExample() {
double absValue = Math.abs(-10.5);
double sqrtValue = Math.sqrt(16);
double powValue = Math.pow(2, 3);
double randomValue = Math.random();
System.out.println("绝对值: " + absValue);
System.out.println("平方根: " + sqrtValue);
System.out.println("幂运算结果: " + powValue);
System.out.println("随机数: " + randomValue);
}
// IO流操作
public static void ioExample() {
// 读取文件
try (InputStream inputStream = new FileInputStream("example.txt")) {
int data;
while ((data = inputStream.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
// 写入文件
try (OutputStream outputStream = new FileOutputStream("example.txt")) {
String str = "Hello, World!";
outputStream.write(str.getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
// 异常处理
public static void exceptionExample() {
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("发生了算术异常: " + e.getMessage());
} finally {
System.out.println("finally块被执行");
}
}
public static void main(String[] args) {
stringExample();
dateTimeExample();
mathExample();
ioExample();
exceptionExample();
}
}
(十三)Java多线程
多线程是Java的一个重要特性,它允许程序同时执行多个任务。多线程可以提高程序的性能和响应能力。
1. 线程的创建
在Java中,可以通过继承Thread类或实现Runnable接口来创建线程。
-
继承
Thread类public class MyThread extends Thread { @Override public void run() { System.out.println("线程正在运行"); } } -
实现
Runnable接口public class MyRunnable implements Runnable { @Override public void run() { System.out.println("线程正在运行"); } }
2. 线程的生命周期
线程的生命周期包括新建、就绪
、运行、阻塞和死亡五个状态。
- 新建状态:线程被创建但尚未启动。
- 就绪状态:线程已经启动,等待CPU调度。
- 运行状态:线程正在执行。
- 阻塞状态:线程因为某些原因暂停执行,如等待I/O操作或等待锁。
- 死亡状态:线程执行完毕或被终止。
3. 线程的同步
线程同步用于解决多线程环境下的数据共享问题。Java提供了多种同步机制,如synchronized关键字和Lock接口。
-
synchronized关键字synchronized关键字用于同步方法或代码块,确保同一时间只有一个线程可以访问共享资源。public class Counter { private int count = 0; public synchronized void increment() { count++; } public synchronized int getCount() { return count; } }
-
Lock接口Lock接口提供了一种更灵活的同步机制,它允许更细粒度的控制。public class Counter { private int count = 0; private Lock lock = new ReentrantLock(); public void increment() { lock.lock(); try { count++; } finally { lock.unlock(); } } public int getCount() { lock.lock(); try { return count; } finally { lock.unlock(); } } }
4. 线程的通信
线程通信用于解决线程之间的协作问题。Java提供了wait、notify和notifyAll方法用于线程通信。
-
wait方法wait方法使当前线程进入等待状态,直到被其他线程唤醒。synchronized (this) { while (condition) { wait(); } }
-
notify和notifyAll方法notify方法唤醒一个等待的线程,notifyAll方法唤醒所有等待的线程。synchronized (this) { notify(); }
5. 常见代码示例
public class MultiThreadExample {
// 继承Thread类
public static class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程正在运行");
}
}
// 实现Runnable接口
public static class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("线程正在运行");
}
}
// 线程同步示例
public static class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
// 线程通信示例
public static class ProducerConsumerExample {
private int count = 0;
public synchronized void produce() throws InterruptedException {
while (count >= 1) {
wait();
}
count++;
System.out.println("生产者生产,当前数量: " + count);
notifyAll();
}
public synchronized void consume() throws InterruptedException {
while (count <= 0) {
wait();
}
count--;
System.out.println("消费者消费,当前数量: " + count);
notifyAll();
}
}
public static void main(String[] args) throws InterruptedException {
// 创建线程
MyThread thread1 = new MyThread();
thread1.start();
Thread thread2 = new Thread(new MyRunnable());
thread2.start();
// 线程同步
Counter counter = new Counter();
Thread incrementThread = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
Thread incrementThread2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) {
counter.increment();
}
});
incrementThread.start();
incrementThread2.start();
incrementThread.join();
incrementThread2.join();
System.out.println("最终计数: " + counter.getCount());
// 线程通信
ProducerConsumerExample example = new ProducerConsumerExample();
Thread producer = new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
example.produce();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread consumer = new Thread(() -> {
try {
for (int i = 0; i < 10; i++) {
example.consume();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
});
producer.start();
consumer.start();
}
}
(十四)Java网络编程
Java提供了丰富的网络编程支持,用于开发基于网络的应用程序。Java的网络编程主要涉及套接字(Socket)编程和基于HTTP协议的Web开发。
1. TCP网络编程
TCP是一种面向连接的协议,它提供可靠的数据传输服务。在Java中,可以通过ServerSocket和Socket类来实现TCP网络编程。
-
服务器端
public class TCPServer { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(8080); System.out.println("服务器已启动,等待客户端连接..."); while (true) { Socket socket = serverSocket.accept(); System.out.println("客户端已连接"); new Thread(new ClientHandler(socket)).start(); } } static class ClientHandler implements Runnable { private Socket socket; public ClientHandler(Socket socket) { this.socket = socket; } @Override public void run() { try (InputStream inputStream = socket.getInputStream(); OutputStream outputStream = socket.getOutputStream()) { byte[] buffer = new byte[1024]; int length; while ((length = inputStream.read(buffer)) != -1) { outputStream.write(buffer, 0, length); } } catch (IOException e) { e.printStackTrace(); } finally { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } } } -
客户端
public class TCPClient { public static void main(String[] args) throws IOException { Socket socket = new Socket("127.0.0.1", 8080); System.out.println("已连接到服务器"); try (OutputStream outputStream = socket.getOutputStream(); InputStream inputStream = socket.getInputStream()) { outputStream.write("Hello, Server!".getBytes()); byte[] buffer = new byte[1024]; int length = inputStream.read(buffer); System.out.println("服务器响应: " + new String(buffer, 0, length)); } finally { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
2. UDP网络编程
UDP是一种无连接的协议,它不保证数据的可靠传输。在Java中,可以通过DatagramSocket和DatagramPacket类来实现UDP网络编程。
-
服务器端
public class UDPServer { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(8080); System.out.println("服务器已启动,等待客户端消息..."); byte[] buffer = new byte[1024]; DatagramPacket packet = new DatagramPacket(buffer, buffer.length); while (true) { socket.receive(packet); String message = new String(packet.getData(), 0, packet.getLength()); System.out.println("收到客户端消息: " + message); // 发送响应 String response = "Hello, Client!"; DatagramPacket responsePacket = new DatagramPacket(response.getBytes(), response.length(), packet.getAddress(), packet.getPort()); socket.send(responsePacket); } } } -
客户端
public class UDPClient { public static void main(String[] args) throws IOException { DatagramSocket socket = new DatagramSocket(); InetAddress address = InetAddress.getByName("127.0.0.1"); String message = "Hello, Server!"; byte[] buffer = message.getBytes(); DatagramPacket packet = new DatagramPacket(buffer, buffer.length, address, 8080); socket.send(packet); byte[] receiveBuffer = new byte[1024]; DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length); socket.receive(receivePacket); String response = new String(receivePacket.getData(), 0, receivePacket.getLength()); System.out.println("服务器响应: " + response); socket.close(); } }
3. HTTP协议与Web开发基础
HTTP协议是Web开发的基础。Java提供了HttpURLConnection类用于发送HTTP请求和接收响应。
public class HttpExample {
public static void main(String[] args) throws
IOException {
URL url = new URL("http://example.com");
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
int responseCode = connection.getResponseCode();
System.out.println("响应码: " + responseCode);
try (InputStream inputStream = connection.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
}
}
}
(十五)Java数据库编程(JDBC)
Java数据库连接(JDBC)是Java用于访问数据库的API。通过JDBC,可以连接数据库、执行SQL语句和处理结果集。
1. JDBC概述
JDBC提供了以下接口和类:
DriverManager:用于获取数据库连接。Connection:表示与数据库的连接。Statement:用于执行SQL语句。ResultSet:用于处理查询结果。
2. 数据库连接与操作
-
连接数据库
Connection connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "username", "password"); -
执行SQL语句
Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery("SELECT * FROM users"); -
处理结果集
while (resultSet.next()) { String name = resultSet.getString("name"); int age = resultSet.getInt("age"); System.out.println("姓名: " + name + ", 年龄: " + age); }
3. 事务处理
事务用于保证数据库操作的原子性。在Java中,可以通过设置事务的隔离级别和提交/回滚事务来管理事务。
-
设置事务隔离级别
connection.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); -
提交事务
connection.commit(); -
回滚事务
connection.rollback();
4. 常见代码示例
public class JdbcExample {
public static void main(String[] args) {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
try {
// 加载数据库驱动
Class.forName("com.mysql.cj.jdbc.Driver");
// 连接数据库
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydatabase", "username", "password");
// 创建Statement
statement = connection.createStatement();
// 执行查询
resultSet = statement.executeQuery("SELECT * FROM users");
// 处理结果集
while (resultSet.next()) {
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
System.out.println("姓名: " + name + ", 年龄: " + age);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源
try {
if (resultSet != null) {
resultSet.close();
}
if (statement != null) {
statement.close();
}
if (connection != null) {
connection.close();
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
(十六)Java注解与反射
2. 自定义注解
自定义注解可以通过@interface关键字来定义。注解可以有成员变量,这些成员变量在使用注解时需要提供值。
public @interface MyAnnotation {
String value(); // 必须指定的成员变量
int age() default 18; // 可选的成员变量,有默认值
}
使用自定义注解:
@MyAnnotation(value = "Kimi", age = 25)
public class MyClass {
}
3. 反射机制
反射是Java的一种动态机制,允许程序在运行时检查和操作类、方法、字段等信息。
-
获取
Class对象Class<?> clazz = MyClass.class; // 通过类名获取 Class<?> clazz2 = new MyClass().getClass(); // 通过对象获取 Class<?> clazz3 = Class.forName("com.example.MyClass"); // 通过类的全限定名获取 -
获取类的信息
Field[] fields = clazz.getDeclaredFields(); // 获取所有字段 Method[] methods = clazz.getDeclaredMethods(); // 获取所有方法 Constructor<?>[] constructors = clazz.getDeclaredConstructors(); // 获取所有构造方法 -
通过反射创建对象
Constructor<?> constructor = clazz.getDeclaredConstructor(); constructor.setAccessible(true); // 如果是私有构造方法,需要设置为可访问 Object instance = constructor.newInstance(); -
通过反射调用方法
Method method = clazz.getDeclaredMethod("methodName", String.class); method.setAccessible(true); // 如果是私有方法,需要设置为可访问 method.invoke(instance, "Hello"); -
通过反射访问字段
Field field = clazz.getDeclaredField("fieldName"); field.setAccessible(true); // 如果是私有字段,需要设置为可访问 Object value = field.get(instance); // 获取字段值 field.set(instance, "newValue"); // 设置字段值
4. 常见代码示例
public class ReflectionExample {
public static class MyClass {
private String name = "Kimi";
public void printName() {
System.out.println("名字: " + name);
}
}
public static void main(String[] args) throws Exception {
// 获取Class对象
Class<?> clazz = MyClass.class;
// 获取类的信息
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
System.out.println("字段: " + field.getName());
}
Method[] methods = clazz.getDeclaredMethods();
for (Method method : methods) {
System.out.println("方法: " + method.getName());
}
// 通过反射创建对象
Constructor<?> constructor = clazz.getDeclaredConstructor();
constructor.setAccessible(true);
Object instance = constructor.newInstance();
// 通过反射调用方法
Method method = clazz.getDeclaredMethod("printName");
method.setAccessible(true);
method.invoke(instance);
// 通过反射访问字段
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);
String value = (String) field.get(instance);
System.out.println("字段值: " + value);
field.set(instance, "Alice");
method.invoke(instance); // 输出:名字: Alice
}
}
(十七)Java设计模式
设计模式是解决常见问题的通用解决方案。Java中常用的设计模式包括创建型模式、结构型模式和行为型模式。
1. 创建型设计模式
创建型设计模式用于创建对象,同时隐藏创建逻辑,而不是直接使用new操作符。
-
单例模式
- 确保一个类只有一个实例,并提供一个全局访问点。
public class Singleton { private static Singleton instance; private Singleton() { } public static Singleton getInstance() { if (instance == null) { synchronized (Singleton.class) { if (instance == null) { instance = new Singleton(); } } } return instance; } }
- 确保一个类只有一个实例,并提供一个全局访问点。
-
工厂模式
- 提供一个创建对象的接口,让子类决定实例化哪一个类。
public interface Shape { void draw(); } public class Circle implements Shape { @Override public void draw() { System.out.println("画一个圆"); } } public class Rectangle implements Shape { @Override public void draw() { System.out.println("画一个矩形"); } } public class ShapeFactory { public Shape getShape(String shapeType) { if (shapeType == null) { return null; } if (shapeType.equalsIgnoreCase("CIRCLE")) { return new Circle(); } else if (shapeType.equalsIgnoreCase("RECTANGLE")) { return new Rectangle(); } return null; } }
- 提供一个创建对象的接口,让子类决定实例化哪一个类。
-
建造者模式
- 用于创建一个复杂的对象,同时隐藏对象的创建逻辑。
public class BuilderExample { private String name; private int age; private String address; public static class Builder { private String name; private int age; private String address; public Builder setName(String name) { this.name = name; return this; } public Builder setAge(int age) { this.age = age; return this; } public Builder setAddress(String address) { this.address = address; return this; } public BuilderExample build() { return new BuilderExample(this); } } private BuilderExample(Builder builder) { this.name = builder.name; this.age = builder.age; this.address = builder.address; } @Override public String toString() { return "BuilderExample{" + "name='" + name + '\'' + ", age=" + age + ", address='" + address + '\'' + '}'; } }
- 用于创建一个复杂的对象,同时隐藏对象的创建逻辑。
2. 结构型设计模式
结构型设计模式用于处理类或对象的组合。
-
适配器模式
- 允许将不兼容的接口转换为一个可以使用的兼容接口。
public interface MediaPlayer { void play(String audioType, String fileName); } public interface AdvancedMediaPlayer { void playVlc(String fileName); void playMp4(String fileName); } public class VlcPlayer implements AdvancedMediaPlayer { @Override public void playVlc(String fileName) { System.out.println("Playing vlc file. Name: " + fileName); } @Override public void playMp4(String fileName) { // Do nothing } } public class Mp4Player implements AdvancedMediaPlayer { @Override public void playVlc(String fileName) { // Do nothing } @Override public void playMp4(String fileName) { System.out.println("Playing mp4 file. Name: " + fileName); } } public class MediaAdapter implements MediaPlayer { private AdvancedMediaPlayer advancedMediaPlayer; public MediaAdapter(String audioType) { if (audioType.equalsIgnoreCase("vlc")) { advancedMediaPlayer = new VlcPlayer(); } else if (audioType.equalsIgnoreCase("mp4")) { advancedMediaPlayer = new Mp4Player(); } } @Override public void play(String audioType, String fileName) { if (audioType.equalsIgnoreCase("vlc")) { advancedMediaPlayer.playVlc(fileName); } else if (audioType.equalsIgnoreCase("mp4")) { advancedMediaPlayer.playMp4(fileName); } } }
- 允许将不兼容的接口转换为一个可以使用的兼容接口。
-
装饰器模式
- 动态地给一个对象添加额外的职责。
public interface Component { void operation(); } public class ConcreteComponent implements Component { @Override public void operation() { System.out.println("具体组件的操作"); } } public abstract class Decorator implements Component { protected Component component; public Decorator(Component component) { this.component = component; } @Override public void operation() { component.operation(); } } public class ConcreteDecoratorA extends Decorator { public ConcreteDecoratorA(Component component) { super(component); } @Override public void operation() { super.operation(); addedBehavior(); } private void addedBehavior() { System.out.println("添加额外的行为A"); } } public class ConcreteDecoratorB extends Decorator { public ConcreteDecoratorB(Component component) { super(component); } @Override public void operation() { super.operation(); addedBehavior(); } private void addedBehavior() { System.out.println("添加额外的行为B"); } }
- 动态地给一个对象添加额外的职责。
-
代理模式
- 为其他对象提供一种代理以控制对这个对象的访问。
public interface Subject { void request(); } public class RealSubject implements Subject { @Override public void request(){ System.out.println("真实主题的请求"); } } public class Proxy implements Subject { private RealSubject realSubject; @Override public void request() { preRequest(); if (realSubject == null) { realSubject = new RealSubject(); } realSubject.request(); postRequest(); } private void preRequest() { System.out.println("代理的预处理"); } private void postRequest() { System.out.println("代理的后处理"); } }
- 为其他对象提供一种代理以控制对这个对象的访问。
3. 行为型设计模式
行为型设计模式用于处理类或对象之间的通信。
-
策略模式
- 定义一系列算法,将每个算法封装起来,并使它们可以互换。
public interface Strategy { int doOperation(int num1, int num2); } public class OperationAdd implements Strategy { @Override public int doOperation(int num1, int num2) { return num1 + num2; } } public class OperationSubtract implements Strategy { @Override public int doOperation(int num1, int num2) { return num1 - num2; } } public class Context { private Strategy strategy; public Context(Strategy strategy) { this.strategy = strategy; } public int executeStrategy(int num1, int num2) { return strategy.doOperation(num1, num2); } }
- 定义一系列算法,将每个算法封装起来,并使它们可以互换。
-
模板方法模式
- 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
public abstract class AbstractClass { public final void templateMethod() { step1(); step2(); step3(); } protected abstract void step1(); protected abstract void step2(); protected void step3() { System.out.println("默认的第三步"); } } public class ConcreteClassA extends AbstractClass { @Override protected void step1() { System.out.println("具体实现A的第一步"); } @Override protected void step2() { System.out.println("具体实现A的第二步"); } } public class ConcreteClassB extends AbstractClass { @Override protected void step1() { System.out.println("具体实现B的第一步"); } @Override protected void step2() { System.out.println("具体实现B的第二步"); } }
- 定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。
-
观察者模式
- 定义对象间的一种一对多的依赖关系,使得当一个对象改变状态时,所有依赖于它的对象都得到通知并自动更新。
public interface Observer { void update(String message); } public interface Subject { void register(Observer obj); void unregister(Observer obj); void notifyObservers(); } public class ConcreteSubject implements Subject { private List<Observer> observers = new ArrayList<>(); @Override public void register(Observer obj) { observers.add(obj); } @Override public void unregister(Observer obj) { observers.remove(obj); } @Override public void notifyObservers() { for (Observer observer : observers) { observer.update("状态已改变"); } } } public class ConcreteObserver implements Observer { private String name; public ConcreteObserver(String name) { this.name = name; } @Override public void update(String message) { System.out.println(name + "收到消息: " + message); } }
- 定义对象间的一种一对多的依赖关系,使得当一个对象改变状态时,所有依赖于它的对象都得到通知并自动更新。
4. 常见代码示例
public class DesignPatternsExample {
// 单例模式
public static class SingletonExample {
private static SingletonExample instance;
private SingletonExample() {
}
public static SingletonExample getInstance() {
if (instance == null) {
synchronized (SingletonExample.class) {
if (instance == null) {
instance = new SingletonExample();
}
}
}
return instance;
}
}
// 工厂模式
public static class FactoryExample {
public static void main(String[] args) {
ShapeFactory shapeFactory = new ShapeFactory();
Shape shape1 = shapeFactory.getShape("CIRCLE");
shape1.draw();
Shape shape2 = shapeFactory.getShape("RECTANGLE");
shape2.draw();
}
}
// 建造者模式
public static class BuilderExample {
public static void main(String[] args) {
BuilderExample example = new BuilderExample.Builder()
.setName("Kimi")
.setAge(25)
.setAddress("Beijing")
.build();
System.out.println(example);
}
}
// 适配器模式
public static class AdapterExample {
public static void main(String[] args) {
MediaPlayer mediaPlayer = new MediaAdapter("vlc");
mediaPlayer.play("vlc", "example.vlc");
mediaPlayer = new MediaAdapter("mp4");
mediaPlayer.play("mp4", "example.mp4");
}
}
// 装饰器模式
public static class DecoratorExample {
public static void main(String[] args) {
Component component = new ConcreteComponent();
Component decoratedComponent = new ConcreteDecoratorA(component);
decoratedComponent.operation();
decoratedComponent = new ConcreteDecoratorB(decoratedComponent);
decoratedComponent.operation();
}
}
// 代理模式
public static class ProxyExample {
public static void main(String[] args) {
Subject proxy = new Proxy();
proxy.request();
}
}
// 策略模式
public static class StrategyExample {
public static void main(String[] args) {
Context context = new Context(new OperationAdd());
System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationSubtract());
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
}
}
// 模板方法模式
public static class TemplateMethodExample {
public static void main(String[] args) {
AbstractClass classA = new ConcreteClassA();
classA.templateMethod();
AbstractClass classB = new ConcreteClassB();
classB.templateMethod();
}
}
// 观察者模式
public static class ObserverExample {
public static void main(String[] args) {
Subject subject = new ConcreteSubject();
Observer observer1 = new ConcreteObserver("Observer1");
Observer observer2 = new ConcreteObserver("Observer2");
subject.register(observer1);
subject.register(observer2);
subject.notifyObservers();
}
}
public static void main(String[] args) {
SingletonExample singleton = SingletonExample.getInstance();
System.out.println(singleton);
FactoryExample.main(args);
BuilderExample.main(args);
AdapterExample.main(args);
DecoratorExample.main(args);
ProxyExample.main(args);
StrategyExample.main(args);
TemplateMethodExample.main(args);
ObserverExample.main(args);
}
}
浙公网安备 33010602011771号