说明:
目录
一、类和对象
1.1 类
1.2 对象
1.3 类的构造方法
1.4 this关键字
注意事项
1.5 抽象
1.6 接口
1.7 作业习题:实现一个类的构造方法,并且创建该类的一个实例(对象)
二、面向对象编程的特点
2.1 封装
2.2 继承
2.3 多态
2.4 作业习题:应用面向对象编程的封装、继承、多态三大特点
三、字符串(String类)
3.1 字符串查找
3.2 字符串比较
3.3 字符串修改
3.4 字符串与其他类型转换
3.5 其他字符串操作
3.6 字符串示例:
创建字符串
字符串长度
字符串连接
字符串比较
字符串查找
字符串截取
字符串替换
字符串分割
字符串大小写转换
字符串去除空格
字符串格式化
字符串与基本数据类型的转换
字符串编码和解码
3.7 作业习题:实现对三个数组的元素进行合并排序
四、常用类
4.1 包装类
Integer类
Double类
Boolean类
Character类
Number类
4.2 数字处理
数字格式化
Math类
Random类
BigInteger类
BigDecimal类
4.3 系统类
类字段
方法
4.4 日期类
Date类
Calendar类
SimpleDateFormat类
TimeZone类
LocalDate类
LocalDateTime类
4.5 作业习题:使用LocalDateTime实现计算1000次LocalDate的plusDays(1) 方法所消耗的时间
五、集合类
5.1 集合接口
5.2 实现类
5.3 集合类常用方法
Collection 接口
List 接口(继承自 Collection)
Set 接口(继承自 Collection)
Map 接口
Iterator 接口
ListIterator 接口(继承自 Iterator)
5.4 作业习题:给定两个集合 A 和 B,请编写一个方法,输出这两个集合的并集和交集
六、 异常处理
6.1 异常类型:
6.2 异常处理关键字
6.3 异常处理的基本模式
6.4 作业习题:实现自定义异常处理
七、文件
7.1 File类
实例方法
静态方法
7.2 文件的输入/输出流(非缓存、缓存)
输入流(读取文件)
输出流(写入文件)
字节流读取文件
字节流写入文件
字符流读取文件
字符流写入文件
7.3 缓存输入/输出流使用说明
使用带缓存流的情况:
不使用带缓存流的情况:
7.4 作业习题:使用非缓存输入/输出流 实现(字节和字符流) 读取和写入文件的操作
类是创建对象的蓝图或模板。它是一个定义对象的属性(变量)和行为(方法)的模板。在Java中,类是用于定义对象的特征和行为的自定义数据类型。
public class Car {
// 属性(成员变量)
String color;
String model;
int year;
// 方法(行为)
public void start() {
System.out.println("汽车启动了");
}
public void stop() {
System.out.println("汽车停止了");
}
}
对象是类的实例。当你创建一个对象时,你实际上是在类的基础上创建了一个具体的实体。对象通常具有状态(由属性表示)和行为(由方法表示)。
public class Main {
public static void main(String[] args) {
// 创建Car类的一个对象
Car myCar = new Car();
// 设置对象的属性
myCar.color = "红色";
myCar.model = "SUV";
myCar.year = 2024;
// 调用对象的方法
myCar.start();
myCar.stop();
}
}
定义构造方法的例子:
public class Person {
String name;
int age;
// 无参构造方法
public Person() {
name = "未知";
age = 0;
}
// 带参数的构造方法
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
以下是创建Person
对象并调用构造方法的示例:
public class Main {
public static void main(String[] args) {
// 使用无参构造方法创建对象
Person person1 = new Person();
System.out.println(person1.name + " " + person1.age); // 输出:未知 0
// 使用带参数的构造方法创建对象
Person person2 = new Person("Alice", 30);
System.out.println(person2.name + " " + person2.age); // 输出:Alice 30
}
}
this
关键字是一个引用当前对象的特殊关键字。它可以用于类的实例方法内部,也可以用于构造方法中。
使用this
关键字来引用当前对象的属性:
public class Person {
private String name;
private int age;
public Person(String name, int age) {
this.name = name; // 使用this区分局部变量和实例变量
this.age = age;
}
public void setName(String name) {
this.name = name; // 使用this引用当前对象的name属性
}
public String getName() {
return this.name; // 使用this引用当前对象的name属性
}
public void setAge(int age) {
this.age = age; // 使用this引用当前对象的age属性
}
public int getAge() {
return this.age; // 使用this引用当前对象的age属性
}
}
使用this
关键字来调用当前对象的其他方法:
public class Person {
// ...
public void printDetails() {
System.out.println("Name: " + this.getName()); // 调用getName()方法
System.out.println("Age: " + this.getAge()); // 调用getAge()方法
}
}
在一个类的构造方法中,可以使用this
关键字来调用同一个类的另一个构造方法:
public class Person {
private String name;
private int age;
public Person() {
this("Unknown", 0); // 调用另一个构造方法
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
// ...
}
this
关键字只能在实例方法或构造方法中使用,不能在静态方法中使用,因为静态方法不属于任何特定的对象实例。this
调用必须位于方法的第一行,否则编译器会报错。抽象类
abstract
关键字来定义。抽象方法
abstract
关键字声明。下面是一个Java抽象类的简单例子:
public abstract class Animal {
private String name;
public Animal(String name) {
this.name = name;
}
public abstract void sound(); // 抽象方法
public void sleep() {
System.out.println(name + " is sleeping.");
}
}
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
@Override
public void sound() {
System.out.println("Woof!");
}
}
接口(Interface)是一种引用类型,类似于类,用于存放抽象方法和静态常量。接口定义了一个规范,规定了实现接口的类应具备哪些方法。以下是关于Java接口的一些详细信息:
接口的定义
interface
关键字来定义。public
和abstract
的,即它们没有方法体。public
、static
和final
的,即它们是常量。接口的方法
下面是一个Java接口的简单例子:
public interface Animal {
void sound(); // 抽象方法
// Java 8的默认方法
default void sleep() {
System.out.println("Animal is sleeping.");
}
// Java 8的静态方法
static int getAge() {
return 5;
}
}
public class Dog implements Animal {
@Override
public void sound() {
System.out.println("Woof!");
}
}
private
, protected
, public
)来控制类成员的访问级别。public class BankAccount {
private double balance; // 私有属性,外部不能直接访问
// 公共方法,用于获取账户余额
public double getBalance() {
return balance;
}
// 公共方法,用于存款
public void deposit(double amount) {
if(amount > 0) {
balance += amount;
}
}
// 公共方法,用于取款
public void withdraw(double amount) {
if(amount <= balance && amount > 0) {
balance -= amount;
}
}
}
在这个例子中,balance
是一个私有属性,只能通过 deposit
和 withdraw
方法来修改,而不能直接从类的外部访问。
public class Animal {
void eat() {
System.out.println("动物正在吃东西");
}
}
public class Dog extends Animal {
void bark() {
System.out.println("狗在叫");
}
}
在这个例子中,Dog
类继承了 Animal
类,因此 Dog
类的对象可以使用 eat
方法。
public class Animal {
void sound() {
System.out.println("动物发出声音");
}
}
public class Dog extends Animal {
@Override
void sound() {
System.out.println("狗在叫");
}
}
public class Cat extends Animal {
@Override
void sound() {
System.out.println("猫在喵喵叫");
}
}
public class TestPolymorphism {
public static void main(String[] args) {
Animal myAnimal = new Dog(); // Dog对象被向上转型为Animal类型
Animal myOtherAnimal = new Cat(); // Cat对象被向上转型为Animal类型
myAnimal.sound(); // 输出:狗在叫
myOtherAnimal.sound(); // 输出:猫在喵喵叫
}
}
在这个例子中,尽管 myAnimal
和 myOtherAnimal
被声明为 Animal
类型,但它们分别引用了 Dog
和 Cat
类型的对象。调用 sound
方法时,会根据对象的实际类型来决定调用哪个类的方法,这就是多态的表现。
boolean contains(CharSequence s)
:检查字符串是否包含指定的字符序列。int indexOf(int ch)
:返回指定字符在此字符串中第一次出现处的索引。int indexOf(int ch, int fromIndex)
:返回指定字符在此字符串中第一次出现处的索引,从指定的索引开始搜索。int indexOf(String str)
:返回指定子字符串在此字符串中第一次出现处的索引。int indexOf(String str, int fromIndex)
:返回指定子字符串在此字符串中第一次出现处的索引,从指定的索引开始。int lastIndexOf(int ch)
:返回指定字符在此字符串中最后一次出现处的索引。int lastIndexOf(int ch, int fromIndex)
:返回指定字符在此字符串中最后一次出现处的索引,从指定的索引开始向后搜索。int lastIndexOf(String str)
:返回指定子字符串在此字符串中最右边出现处的索引。int lastIndexOf(String str, int fromIndex)
:返回指定子字符串在此字符串中最后一次出现处的索引,从指定的索引开始向后搜索。boolean equals(Object anObject)
:将此字符串与指定的对象比较。boolean equalsIgnoreCase(String anotherString)
:将此字符串与另一个字符串比较,不考虑大小写。int compareTo(String anotherString)
:按字典顺序比较两个字符串。int compareToIgnoreCase(String str)
:按字典顺序比较两个字符串,不考虑大小写。String concat(String str)
:将指定的字符串连接到此字符串的末尾。String replace(char oldChar, char newChar)
:返回一个新的字符串,它是通过用 newChar 替换此字符串中出现的所有 oldChar 得到的。String replace(CharSequence target, CharSequence replacement)
:使用指定的字面值替换序列替换此字符串所有匹配字面值目标序列的子字符串。String replaceAll(String regex, String replacement)
:使用给定的 replacement 替换此字符串所有匹配给定的正则表达式的子字符串。String replaceFirst(String regex, String replacement)
:使用给定的 replacement 替换此字符串匹配给定的正则表达式的第一个子字符串。String substring(int beginIndex)
:返回一个新的字符串,它是此字符串的一个子字符串。String substring(int beginIndex, int endIndex)
:返回一个新字符串,它是此字符串的一个子字符串。String toLowerCase()
:使用默认语言环境的规则将此 String 中的所有小写字。String toUpperCase()
:使用默认语言环境的规则将此 String 中的所有小写字转换成大写。String trim()
:删除指定字符串的首尾空白符。char[] toCharArray()
:将此字符串转换为一个新的字符数组。static String copyValueOf(char[] data)
:返回指定数组中表示该字符序列的 String。static String copyValueOf(char[] data, int offset, int count)
:返回指定数组中表示该字符序列的 String。static String valueOf(primitive data type x)
:返回指定类型参数的字符串表示形式。boolean isEmpty()
:当且仅当 length() 为 0 时返回 true。boolean startsWith(String prefix)
:测试此字符串是否以指定的前缀开始。boolean endsWith(String suffix)
:测试此字符串是否以指定的后缀结束。String intern()
:返回字符串对象的规范化表示形式。int hashCode()
:返回此字符串的哈希码。boolean matches(String regex)
:告知此字符串是否匹配给定的正则表达式。String[] split(String regex)
:根据匹配给定的正则表达式来拆分此字符串。String[] split(String regex, int limit)
:根据匹配给定的正则表达式来拆分此字符串,最多不超过 limit 个,如果超过了,剩下的全部放到最后一个元素中。如果对字符串的每个操作进行详细解析会导致文章的篇幅过长,为了避免冗余,选择对字符串的常用操作的示例总结,如下:
String str1 = "Hello";
String str2 = new String("World");
int length = str1.length();
String concatenated = str1 + " " + str2;
boolean isEqual = str1.equals(str2);
boolean isSame = str1 == str2; // 通常不推荐用于字符串比较,因为它比较的是引用
int index = str1.indexOf("lo");
boolean contains = str1.contains("ell");
String subStr = str1.substring(1, 4); // 从索引1到索引3(不包括4)
String replaced = str1.replace("Hello", "Hi");
String[] words = str1.split(" ");
String upperCase = str1.toUpperCase();
String lowerCase = str1.toLowerCase();
String trimmed = str1.trim(); // 去除首尾空格
String formatted = String.format("Name: %s, Age: %d", "John", 30);
int num = Integer.parseInt("123");
String strNum = String.valueOf(123);
byte[] bytes = str1.getBytes(); // 默认使用平台默认编码
String strFromBytes = new String(bytes, "UTF-8"); // 使用UTF-8解码
Integer
类是 int
基本数据类型的包装类。int
类型的值,例如将字符串转换为整数、比较整数等。parseInt(String s)
、valueOf(String s)
、toString(int i)
等。int
和 Integer
之间自动转换。示例代码:
public class IntegerExample {
public static void main(String[] args) {
Integer intObj1 = 10; // 自动装箱
Integer intObj2 = Integer.valueOf("20");
int intVal = intObj1 + intObj2; // 自动拆箱
System.out.println("两个整数的和: " + intVal);
}
}
Double
类是 double
基本数据类型的包装类。double
值的方法,如字符串到 double
的转换、比较 double
值等。parseDouble(String s)
、valueOf(String s)
、toString(double d)
等。示例代码:
public class DoubleExample {
public static void main(String[] args) {
Double doubleObj1 = 10.5; // 自动装箱
Double doubleObj2 = Double.valueOf("20.5");
double doubleVal = doubleObj1 + doubleObj2; // 自动拆箱
System.out.println("两个双精度浮点数的和: " + doubleVal);
}
}
Boolean
类是 boolean
基本数据类型的包装类。boolean
值的方法,以及 boolean
值的常用逻辑操作。parseBoolean(String s)
、valueOf(String s)
、toString(boolean b)
等。示例代码:
public class BooleanExample {
public static void main(String[] args) {
Boolean boolObj1 = true; // 自动装箱
Boolean boolObj2 = Boolean.valueOf("false");
boolean boolVal = boolObj1 && boolObj2; // 自动拆箱
System.out.println("两个布尔值的逻辑与: " + boolVal);
}
}
Character
类是 char
基本数据类型的包装类。char
值的方法,比如判断字符是否是大写、小写、数字等。isLetter(char ch)
、isDigit(char ch)
、toUpperCase(char ch)
、toLowerCase(char ch)
等。示例代码:
public class CharacterExample {
public static void main(String[] args) {
Character charObj = 'A'; // 自动装箱
boolean isUpperCase = Character.isUpperCase(charObj); // 自动拆箱
System.out.println("字符是否为大写: " + isUpperCase);
}
}
Number
类是所有数值包装类的抽象超类。byteValue()
、shortValue()
、intValue()
、longValue()
、floatValue()
和 doubleValue()
。Number
类的子类包括 Integer
、Double
、Float
、Byte
、Short
、Long
和 BigDecimal
。public class NumberExample {
public static void main(String[] args) {
Double numberObj = 123.456; // 自动装箱
int intValue = numberObj.intValue();
long longValue = numberObj.longValue();
float floatValue = numberObj.floatValue();
System.out.println("Double转换为int: " + intValue);
System.out.println("Double转换为long: " + longValue);
System.out.println("Double转换为float: " + floatValue);
}
}
Java提供了多种方式来格式化数字,包括使用String.format()
方法和DecimalFormat
类。
Math
类是一个包含基本数学运算的类,如三角函数、对数、平方根等。它提供了静态方法,因此不需要实例化即可使用。
重要方法:
sqrt(double a)
: 返回a
的平方根。pow(double a, double b)
: 返回a
的b
次幂。sin(double a)
: 返回角度a
的正弦值(以弧度为单位)。cos(double a)
: 返回角度a
的余弦值(以弧度为单位)。tan(double a)
: 返回角度a
的正切值(以弧度为单位)。log(double a)
: 返回a
的自然对数。max(double a, double b)
: 返回a
和b
中的最大值。min(double a, double b)
: 返回a
和b
中的最小值。random()
: 返回一个大于等于0.0且小于1.0的随机浮点数。public class MathExample {
public static void main(String[] args) {
double x = 10.0;
double y = 5.0;
// 计算平方根
double sqrtX = Math.sqrt(x);
System.out.println("Square root of " + x + " is " + sqrtX);
// 计算x的y次幂
double powXY = Math.pow(x, y);
System.out.println(x + " raised to the power of " + y + " is " + powXY);
// 计算随机数
double randomNum = Math.random();
System.out.println("A random number between 0.0 and 1.0 is " + randomNum);
}
}
Random
类用于生成伪随机数。它提供了多种方法来生成不同类型的随机数。
重要方法:
nextInt()
: 返回一个随机整数。nextInt(int bound)
: 返回一个介于0(包含)和指定值(不包含)之间的随机整数。nextDouble()
: 返回一个介于0.0(包含)和1.0(不包含)之间的随机浮点数。nextBoolean()
: 返回一个随机布尔值。import java.util.Random;
public class RandomExample {
public static void main(String[] args) {
Random random = new Random();
// 生成一个随机整数
int intRandom = random.nextInt();
System.out.println("A random integer: " + intRandom);
// 生成一个介于0到100之间的随机整数
int intRandomBound = random.nextInt(100);
System.out.println("A random integer between 0 and 100: " + intRandomBound);
// 生成一个随机浮点数
double doubleRandom = random.nextDouble();
System.out.println("A random double between 0.0 and 1.0: " + doubleRandom);
// 生成一个随机布尔值
boolean boolRandom = random.nextBoolean();
System.out.println("A random boolean: " + boolRandom);
}
}
BigInteger
类用于处理任意精度的整数运算。它没有直接对应的基本类型,因此必须使用构造函数来创建实例。
重要方法:
add(BigInteger val)
: 返回两个BigInteger
的和。subtract(BigInteger val)
: 返回两个BigInteger
的差。multiply(BigInteger val)
: 返回两个BigInteger
的乘积。divide(BigInteger val)
: 返回两个BigInteger
的商。import java.math.BigInteger;
public class BigIntegerExample {
public static void main(String[] args) {
BigInteger bigInt1 = new BigInteger("123456789012345678901234567890");
BigInteger bigInt2 = new BigInteger("987654321098765432109876543210");
// 加法
BigInteger sum = bigInt1.add(bigInt2);
System.out.println("Sum: " + sum);
// 乘法
BigInteger product = bigInt1.multiply(bigInt2);
System.out.println("Product: " + product);
}
}
BigDecimal
类用于处理任意精度的十进制数。与BigInteger
类似,它也是不可变的,并且用于精确的数学计算。
BigDecimal(String val)
: 通过字符串构造一个 BigDecimal
对象。BigDecimal(double val)
: 通过 double
值构造一个 BigDecimal
对象,通常不推荐使用,因为它可能会失去精度。BigDecimal(BigInteger val)
: 通过 BigInteger
对象构造一个 BigDecimal
对象。add(BigDecimal augend)
: 返回 this
和 augend
的和。subtract(BigDecimal subtrahend)
: 返回 this
减去 subtrahend
的结果。multiply(BigDecimal multiplicand)
: 返回 this
和 multiplicand
的乘积。divide(BigDecimal divisor, int scale, RoundingMode roundingMode)
: 返回 this
除以 divisor
的结果,结果按照指定的 scale
和 roundingMode
进行四舍五入。divide(BigDecimal divisor)
: 返回 this
除以 divisor
的结果,不进行四舍五入。setScale(int newScale, RoundingMode roundingMode)
: 返回一个新的 BigDecimal
,其值是 this
值按指定 scale
和 roundingMode
四舍五入的结果。compareTo(BigDecimal val)
: 比较两个 BigDecimal
对象的大小。intValue()
: 返回 BigDecimal
的 int
值,通过丢失精度。longValue()
: 返回 BigDecimal
的 long
值,通过丢失精度。doubleValue()
: 返回 BigDecimal
的 double
值,通过丢失精度。sqrt(int precision)
: 返回 BigDecimal
的平方根,精度由 precision
指定。pow(int n)
: 返回 BigDecimal
的 n
次幂。示例代码:
import java.math.BigDecimal;
import java.math.RoundingMode;
public class BigDecimalExample {
public static void main(String[] args) {
BigDecimal bd1 = new BigDecimal("123.456");
BigDecimal bd2 = new BigDecimal("7.89");
// 加法
BigDecimal sum = bd1.add(bd2);
System.out.println("加法结果: " + sum);
// 减法
BigDecimal difference = bd1.subtract(bd2);
System.out.println("减法结果: " + difference);
// 乘法
BigDecimal product = bd1.multiply(bd2);
System.out.println("乘法结果: " + product);
// 除法
BigDecimal quotient = bd1.divide(bd2, 3, RoundingMode.HALF_UP);
System.out.println("除法结果: " + quotient);
// 四舍五入
BigDecimal rounded = bd1.setScale(2, RoundingMode.HALF_UP);
System.out.println("四舍五入结果: " + rounded);
// 比较大小
int comparison = bd1.compareTo(bd2);
if (comparison > 0) {
System.out.println("bd1 大于 bd2");
} else if (comparison < 0) {
System.out.println("bd1 小于 bd2");
} else {
System.out.println("bd1 等于 bd2");
}
}
}
System
类是一个final类,所以不允许被继承。它包含一些有用的类字段和方法,用于与系统环境进行交互。
System.in
: 标准输入流(通常是键盘输入)。System.out
: 标准输出流(通常是控制台输出)。System.err
: 标准错误输出流(通常是控制台错误输出)。arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
: 从一个数组复制一段内容到另一个数组。currentTimeMillis()
: 返回当前时间(以毫秒为单位,从1970年1月1日00:00:00 UTC开始)。gc()
: 请求Java虚拟机进行垃圾回收。exit(int status)
: 终止当前运行的Java虚拟机,status
为退出状态码。identityHashCode(Object x)
: 返回对象的内存地址的哈希码。getProperties()
: 获取当前系统属性。setProperty(String key, String value)
: 设置系统属性。lineSeparator()
: 返回当前系统的行分隔符。import java.util.Properties;
public class SystemExample {
public static void main(String[] args) {
// 使用System.out.println输出到标准输出
System.out.println("Hello, World!");
// 使用System.err.println输出到标准错误
System.err.println("This is an error message.");
// 复制数组
char[] srcArray = {'a', 'b', 'c', 'd', 'e'};
char[] destArray = new char[5];
System.arraycopy(srcArray, 0, destArray, 0, 3);
for (char c : destArray) {
System.out.print(c); // 输出: abcde
}
System.out.println();
// 获取当前时间
long currentTime = System.currentTimeMillis();
System.out.println("Current time in milliseconds: " + currentTime);
// 获取系统属性
Properties properties = System.getProperties();
System.out.println("Java Home: " + properties.getProperty("java.home"));
System.out.println("OS Name: " + properties.getProperty("os.name"));
System.out.println("User Home: " + properties.getProperty("user.home"));
// 设置系统属性
System.setProperty("example.property", "Example Value");
System.out.println("Example Property: " + System.getProperty("example.property"));
// 获取行分隔符
String lineSeparator = System.lineSeparator();
System.out.println("Line Separator: " + lineSeparator);
}
}
System.in
是一个标准输入流,通常用于读取键盘输入。下面是一个简单的示例,展示了如何使用 System.in
读取用户输入的整数:
import java.util.Scanner;
public class SystemInExample {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("请输入一个整数:");
int number = scanner.nextInt();
System.out.println("您输入的整数是:" + number);
scanner.close(); // 关闭扫描器
}
}
在Java中,日期和时间相关的类位于java.util
包中,主要有以下几个类:
Date
- 用于表示特定的瞬间,通常称为日期和时间。Calendar
- 用于日期和时间的操作,提供了一些静态方法。SimpleDateFormat
- 用于格式化和解析日期。TimeZone
- 用于表示时区。getTime()
: 返回自1970年1月1日00:00:00 UTC以来的毫秒数。setTime(long time)
: 将日期和时间设置为指定的毫秒数。toString()
: 返回日期和时间的字符串表示。getYear()
: 获取年份。getMonth()
: 获取月份(0-11)。getDate()
: 获取日。getHours()
: 获取小时。getMinutes()
: 获取分钟。getSeconds()
: 获取秒。import java.util.Date;
public class DateExample {
public static void main(String[] args) {
// 获取当前日期和时间
Date currentDate = new Date();
System.out.println("当前日期和时间: " + currentDate);
// 获取日期和时间的毫秒数
long time = currentDate.getTime();
System.out.println("日期和时间的毫秒数: " + time);
// 设置日期和时间
Date newDate = new Date(time);
System.out.println("设置后的日期和时间: " + newDate);
}
}
getInstance()
: 获取当前日历的实例。setTime(Date date)
: 将日期设置到当前日历。getTime()
: 返回当前日历的日期和时间。add(int field, int amount)
: 添加或减去指定日期字段的指定数量。get(int field)
: 获取指定日期字段的值。set(int year, int month, int date)
: 设置年份、月份和日期。import java.util.Calendar;
public class CalendarExample {
public static void main(String[] args) {
// 获取当前日期和时间
Calendar currentCalendar = Calendar.getInstance();
System.out.println("当前日期和时间: " + currentCalendar);
// 设置日期和时间
Calendar newCalendar = Calendar.getInstance();
newCalendar.set(Calendar.YEAR, 2023);
newCalendar.set(Calendar.MONTH, Calendar.NOVEMBER);
newCalendar.set(Calendar.DAY_OF_MONTH, 1);
System.out.println("设置后的日期和时间: " + newCalendar);
}
}
format(Date date)
: 将日期格式化为字符串。parse(String source)
: 将字符串解析为日期。setPattern(String pattern)
: 设置日期和时间的格式模式。、import java.text.ParseException;
import java.text.SimpleDateFormat;
public class SimpleDateFormatExample {
public static void main(String[] args) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formattedDate = simpleDateFormat.format(new Date());
System.out.println("格式化后的日期: " + formattedDate);
String inputDate = "2023-11-01 12:30:45";
try {
Date parsedDate = simpleDateFormat.parse(inputDate);
System.out.println("解析后的日期: " + parsedDate);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
getTimeZone(String ID)
: 根据时区ID获取时区对象。getDisplayName(boolean dst, int style)
:获取时区的简短名称和完整名称。import java.util.TimeZone;
public class TimeZoneDisplayNameExample {
public static void main(String[] args) {
TimeZone timeZone = TimeZone.getTimeZone("GMT+8");
System.out.println("时区对象: " + timeZone);
// 获取简短的时区名称
String shortName = timeZone.getDisplayName(false, TimeZone.SHORT);
System.out.println("简短的时区名称: " + shortName);
// 获取完整的时区名称
String longName = timeZone.getDisplayName(false, TimeZone.LONG);
System.out.println("完整的时区名称: " + longName);
}
}
在Java 8及更高版本中,引入了新的日期和时间API,位于java.time
包中。这个新的API提供了更好的日期和时间处理功能,并且是线程安全的。主要有以下几个类:
LocalDate
类表示日期,不包含时间部分。它提供了日期相关的操作和格式化方法。LocalDateTime
类用于表示日期和时间,它结合了LocalDate
和LocalTime
两个类。LocalDate
类用于表示日期,不包含时间部分。它提供了日期相关的操作和格式化方法。
重要方法:
now()
: 获取当前日期。of(int year, int month, int dayOfMonth)
: 创建一个日期对象。plusYears(long yearsToAdd)
: 增加指定的年数。minusYears(long yearsToSubtract)
: 减少指定的年数。format(DateTimeFormatter formatter)
: 使用指定的格式器格式化日期。import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class LocalDateExample {
public static void main(String[] args) {
// 获取当前日期
LocalDate currentDate = LocalDate.now();
System.out.println("当前日期: " + currentDate);
// 创建特定日期
LocalDate specificDate = LocalDate.of(2023, 11, 1);
System.out.println("特定日期: " + specificDate);
// 增加天数
LocalDate newDate = currentDate.plusDays(10);
System.out.println("增加10天后: " + newDate);
// 减少天数
LocalDate oldDate = currentDate.minusDays(10);
System.out.println("减少10天后: " + oldDate);
// 格式化日期
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String formattedDate = currentDate.format(formatter);
System.out.println("格式化后的日期: " + formattedDate);
}
}
LocalDateTime
类用于表示日期和时间,它结合了LocalDate
和LocalTime
两个类。
重要方法:
now()
: 获取当前日期和时间。of(int year, int month, int dayOfMonth, int hour, int minute, int second)
: 创建一个日期时间对象。plusHours(long hoursToAdd)
: 增加指定的小时数。minusHours(long hoursToSubtract)
: 减少指定的小时数。format(DateTimeFormatter formatter)
: 使用指定的格式器格式化日期和时间。import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class LocalDateTimeExample {
public static void main(String[] args) {
// 获取当前日期和时间
LocalDateTime currentDateTime = LocalDateTime.now();
System.out.println("当前日期和时间: " + currentDateTime);
// 创建特定日期和时间
LocalDateTime specificDateTime = LocalDateTime.of(2023, 11, 1, 12, 30, 45);
System.out.println("特定日期和时间: " + specificDateTime);
// 增加小时数
LocalDateTime newDateTime = currentDateTime.plusHours(10);
System.out.println("增加10小时后: " + newDateTime);
// 减少小时数
LocalDateTime oldDateTime = currentDateTime.minusHours(10);
System.out.println("减少10小时后: " + oldDateTime);
// 格式化日期和时间
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formattedDateTime = currentDateTime.format(formatter);
System.out.println("格式化后的日期和时间: " + formattedDateTime);
}
}
Collection:这是集合框架中的根接口,它表示一组对象,称为元素。Collection
接口继承了Iterable
接口,因此可以被用于增强的for循环中。
ArrayList
、LinkedList
和Vector
。HashSet
、LinkedHashSet
和TreeSet
。Map:将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。实现类包括HashMap
、LinkedHashMap
、TreeMap
和Hashtable
。
其他接口和类:
PriorityQueue
和LinkedList
(它实现了Queue
接口)。Queue
,代表双端队列,允许元素从两端被添加或移除。实现类包括ArrayDeque
和LinkedList
。List接口:
Set接口:
HashSet
,即插入顺序。不是线程安全的。Map接口:
HashMap
,即插入顺序。不是线程安全的。Java 集合框架提供了一套丰富的接口和类,用于存储和管理对象集合。以下是集合类中的一些常用方法,按照集合接口进行分类总结:
add(E e)
:添加元素到集合中。addAll(Collection extends E> c)
:添加指定集合中的所有元素到当前集合中。clear()
:移除集合中的所有元素。contains(Object o)
:如果集合包含指定的元素,则返回 true。containsAll(Collection> c)
:如果集合包含指定集合中的所有元素,则返回 true。isEmpty()
:如果集合不包含任何元素,则返回 true。iterator()
:返回集合中元素的迭代器。remove(Object o)
:从集合中移除指定的元素。removeAll(Collection> c)
:移除集合中所有也包含在指定集合中的元素。retainAll(Collection> c)
:仅保留集合中包含在指定集合中的元素。size()
:返回集合中元素的数量。toArray()
:返回包含集合中所有元素的数组。import java.util.ArrayList;
import java.util.Collection;
public class CollectionExample {
public static void main(String[] args) {
Collection collection = new ArrayList<>();
// 添加元素
collection.add("Apple");
collection.add("Banana");
collection.add("Cherry");
// 预期结果: [Apple, Banana, Cherry]
System.out.println("Collection: " + collection);
// 检查集合是否包含某个元素
// 预期结果: true
System.out.println("Contains 'Apple': " + collection.contains("Apple"));
// 移除元素
collection.remove("Banana");
// 预期结果: [Apple, Cherry]
System.out.println("Collection after removal: " + collection);
// 获取集合大小
// 预期结果: 2
System.out.println("Size of collection: " + collection.size());
// 将集合转换为数组
Object[] array = collection.toArray();
// 预期结果: [Apple, Cherry]
System.out.println("Array: " + java.util.Arrays.toString(array));
}
}
add(int index, E element)
:在指定位置插入元素。addAll(int index, Collection extends E> c)
:在指定位置插入指定集合中的所有元素。get(int index)
:返回指定位置的元素。indexOf(Object o)
:返回指定元素在集合中首次出现的位置。lastIndexOf(Object o)
:返回指定元素在集合中最后一次出现的位置。listIterator()
:返回列表的列表迭代器。remove(int index)
:移除指定位置的元素。set(int index, E element)
:用指定元素替换指定位置的元素。import java.util.ArrayList;
import java.util.List;
public class ListExample {
public static void main(String[] args) {
List list = new ArrayList<>();
// 添加元素
list.add("Apple");
list.add("Banana");
list.add("Cherry");
// 在指定位置插入元素
list.add(1, "Grape");
// 预期结果: [Apple, Grape, Banana, Cherry]
System.out.println("List after insertion: " + list);
// 获取指定位置的元素
// 预期结果: Grape
System.out.println("Element at index 1: " + list.get(1));
// 替换指定位置的元素
list.set(2, "Mango");
// 预期结果: [Apple, Grape, Mango, Cherry]
System.out.println("List after replacement: " + list);
// 移除指定位置的元素
list.remove(0);
// 预期结果: [Grape, Mango, Cherry]
System.out.println("List after removal: " + list);
}
}
add(E e)
:添加元素到集合中,如果集合已经包含该元素,则不会添加。addAll(Collection extends E> c)
:添加指定集合中的所有元素,忽略已经存在的元素。containsAll(Collection> c)
:如果集合包含指定集合中的所有元素,则返回 true。import java.util.HashSet;
import java.util.Set;
public class SetExample {
public static void main(String[] args) {
// 创建一个 Set 对象
Set set = new HashSet<>();
// 添加元素
set.add("Apple");
set.add("Banana");
set.add("Cherry");
// 检查集合是否包含某个元素
System.out.println("Contains 'Apple': " + set.contains("Apple"));
// 预期输出: Contains 'Apple': true
// 获取集合大小
System.out.println("Size of set: " + set.size());
// 预期输出: Size of set: 3
// 尝试添加重复元素
set.add("Apple"); // 不会有任何效果,因为 Set 不允许重复
// 输出整个集合
System.out.println("Set: " + set);
// 预期输出: Set: [Apple, Banana, Cherry]
// 移除元素
set.remove("Banana");
System.out.println("Set after removal: " + set);
// 预期输出: Set after removal: [Apple, Cherry]
}
}
clear()
:移除所有映射关系。containsKey(Object key)
:如果映射包含指定的键,则返回 true。containsValue(Object value)
:如果映射将一个或多个键映射到指定的值,则返回 true。entrySet()
:返回映射中包含的映射关系的 Set 视图。get(Object key)
:返回指定键所映射的值。keySet()
:返回映射中包含的键的 Set 视图。put(K key, V value)
:将指定的值与此映射中的指定键关联。putAll(Map extends K, ? extends V> m)
:从指定映射中将所有映射关系复制到此映射中。remove(Object key)
:如果存在,则从映射中移除键的映射关系。size()
:返回映射中的键-值映射关系数。values()
:返回映射中包含的值的 Collection 视图。import java.util.HashMap;
import java.util.Map;
public class MapExample {
public static void main(String[] args) {
// 创建一个 Map 对象
Map map = new HashMap<>();
// 添加键值对
map.put("Apple", 1);
map.put("Banana", 2);
map.put("Cherry", 3);
// 获取键值对
System.out.println("获取键值对:");
for (Map.Entry entry : map.entrySet()) {
System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}
// 预期输出: Key: Apple, Value: 1
// Key: Banana, Value: 2
// Key: Cherry, Value: 3
// 获取键对应的值
System.out.println("\n获取键对应的值:");
Integer value = map.get("Apple");
System.out.println("Value for 'Apple': " + value);
// 预期输出: Value for 'Apple': 1
// 检查键是否存在
System.out.println("\n检查键是否存在:");
boolean containsKey = map.containsKey("Apple");
System.out.println("Contains key 'Apple': " + containsKey);
// 预期输出: Contains key 'Apple': true
// 检查值是否存在
System.out.println("\n检查值是否存在:");
boolean containsValue = map.containsValue(2);
System.out.println("Contains value 2: " + containsValue);
// 预期输出: Contains value 2: true
// 移除键值对
map.remove("Cherry");
System.out.println("\n移除键值对:");
System.out.println("After removing 'Cherry': " + map);
// 预期输出: After removing 'Cherry': {Apple=1, Banana=2}
}
}
entrySet()
和 keySet()
方法用于返回映射中包含的键值对(Map.Entry
)的集合视图。这些方法提供了不同的方式来访问 Map
中的元素。
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Iterator;
public class EntrySetAndKeySetExample {
public static void main(String[] args) {
Map map = new HashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
map.put("Cherry", 3);
// 使用 entrySet() 遍历所有键值对
System.out.println("使用 entrySet() 遍历所有键值对:");
Set> entrySet = map.entrySet();
for (Map.Entry entry : entrySet) {
System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}
// 预期输出: Key: Apple, Value: 1
// Key: Banana, Value: 2
// Key: Cherry, Value: 3
// 使用 keySet() 遍历所有键
System.out.println("\n使用 keySet() 遍历所有键:");
Set keySet = map.keySet();
for (String key : keySet) {
System.out.println("Key: " + key + ", Value: " + map.get(key));
}
// 预期输出: Key: Apple, Value: 1
// Key: Banana, Value: 2
// Key: Cherry, Value: 3
}
}
hasNext()
:如果迭代器指向的集合中还有元素,则返回 true。next()
:返回迭代器指向的集合中的下一个元素。remove()
:从迭代器指向的集合中移除迭代器返回的最后一个元素。import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class IteratorExample {
public static void main(String[] args) {
// 创建一个 List 对象
List list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Cherry");
// 获取 Iterator 对象
Iterator iterator = list.iterator();
// 使用 Iterator 遍历 List
System.out.println("使用 Iterator 遍历 List:");
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
}
// 预期输出: Apple, Banana, Cherry
// 尝试使用 remove 方法移除元素
System.out.println("\n尝试使用 remove 方法移除元素:");
iterator = list.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
if ("Banana".equals(element)) {
iterator.remove();
}
}
System.out.println("After removing 'Banana': " + list);
// 预期输出: [Apple, Cherry]
}
}
hasPrevious()
:如果迭代器指向的列表中有前一个元素,则返回 true。previous()
:返回迭代器指向的列表中的前一个元素。add(E e)
:在迭代器当前位置前添加一个元素。set(E e)
:用指定元素替换迭代器返回的最后一个元素。import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
public class ListIteratorExample {
public static void main(String[] args) {
List list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Cherry");
ListIterator listIterator = list.listIterator();
// 正向遍历列表
System.out.println("正向遍历列表:");
while (listIterator.hasNext()) {
String fruit = listIterator.next();
System.out.println(fruit);
}
// 预期输出: Apple, Banana, Cherry
// 反向遍历列表
System.out.println("\n反向遍历列表:");
while (listIterator.hasPrevious()) {
String fruit = listIterator.previous();
System.out.println(fruit);
}
// 预期输出: Cherry, Banana, Apple
// 修改列表中的元素
listIterator.set("Grape");
System.out.println("\n修改列表中的元素:");
System.out.println("After modification: " + list);
// 预期输出: [Apple, Banana, Grape]
// 在当前位置添加元素
listIterator.add("Mango");
System.out.println("\n在当前位置添加元素:");
System.out.println("After addition: " + list);
// 预期输出: [Apple, Banana, Grape, Mango]
}
}
A
和 B
,请编写一个方法,输出这两个集合的并集和交集IOException
和SQLException
。NullPointerException
、ArrayIndexOutOfBoundsException
)和错误(如OutOfMemoryError
)。try 块:将可能抛出异常的代码放在try
块中。如果try
块中的代码抛出了异常,则尝试找到匹配的catch
块来处理它。
catch 块:用于捕获并处理try
块中抛出的异常。可以有多个catch
块来捕获不同类型的异常。
finally 块:无论是否捕获或处理异常,finally
块中的代码总是会执行。通常用于释放资源。
throw 关键字:用于显式地抛出一个异常。
throws 关键字:用于在方法签名中声明该方法可能抛出的异常。
try {
// 可能抛出异常的代码
} catch (特定异常类型1 e) {
// 当抛出特定异常类型1时执行的代码
} catch (特定异常类型2 e) {
// 当抛出特定异常类型2时执行的代码
} finally {
// 无论是否捕获异常都会执行的代码
}
public class ExceptionDemo {
public static void main(String[] args) {
try {
int result = divide(10, 0);
System.out.println("结果为: " + result);
} catch (ArithmeticException e) {
System.out.println("捕获到算术异常: " + e.getMessage());
} finally {
System.out.println("这是finally块,总是会执行。");
}
}
public static int divide(int a, int b) throws ArithmeticException {
return a / b; // 可能会抛出除以0的异常
}
}
java.io.File
类是一个用于文件和目录操作的类。它提供了一组静态方法和实例方法,用于创建、删除、移动、重命名文件和目录,以及获取文件和目录的信息。
boolean exists()
:判断文件或目录是否存在。boolean isDirectory()
:判断对象是否是一个目录。boolean isFile()
:判断对象是否是一个文件。boolean isHidden()
:判断文件是否是隐藏文件。long lastModified()
:返回文件或目录最后一次被修改的时间戳。String[] list()
:返回指定目录中的所有子文件和子目录的名称数组。File[] listFiles()
:返回指定目录中的所有子文件和子目录的 File
对象数组。boolean mkdir()
:创建指定目录。boolean mkdirs()
:创建指定目录及其所有父目录。boolean renameTo(File dest)
:将此文件重命名为指定的文件。boolean setExecutable(boolean executable)
:设置文件是否可执行。boolean setReadable(boolean readable)
:设置文件是否可读。boolean setReadOnly()
:设置文件是否只读。boolean setWritable(boolean writable)
:设置文件是否可写。void setLastModified(long time)
:设置文件的最后修改时间戳。void setReadOnly()
:将文件设置为只读。File[] listRoots()
:返回所有文件系统的根目录。String pathSeparator
:文件路径分隔符。String separator
:文件系统分隔符。void setExecutable(File file, boolean executable)
:设置文件是否可执行。void setReadable(File file, boolean readable)
:设置文件是否可读。void setReadOnly(File file)
:设置文件是否只读。void setWritable(File file, boolean writable)
:设置文件是否可写。简单的 Java 代码示例,展示了如何使用 java.io.File
类来创建、删除和重命名文件:
import java.io.File;
public class FileExample {
public static void main(String[] args) {
// 创建一个新的 File 对象
File file = new File("example.txt");
// 创建文件
if (!file.exists()) {
try {
if (file.createNewFile()) {
System.out.println("文件创建成功");
} else {
System.out.println("文件创建失败");
}
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println("文件已存在");
}
// 删除文件
if (file.delete()) {
System.out.println("文件删除成功");
} else {
System.out.println("文件删除失败");
}
// 重命名文件
File newFile = new File("newExample.txt");
if (file.renameTo(newFile)) {
System.out.println("文件重命名成功");
} else {
System.out.println("文件重命名失败");
}
}
}
文件的输入/输出流(I/O)操作通常使用 java.io
包中的类来实现。这个包提供了多种流类,用于读取和写入文件。而带缓存的输入/输出流(I/O)可以提高读写文件的效率。带缓存的流会先将数据读取到内存中的缓冲区,或者先将数据写入内存中的缓冲区,然后再将缓冲区的数据写入文件或从文件读取。
字节流:
FileInputStream
:用于读取以字节形式存储的文件。BufferedInputStream
:增强 FileInputStream
的性能,提供缓冲功能。字符流:
FileReader
:用于读取以字符形式存储的文件。BufferedReader
:增强 FileReader
的性能,提供缓冲功能。字节流:
FileOutputStream
:用于写入以字节形式存储的文件。BufferedOutputStream
:增强 FileOutputStream
的性能,提供缓冲功能。字符流:
FileWriter
:用于写入以字符形式存储的文件。BufferedWriter
:增强 FileWriter
的性能,提供缓冲功能。因为缓存的输入/输出处理大量数据提高性能,所以以缓存的输入/输出作为示例代码:
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class ByteStreamReadExample {
public static void main(String[] args) {
String filePath = "example.txt";
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath))) {
int data;
while ((data = bis.read()) != -1) {
System.out.print((char) data);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
public class ByteStreamWriteExample {
public static void main(String[] args) {
String filePath = "example.txt";
try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath))) {
bos.write("Hello, World!".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class CharStreamReadExample {
public static void main(String[] args) {
String filePath = "example.txt";
try (BufferedReader br = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class CharStreamWriteExample {
public static void main(String[] args) {
String filePath = "example.txt";
try (BufferedWriter bw = new BufferedWriter(new FileWriter(filePath))) {
bw.write("Hello, World!");
bw.newLine(); // 写入新行
} catch (IOException e) {
e.printStackTrace();
}
}
}
不是一定要使用带缓存的输入/输出流。使用带缓存的流可以提高文件读写的效率,但并不是在所有情况下都是必需的。以下是一些使用或不使用带缓存流的考虑因素:
大量数据的读写:如果需要处理大量数据,使用带缓存流可以减少对文件系统的直接访问次数,从而提高读写速度。
网络文件读写:在处理网络文件时,由于网络延迟,使用带缓存流可以减少等待时间。
性能优化:在需要提高程序性能的情况下,使用带缓存流可以减少 I/O 操作的次数,从而优化程序性能。
小文件的读写:对于小文件,由于文件本身不大,带缓存的优势可能不明显,甚至可能会增加内存使用。
内存限制:如果系统内存有限,使用带缓存流可能会消耗更多的内存资源,这可能会导致性能下降。
特定应用场景:在某些特定的应用场景下,如实时数据处理或需要实时响应的应用,使用带缓存流可能会引入额外的延迟。