厉兵秣马之Java 语言基础和进阶(二)
- 5. 抽象类
- 6. 接口
- 7. 抽象类与接口区别
- 8. JAVA集合类的使用
- 9 JAVA包、内部类和匿名类
- 10 数组
- 11 字符串
- 12.文件处理 Apache Commons IO
- 13. JAVA异常类的使用
5. 抽象类
抽象类是Java中一种不能被实例化的类,它通常包含抽象方法,这些方法没有具体的实现,需要在子类中被具体实现。抽象类是面向对象编程中抽象化的一种手段,它提供了一种方式来定义一组相关类共享的通用模板,同时强制要求子类实现某些方法。
抽象类的特点
- 不能实例化:你不能创建抽象类的对象。
- 可以包含抽象方法:抽象方法没有实现,需要在子类中被重写。
- 可以包含具体方法:抽象类可以包含已经实现的方法,这些方法可以被子类继承和使用。
- 可以有成员变量:抽象类可以有成员变量,这些变量可以是
private
、protected
、public
或static
。 - 可以被继承:其他类可以通过
extends
关键字继承抽象类,并提供抽象类中抽象方法的具体实现。
抽象类的使用
抽象类通常用于以下情况:
- 当你想要定义一个通用模板,但不想允许直接创建该类的对象时。
- 当你想要提供一个或多个方法的部分实现,并要求子类完成剩余部分时。
- 当你想要强制子类遵循特定的协议或行为时。
示例
// 定义一个抽象类
abstract class Animal {
// 抽象方法,没有实现
abstract void makeSound();
// 具体方法,已经被实现
void eat() {
System.out.println("This animal eats");
}
}
// 继承抽象类并实现抽象方法
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Dog barks");
}
}
// 继承抽象类并实现抽象方法
class Cat extends Animal {
@Override
void makeSound() {
System.out.println("Cat meows");
}
}
public class Main {
public static void main(String[] args) {
Animal myDog = new Dog(); // 合法,可以创建子类的实例
myDog.makeSound(); // 输出: Dog barks
myDog.eat(); // 输出: This animal eats
// Animal myAnimal = new Animal(); // 非法,不能创建抽象类的对象
}
}
在这个例子中,Animal
是一个抽象类,它包含一个抽象方法makeSound
和一个具体方法eat
。Dog
和Cat
类继承自Animal
类,并提供了makeSound
方法的具体实现。在main
方法中,我们可以创建Dog
和Cat
的对象,但不能创建Animal
的对象。
抽象类是Java中实现代码重用和确保子类遵循特定协议的有效方式。通过使用抽象类,你可以定义一个通用的模板,并通过子类来提供具体的实现,从而实现代码的灵活性和可扩展性。
6. 接口
接口可以理解为一种特殊的类,里面全部都是由全局常量和公共的抽象方法所组成
1.接口必须有子类,并且子类要实现全部的抽象方法
2.一个子类可以实现多个接口,但是一个子类只能继承一个抽象类
3.一个接口可以继承多个接口
4.一个子类可以继承抽象类同时实现接口
接口(Interface)在Java中是一种特殊的抽象类型,它是一组方法声明的集合,这些方法没有具体的实现。接口主要用于定义类必须遵守的契约或行为规范。接口是Java实现多态的一种机制,允许不同的类以自己的方式实现相同的方法。
接口的特点
- 抽象方法:接口中的方法默认是
public
和abstract
的,这意味着它们没有实现,必须由实现接口的类来提供具体实现。 - 默认方法:从Java 8开始,接口可以包含默认方法(
default
方法),这些方法有实现,可以被实现类继承。 - 静态方法:接口也可以包含静态方法,这些方法可以直接通过接口调用,不需要实现。
- 常量:接口中可以定义常量,即
public static final
变量。 - 多重实现:一个类可以实现多个接口,这允许类具有多个类型的属性和行为。
- 继承:接口可以继承自一个或多个其他接口,这有助于代码的组织和重用。
接口的用途
接口主要用于以下目的:
- 定义契约:接口定义了实现类必须遵守的规则和行为。
- 实现多态:通过实现相同的接口,不同的类可以以不同的方式响应相同的方法调用。
- 代码解耦:接口允许代码与具体实现分离,提高代码的灵活性和可维护性。
- 扩展功能:通过实现不同的接口,类可以扩展其功能,而不需要修改现有的代码。
示例
// 定义一个接口
interface Flyable {
void fly();
}
// 定义一个接口
interface Swimmable {
void swim();
}
// 实现接口
class Bird implements Flyable {
public void fly() {
System.out.println("Bird is flying");
}
}
class Fish implements Swimmable {
public void swim() {
System.out.println("Fish is swimming");
}
}
// 多重实现
class Duck implements Flyable, Swimmable {
public void fly() {
System.out.println("Duck is flying");
}
public void swim() {
System.out.println("Duck can also swim");
}
}
public class Main {
public static void main(String[] args) {
Flyable myBird = new Bird();
myBird.fly(); // 输出: Bird is flying
Swimmable myFish = new Fish();
myFish.swim(); // 输出: Fish is swimming
Flyable myDuck = new Duck();
myDuck.fly(); // 输出: Duck is flying
}
}
在这个例子中,Flyable
和Swimmable
是两个接口,它们定义了fly
和swim
方法。Bird
和Fish
类分别实现了这些接口,而Duck
类实现了两个接口,展示了多重实现的能力。
接口是Java中实现多态和定义契约的强大工具,它们使得代码更加灵活和可扩展。通过接口,Java程序可以轻松地适应变化,支持新的功能和行为。
7. 抽象类与接口区别
接口(Interface)和抽象类(Abstract Class)在Java中都是用于定义不能被实例化的类型,它们都可以包含抽象方法,但它们之间存在一些关键的区别:
-
继承限制:
- 一个类可以实现多个接口,但只能继承自一个抽象类或具体类。这使得接口成为实现多重继承的一种方式。
- 抽象类可以继承自另一个抽象类或具体类。
-
方法实现:
- 接口中的所有方法默认都是抽象的,必须由实现接口的类提供具体实现。
- 抽象类可以包含抽象方法和具体方法。抽象类中的抽象方法必须由子类实现,而具体方法可以直接使用。
-
构造方法:
- 接口不能包含构造方法,因为它们不能被实例化。
- 抽象类可以包含构造方法,但这些构造方法不能从外部访问,只能被子类调用。
-
成员变量:
- 接口中的成员变量默认是
public static final
的,即它们是常量。 - 抽象类中的成员变量可以是
private
、protected
、public
或static
,并且可以不是final
的。
- 接口中的成员变量默认是
-
实例化:
- 接口不能被实例化,但可以从接口类型引用变量指向实现该接口的具体类的实例。
- 抽象类不能被直接实例化,但可以创建其实例的引用指向其子类的实例。
-
默认方法和静态方法:
- 从Java 8开始,接口可以包含默认方法(
default
方法),这些方法有默认实现,可以被子类覆盖。 - 接口也可以包含静态方法,这些方法可以直接通过接口调用。
- 抽象类可以包含静态方法和非静态方法,这些方法可以有实现。
- 从Java 8开始,接口可以包含默认方法(
-
设计目的:
- 接口主要用于定义一组规范或契约,它们是行为的集合。
- 抽象类用于提供一个通用的模板,它可能包含一些通用的实现,同时定义一些必须由子类实现的方法。
示例
// 接口
interface Flyable {
void fly();
}
// 抽象类
abstract class Animal {
abstract void eat();
void sleep() {
System.out.println("Animal sleeps");
}
}
// 实现接口
class Bird implements Flyable {
public void fly() {
System.out.println("Bird is flying");
}
}
// 继承抽象类
class Dog extends Animal {
public void eat() {
System.out.println("Dog is eating");
}
}
public class Main {
public static void main(String[] args) {
Flyable bird = new Bird();
bird.fly(); // 通过接口引用调用方法
Animal dog = new Dog();
dog.eat(); // 通过抽象类引用调用方法
dog.sleep(); // 调用抽象类中的具体方法
}
}
在这个例子中,Flyable
是一个接口,Animal
是一个抽象类。Bird
类实现了Flyable
接口,而Dog
类继承自Animal
抽象类。接口和抽象类都用于定义规范和行为,但它们的使用方式和设计目的有所不同。
8. JAVA集合类的使用
Java集合类是Java标准库(Java Collections Framework,JCF)的一部分,提供了一组用于存储和处理对象集合的接口和类。集合类可以用于存储、检索、更新和操作数据。Java集合类分为几个主要类别,包括列表(List)、集合(Set)、映射(Map)和队列(Queue)。
8.1. 列表(List)
列表是有序的集合,允许重复的元素。主要的列表接口包括:
List<E>
:有序的集合,可以包含重复的元素。ArrayList<E>
:基于动态数组实现的列表,提供快速随机访问。LinkedList<E>
:基于双向链表实现的列表,提供快速的插入和删除操作。
8.2. 集合(Set)
集合是无序的集合,不允许重复的元素。主要的集合接口包括:
Set<E>
:无序的集合,不允许重复的元素。HashSet<E>
:基于散列实现的集合,提供快速的查找和插入操作。LinkedHashSet<E>
:类似于HashSet
,但维护元素的插入顺序。TreeSet<E>
:基于红黑树实现的集合,元素按自然顺序或指定顺序排序。ASCII表顺序。
8.3. 映射(Map)
映射是键值对的集合,键是唯一的。主要的映射接口包括:
Map<K,V>
:键值对的集合,键是唯一的,健值类型要一致,值的类型也要一致。HashMap<K,V>
:基于散列实现的映射,提供快速的查找和插入操作。LinkedHashMap<K,V>
:类似于HashMap
,但维护键值对的插入顺序。TreeMap<K,V>
:基于红黑树实现的映射,键按自然顺序或指定顺序排序。
8.4. 队列(Queue)
队列是遵循先进先出(FIFO)原则的集合。主要的队列接口包括:
Queue<E>
:先进先出的集合。LinkedList<E>
:可以用作队列的链表实现。PriorityQueue<E>
:基于优先级堆实现的队列,元素按优先级排序。
8.5. 其他集合类
Collection<E>
:List
和Set
的父接口,提供一些通用的操作。Iterator<E>
:用于遍历集合中的元素。ListIterator<E>
:Iterator
的子接口,提供双向遍历和修改列表的能力。Comparable<E>
和Comparator<E>
:用于定义对象的自然顺序和自定义排序。
示例
import java.util.*;
public class CollectionExample {
public static void main(String[] args) {
// 创建列表
List<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
System.out.println(list);
// 创建集合
Set<String> set = new HashSet<>();
set.add("Apple");
set.add("Banana");
System.out.println(set);
// 创建映射
Map<String, Integer> map = new HashMap<>();
map.put("Apple", 1);
map.put("Banana", 2);
System.out.println(map);
// 创建队列
Queue<String> queue = new LinkedList<>();
queue.add("Apple");
queue.add("Banana");
System.out.println(queue);
}
}
(1)如果涉及到堆栈、队列等操作,应该考虑用List,对于需要快速插入,删除元素,应该使用LinkedList,如果需要快速随机访问元素,应该使用ArrayList
(2)哈希表的操作,作为key的对象要正确复写equals和hashCode方法
(3)尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果将来要将ArrayList换成LinkedList时,客户端代码不用改变。
(4)List可以有类似数组的下标操作,且允许有相同的元素存在;Map是以键值对(KeyValue)的形式存在,不能存在相同的键。
(5)ArrayList类
ArrayList实现了可变大小的数组,长度随着元素的增加而变化,且可以存在重复的元
素
(6)HashMap类:允许null,即nullkey,null value。且存在的形式是key-value形式,不允许有key重复。
8.6. 迭代器(Iterator)
迭代器是Java集合框架中的一种设计模式,用于遍历集合中的元素。迭代器提供了一种统一的方式来访问集合中的每个元素,而不需要了解集合的内部结构。迭代器模式的主要优点是它支持对集合的迭代操作,而不需要暴露集合的内部结构。在Java中,迭代器通过java.util.Iterator
接口实现,该接口定义了三个方法:
boolean hasNext()
:返回true
如果迭代器还有更多的元素,否则返回false
。E next()
:返回迭代器的下一个元素。void remove()
:从集合中移除迭代器的最后一个返回的元素。
迭代器通常与Collection
接口一起使用,Collection
接口的iterator()
方法返回一个迭代器对象。以下是使用迭代器遍历集合的示例:
import java.util.ArrayList;
import java.util.Iterator;
public class IteratorExample {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("Apple");
list.add("Banana");
list.add("Cherry");
// 获取迭代器
Iterator<String> iterator = list.iterator();
// 遍历集合
while (iterator.hasNext()) {
String fruit = iterator.next();
System.out.println(fruit);
}
}
}
9 JAVA包、内部类和匿名类
9.1.包(Package)
包是一种组织类和接口的方式,用于将功能相关的类和接口分组在一起。包的主要目的是解决命名冲突问题,提高代码的可读性和可维护性,以及控制访问级别,java包通常反域名将类放置到包中,为了隐藏内部代码还可以将代码达成JAR包提供给消费者
9.2. 内部类:
在一个类的内部存在另外一个类就被成为内部类内部类的优点和缺点:
缺点:破坏了程序的结构
优点:方便的访问外部类中的私有属性
注意:此时内部类是无法直接访问的,如果想访问,需要使用static关键字
内部类(Inner Class)是定义在另一个类内部的类。在Java中,内部类提供了一种将相关类组合在一起的方式,同时保持了封装性和作用域的控制。内部类可以访问其外部类的所有成员,包括私有成员。
-
成员内部类(Static Inner Class):定义在另一个类内部的静态类。它不能访问外部类的实例成员(因为静态成员属于类,不属于实例)。
public class OuterClass { public static class InnerClass { // 可以访问外部类的静态成员 } }
-
非静态内部类(Non-static Inner Class):定义在另一个类内部的非静态类。它可以访问外部类的所有成员,包括私有成员。
public class OuterClass { private int outerVar = 10; public class InnerClass { public void display() { System.out.println(outerVar); // 访问外部类的私有成员 } } }
-
匿名内部类(Anonymous Inner Class):没有名称的内部类,通常用于创建短暂的对象。它们经常用在需要实现接口或继承类的场合。
public class OuterClass { public void method() { // 匿名内部类实现接口 MyInterface myObj = new MyInterface() { public void display() { System.out.println("Anonymous Inner Class"); } }; } }
10 数组
在Java中,数组是一种用于存储固定大小的相同类型元素的集合。数组可以是一维的,也可以是多维的(如二维数组、三维数组等)。数组在内存中是连续存储的,这使得数组的访问非常快速,但也限制了它们的灵活性,因为它们的大小在创建后不能改变。
一维数组
一维数组是最简单的数组形式,它存储了一系列的相同类型的元素。以下是创建和使用一维数组的示例:
// 创建一个整型数组
int[] numbers = new int[5]; // 创建一个长度为5的整型数组
// 初始化数组
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;
// 遍历数组
for (int i = 0; i < numbers.length; i++) {
System.out.println(numbers[i]);
}
多维数组
多维数组可以看作是数组的数组。二维数组常用于表示矩阵或表格。以下是创建和使用二维数组的示例:
// 创建一个二维整型数组
int[][] matrix = new int[3][4]; // 创建一个3行4列的二维整型数组
// 初始化数组
matrix[0][0] = 1;
matrix[0][1] = 2;
matrix[1][0] = 3;
matrix[1][1] = 4;
// ... 初始化其他元素
// 遍历二维数组
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();
}
数组的特性
- 固定大小:数组一旦创建,其大小就不能改变。
- 同质性:数组中的所有元素必须是相同类型的。
- 连续存储:数组元素在内存中是连续存储的,这使得数组的访问速度非常快。
- 索引:数组通过索引访问元素,索引从0开始。
数组的局限性
- 大小固定:数组的大小在创建时确定,之后不能改变。
- 单一类型:数组只能存储一种类型的元素。
- 内存浪费:如果数组的容量大于实际需要,可能会造成内存浪费。
11 字符串
在Java中,String
类是java.lang
包中的一个非常常用的类,用于表示和处理字符串。字符串在Java中是不可变的(immutable),这意味着一旦创建了一个字符串对象,它的内容就不能被改变。
String str = new String("Hello, World!"); // 使用String构造函数
String str2 = "Hello, World!"; // 使用字符串字面量
字符串的特性
- 不可变性:字符串一旦创建,其内容就不能被改变。任何修改字符串的操作都会创建一个新的字符串对象。
- 字符串池:Java维护一个字符串池,用于存储字符串字面量和通过
String.intern()
方法显式加入的字符串。这有助于节省内存,因为相同的字符串字面量在程序中只存储一份。
字符串的方法
String
类提供了丰富的方法来操作字符串,包括:
- 连接和拼接:
concat(String str)
,+
操作符 - 查找和比较:
charAt(int index)
,compareTo(String anotherString)
,equals(Object anObject)
,equalsIgnoreCase(String anotherString)
- 搜索和匹配:
indexOf(int ch)
,indexOf(String str)
,contains(CharSequence s)
- 替换和删除:
replace(char oldChar, char newChar)
,replace(CharSequence target, CharSequence replacement)
- 分割和连接:
split(String regex)
,join(CharSequence delimiter, CharSequence... elements)
- 大小写转换:
toLowerCase()
,toUpperCase()
- 修剪空白:
trim()
示例
public class StringExample {
public static void main(String[] args) {
String greeting = "Hello";
String punctuation = "!";
String message = greeting.concat(punctuation); // "Hello!"
System.out.println(message.equalsIgnoreCase("hello!")); // true
System.out.println(message.indexOf('o')); // 4
String upperCase = message.toUpperCase(); // "HELLO!"
System.out.println(upperCase);
String trimmed = message.trim(); // "Hello!"
System.out.println(trimmed);
}
}
12.文件处理 Apache Commons IO
Apache Commons IO 是 Apache 软件基金会的一个库,提供了许多用于简化 Java IO 操作的工具和实用程序。它补充了 Java 标准库中的 IO 类,提供了更高级的文件操作功能,使得文件和流的处理更加容易和直观。
主要功能
-
文件过滤器:提供了各种文件过滤器,用于在文件操作中筛选文件和目录。
-
文件比较:提供了文件比较的工具,可以比较文件的内容或最后修改时间等。
-
文件复制和移动:提供了文件复制和移动的工具,支持缓冲和流控制。
-
文件删除:提供了递归删除目录和文件的工具。
-
临时文件管理:提供了创建和管理临时文件和目录的工具。
-
流操作:提供了各种流操作的工具,如复制流内容、转换流等。
-
字符编码转换:提供了字符编码转换的工具。
-
文件下载和上传:提供了文件下载和上传的工具。
使用示例
以下是一些使用 Apache Commons IO 的示例:
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class ApacheIOExample {
public static void main(String[] args) {
try {
// 文件复制
File sourceFile = new File("source.txt");
File destFile = new File("dest.txt");
FileUtils.copyFile(sourceFile, destFile);
// 文件内容读取
InputStream inputStream = new FileInputStream(sourceFile);
String content = IOUtils.toString(inputStream, "UTF-8");
IOUtils.closeQuietly(inputStream);
System.out.println(content);
// 文件内容写入
OutputStream outputStream = new FileOutputStream(destFile);
IOUtils.write("Hello, World!", outputStream, "UTF-8");
IOUtils.closeQuietly(outputStream);
// 递归删除目录
File directoryToDelete = new File("directory");
FileUtils.deleteDirectory(directoryToDelete);
} catch (IOException e) {
e.printStackTrace();
}
}
}
- Apache Commons IO 不是 Java 标准库的一部分,因此需要单独添加到项目的依赖中。
- Apache Commons IO 提供了许多便利的方法,但在性能敏感的应用中,直接使用 Java 标准库可能更优。
- Apache Commons IO 的一些方法可能会抛出
IOException
,因此需要适当处理异常。
Apache Commons IO 是一个非常有用的库,它简化了许多常见的 IO 操作,使得开发者可以更专注于业务逻辑而不是底层的 IO 细节。通过使用 Apache Commons IO,可以提高开发效率和代码的可读性。
13. JAVA异常类的使用
13.1. 什么是异常?
程序出错分为两部分:编译时出错和运行时出错。编译时出错是编译器在编译源码时发生的错误;运行时出错,则是编译通过,在运行是出现的错误。这种情况叫异常。例:如数组越界,除数为0,文件找不到等等。
在Java中,异常可以分为两大类:检查型异常(Checked Exception)和非检查型异常(Unchecked Exception)。这两类异常在处理方式和使用上有所不同。
检查型异常(Checked Exception)
检查型异常是必须在编译时处理的异常,这意味着如果一个方法可能抛出检查型异常,那么这个方法必须使用throws
关键字声明这个异常,或者在方法内部捕获这个异常。检查型异常通常是外部因素引起的问题,如文件未找到、网络连接失败等。
常见的检查型异常包括:
IOException
:输入/输出异常,如文件读写错误。SQLException
:数据库访问异常。ClassNotFoundException
:类找不到异常。
非检查型异常(Unchecked Exception)
非检查型异常是编译器不强制处理的异常,包括运行时异常(RuntimeException
)和错误(Error
)。这些异常通常是程序内部逻辑错误引起的,如空指针异常、数组越界等。
运行时异常(RuntimeException)
运行时异常是程序运行时可能发生的错误,通常是由于程序逻辑错误或不当使用API引起的。常见的运行时异常包括:
NullPointerException
:尝试使用空对象时抛出。ArrayIndexOutOfBoundsException
:数组索引越界时抛出。IllegalArgumentException
:传递非法或不适当的参数时抛出。IllegalStateException
:方法调用与对象状态不兼容时抛出。
错误(Error)
错误是严重的程序问题,通常是不可恢复的,如系统崩溃、虚拟机错误等。常见的错误包括:
OutOfMemoryError
:内存不足时抛出。StackOverflowError
:递归调用太深导致栈溢出时抛出。VirtualMachineError
:虚拟机错误,如NoClassDefFoundError
、ClassCastException
等。
public class ExceptionDemo {
public static void main(String[] args) {
try {
// 可能抛出检查型异常的代码
FileReader reader = new FileReader("nonexistent.txt");
} catch (FileNotFoundException e) {
System.out.println("File not found: " + e.getMessage());
}
try {
// 可能抛出运行时异常的代码
int[] numbers = new int[5];
System.out.println(numbers[10]);
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Array index out of bounds: " + e.getMessage());
}
}
}
java异常类的层次
处理异常
13.2. 创建自定义异常
自定义异常类只要继承基类,同时实现方法
在Java中,自定义异常是指开发者根据特定应用需求创建的异常类。自定义异常使得错误处理更加具体化,有助于清晰地表达程序中可能遇到的各种错误情况。创建自定义异常通常是通过继承Exception
类或其子类来实现的。
创建自定义异常类通常涉及以下步骤:
-
确定异常类型:根据错误的性质,决定是继承
Exception
(检查型异常)还是RuntimeException
(运行时异常)。 -
定义异常类:创建一个新的类,继承自
Exception
或RuntimeException
,并添加必要的构造函数和其他方法。 -
实现构造函数:提供至少一个构造函数,通常包括一个无参构造函数和一个接受字符串消息的构造函数。也可以提供其他构造函数,如接受
Throwable
对象的构造函数,用于链式异常。 -
添加方法:根据需要添加额外的方法,这些方法可以提供关于异常的更多信息或执行特定的错误处理逻辑。
以下是一个自定义异常的示例,用于处理用户输入无效的情况:
// 自定义异常类
public class InvalidUserInputException extends Exception {
// 无参构造函数
public InvalidUserInputException() {
super();
}
// 接受错误消息的构造函数
public InvalidUserInputException(String message) {
super(message);
}
// 接受错误消息和原因的构造函数
public InvalidUserInputException(String message, Throwable cause) {
super(message, cause);
}
}
// 使用自定义异常
public class UserInputValidator {
public void validateInput(String input) throws InvalidUserInputException {
if (input == null || input.isEmpty()) {
throw new InvalidUserInputException("Input cannot be null or empty.");
}
// 其他验证逻辑...
}
}
public class Main {
public static void main(String[] args) {
UserInputValidator validator = new UserInputValidator();
try {
validator.validateInput(null);
} catch (InvalidUserInputException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
# 14. FILE 文件管理
在Java中,`java.io.File`类是用于表示文件和目录的抽象表示,它提供了丰富的方法来处理文件和目录。`File`类不是用于流式输入输出的,而是用于文件和目录的属性访问、文件系统导航、文件的创建、删除等操作。
```java
import java.io.File;
public class FileExample {
public static void main(String[] args) {
// 创建File对象
File file = new File("example.txt");
// 检查文件是否存在
if (file.exists()) {
System.out.println("File exists.");
} else {
System.out.println("File does not exist.");
}
// 创建文件
try {
if (file.createNewFile()) {
System.out.println("File created.");
} else {
System.out.println("File already exists.");
}
} catch (IOException e) {
System.out.println("An error occurred.");
}
// 删除文件
if (file.delete()) {
System.out.println("File deleted.");
} else {
System.out.println("Failed to delete file.");
}
// 列出目录中的文件
File directory = new File(".");
File[] files = directory.listFiles();
if (files != null) {
for (File f : files) {
System.out.println(f.getName());
}
}
}
}
标签:Java,进阶,System,接口,厉兵秣马,println,抽象类,public,out
From: https://blog.csdn.net/free_girl_fang/article/details/143222698