Java 程序设计案例教程 课件 周清松 第7-11章 Java实类库 - GUI(图形用户界面)_第1页
Java 程序设计案例教程 课件 周清松 第7-11章 Java实类库 - GUI(图形用户界面)_第2页
Java 程序设计案例教程 课件 周清松 第7-11章 Java实类库 - GUI(图形用户界面)_第3页
Java 程序设计案例教程 课件 周清松 第7-11章 Java实类库 - GUI(图形用户界面)_第4页
Java 程序设计案例教程 课件 周清松 第7-11章 Java实类库 - GUI(图形用户界面)_第5页
已阅读5页,还剩172页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第7章

Java实用类库目录CONTENTS01字符串的奥秘02Math类与Random类03系统交互通道04综合实战演练05回顾与练习指引字符串的奥秘01String不可变设计与创建方式String不可变性Java中String对象一旦创建便不可更改,任何修改操作都会生成新实例。这一特性保证了字符串的哈希值恒定,从而确保线程安全,避免多线程环境下的数据冲突。创建方式创建String对象有多种方式,最常见的是使用字面量直接赋值,如`Stringstr="Hello";`。这种方式简单高效,且相同的字面量会共享内存,节省空间。构造方法String类还提供了多种构造方法,例如`String(char[]a)`可以根据字符数组创建字符串,`String(char[]a,intoffset,intlength)`则可以根据字符数组的一部分创建字符串,提供了灵活的创建选项。String高频方法速查常用方法String类提供了丰富的常用方法,如`length()`获取字符串长度,`charAt(intindex)`获取指定索引处的字符,`equals(ObjectanObject)`比较字符串内容等,这些方法是字符串处理的基础工具。StringBuffer与StringBuilder选型01StringBufferStringBuffer是一个线程安全的可变字符序列,适合在多线程环境中使用。它的方法是同步的,因此在并发场景下可以保证数据的正确性。02StringBuilderStringBuilder是Java5新增的可变字符序列类,与StringBuffer功能类似,但它是非线程安全的,因此在单线程环境下性能更高,是更常用的选择。03性能差异由于StringBuffer的同步机制,它在多线程环境下虽然安全,但会带来一定的性能开销。而StringBuilder去掉了同步锁,因此在单线程场景下速度更快。04选择建议在选择StringBuffer还是StringBuilder时,主要考虑线程安全性和性能。如果需要在多线程环境下操作字符串,应使用StringBuffer;在单线程环境下,推荐使用StringBuilder。Math类与Random类02Math类常量与绝对值取整数学常量Math类提供了两个重要的数学常量:Math.PI表示圆周率π,其值约为3.141592653589793;Math.E表示自然对数的底e,其值约为2.718281828459045。这些常量在数学计算中非常有用。绝对值与取整Math类提供了多种绝对值方法,如`Math.abs(inta)`返回int值的绝对值,`Math.abs(doublea)`返回double值的绝对值。此外,还有`Math.ceil(doublea)`向上取整,`Math.floor(doublea)`向下取整,以及`Math.round(doublea)`四舍五入等方法。Math类幂根与三角对数幂运算Math类中的`Math.pow(doublea,doubleb)`方法用于计算a的b次幂。例如,`Math.pow(2.0,3.0)`返回8.0,表示2的3次幂。开方运算Math类提供了`Math.sqrt(doublea)`用于计算a的正平方根,`Math.cbrt(doublea)`用于计算a的立方根。例如,`Math.sqrt(16.0)`返回4.0,`Math.cbrt(27.0)`返回3.0。三角函数Math类还提供了丰富的三角函数方法,如`Math.sin(doublea)`、`Math.cos(doublea)`和`Math.tan(doublea)`分别计算正弦、余弦和正切值。这些方法的参数是以弧度为单位的。Random类构造与种子控制构造方法Random类提供了两种构造方法:无参构造方法`Random()`使用当前系统时间的毫秒数作为种子,每次运行时生成的随机数序列不同;带参构造方法`Random(longseed)`使用指定的种子,可以生成可重复的随机数序列。种子的作用种子在随机数生成中起着关键作用。使用相同的种子创建多个Random实例,它们将生成相同的随机数序列。这在需要可重复的随机数序列时非常有用,例如在测试或模拟中。Random类多类型随机数生成整数随机数Random类的`nextInt()`方法返回一个随机整数,`nextInt(intn)`方法返回一个在0(包括)和指定值n(不包括)之间的随机整数。长整型随机数Random类的`nextLong()`方法返回一个随机长整数。浮点数随机数Random类的`nextFloat()`方法返回一个在0.0和1.0之间的随机浮点数,`nextDouble()`方法返回一个在0.0和1.0之间的随机双精度浮点数。布尔型随机数Random类的`nextBoolean()`方法返回一个随机布尔值,`nextGaussian()`方法返回一个呈高斯分布的随机双精度浮点数。系统交互通道03System标准流与环境属性标准流System类提供了三个静态的PrintStream对象:System.in代表标准输入流,通常与键盘输入关联;System.out代表标准输出流,通常与控制台输出关联;System.err代表标准错误输出流,用于输出错误信息。环境属性System类的`getProperty(Stringkey)`方法用于获取系统属性。例如,`System.getProperty("java.version")`返回Java运行时环境版本,`System.getProperty("")`返回操作系统名称。System时间数组与虚拟机控制

01时间获取System类的`currentTimeMillis()`方法返回当前时间的毫秒数,从1970年1月1日00:00:00GMT开始计算。该方法常用于测量代码执行时间和生成时间戳。02数组复制System类的`arraycopy(Objectsrc,intsrcPos,Objectdest,intdestPos,intlength)`方法用于将源数组中指定范围的元素复制到目标数组的指定位置。这是一个高效的数组复制方法。03虚拟机控制System类的`exit(intstatus)`方法用于终止当前正在运行的Java虚拟机。非零的状态码通常表示异常终止。`gc()`方法用于运行垃圾回收器,但不能保证立即执行。综合实战演练04日志记录器需求与类结构设计日志记录器需求日志记录器需要支持INFO、WARNING、ERROR三种日志级别,每条日志包含时间戳、随机事件ID和消息文本。INFO和WARNING级别的日志输出到标准输出流,ERROR级别的日志输出到标准错误流。类结构设计SimpleLogger类包含三个静态方法:logInfo、logWarning和logError,分别用于记录不同级别的日志。类内使用私有静态Random实例生成随机事件ID,保证多线程复用。日志格式日志格式为`[时间][级别][事件ID]消息`,其中时间使用`%tF%tT`格式化为YYYY-MM-DD和HH:MM:SS,事件ID由Random生成,消息为用户传入的字符串。时间戳与随机ID生成实现时间戳获取在日志方法中调用`System.currentTimeMillis()`获取当前时间的毫秒数,并使用`%tF`和`%tT`格式化为日期和时间。随机ID生成使用`Random`类的`nextInt(1000)`方法生成0到999之间的随机事件ID,确保每条日志都有唯一的标识。分级输出与运行效果展示分级输出INFO和WARNING级别的日志使用`System.out.println()`输出,ERROR级别的日志使用`System.err.println()`输出,便于在控制台区分日志类型。运行效果运行示例显示,同一秒内多条日志拥有不同的事件ID,ERROR级别的日志以红色显示,方便快速定位错误信息。日志示例示例输出:`[2025-05-1107:10:00][INFO][事件ID:345]应用程序启动。`,`[2025-05-1107:10:00][ERROR][事件ID:567]发生了一个严重的错误!`。回顾与练习指引05核心概念速览与易错点提醒核心概念String的不可变性带来了安全性和复用优势,Math类提供了丰富的数学运算方法,Random类用于生成随机数,System类用于与系统交互。易错点提醒StringBuffer和StringBuilder的区别在于线程安全性和性能,Math类中的角度计算需要转换为弧度,System类的属性读取返回的是字符串,需要自行解析。课后编程练习解析思路字符串反转字符串反转可以使用StringBuilder的reverse方法实现,也可以通过手动交换字符数组的首尾元素来完成,后者可以锻炼对数组的操作能力。随机验证码生成生成指定位数的随机验证码时,需要定义一个包含字母和数字的字符池,然后使用Random类的nextInt方法随机选取字符拼接成结果。感谢您的观看THANK

YOU

FOR

WATCHING第8章

集合01集合框架总览与数组差异02List接口与双线实现03Set接口与去重艺术04Map接口与键值宇宙05遍历、排序与泛型安全06实战案例与综合演练集合框架总览与数组差异01集合框架诞生的背景与使命数组的局限性数组在Java中被广泛使用,但存在明显局限性:长度固定,一旦声明无法改变;只能存储同一种类型数据;操作功能单一,仅支持基本的索引访问和修改。集合框架的使命Java集合框架旨在解决数组的局限性,提供动态扩容、类型安全和丰富的操作功能,以满足复杂多变的开发需求。集合框架的价值集合框架通过灵活的数据结构和丰富的API,极大地提高了开发效率,使开发者能够更高效地处理动态数据和复杂业务逻辑。集合家族树:接口与抽象类布局集合框架的根接口Java集合框架的根接口是Collection和Map,其中Collection进一步细分为List和Set接口。这些接口定义了集合的基本操作和行为。抽象类的作用为了减少重复代码,集合框架提供了抽象类,如AbstractList和AbstractSet,为具体实现类提供通用的实现逻辑。数组vs集合:四维对比速查表大小灵活性数组大小固定,一旦创建无法改变;集合大小动态可变,可根据需要自动调整容量。数据类型数组在声明时必须指定存储的数据类型,只能存储相同类型的元素;集合可以存储不同类型的对象,但建议使用泛型确保类型安全。操作功能数组操作功能有限,仅支持基本的索引访问和修改;集合提供了丰富的操作方法,如添加、删除、查找、排序等。内存结构数组在内存中是连续存储的;集合框架提供了多种不同的数据结构实现,如数组、链表、哈希表、树等。List接口与双线实现02List承诺:有序可重复索引访问List接口的核心语义List接口的核心语义是保持元素的插入顺序,允许元素重复,并支持通过索引进行随机访问。List接口的关键APIList接口提供了丰富的API,如add、remove、get、set、indexOf等,用于操作和访问列表中的元素。ArrayList:动态数组的扩容代价ArrayList的底层实现ArrayList基于动态数组实现,当数组容量不足时,会自动创建一个更大的新数组,并将原数组的元素复制到新数组中。ArrayList的性能特点ArrayList的随机访问性能优异,时间复杂度为O(1);但在中间插入或删除元素时,需要移动大量元素,性能较差,时间复杂度为O(n)。ArrayList的扩容机制ArrayList的扩容机制是动态的,当容量不足时,会创建一个更大容量的新数组,并将原数组的元素复制到新数组中。LinkedList:双链节点的指针游戏01LinkedList的底层实现LinkedList基于双向链表实现,每个元素存储在一个节点中,节点包含元素值和指向前一个节点及后一个节点的引用。02LinkedList的性能特点LinkedList在中间插入或删除元素时性能优异,时间复杂度为O(1);但在随机访问元素时性能较差,需要从头或尾节点开始遍历,时间复杂度为O(n)。03LinkedList的适用场景LinkedList适用于需要频繁进行插入和删除操作的场景,如实现队列、栈等数据结构。List选型决策矩阵List选型的关键因素选择合适的List实现类时,需要考虑操作频率、数据规模、内存占用等因素。ArrayList与LinkedList的对比如果需要频繁访问元素,选择ArrayList;如果需要频繁进行插入和删除操作,选择LinkedList。Set接口与去重艺术03Set哲学:唯一性与无序性Set接口的核心特性Set接口的核心特性是元素的唯一性,不允许重复元素,同时不保证元素的顺序。Set接口的适用场景Set接口适用于需要去重的场景,如存储用户ID、商品SKU等。HashSet:哈希表的O(1)信仰01HashSet的底层实现HashSet基于哈希表实现,通过元素的hashCode和equals方法来判断元素是否重复。02HashSet的性能特点HashSet的添加、删除和查找操作的平均时间复杂度接近O(1),性能优异。03HashSet的注意事项使用HashSet时,需要确保元素的hashCode和equals方法正确实现,否则可能导致去重失败。TreeSet:红黑树的有序坚守TreeSet的底层实现TreeSet基于红黑树实现,元素会按照自然排序或指定的Comparator进行排序。TreeSet的性能特点TreeSet的添加、删除和查找操作的平均时间复杂度为O(logn),性能相对较低但仍然高效。TreeSet的适用场景TreeSet适用于需要存储唯一元素且保持排序状态的场景,如存储学生分数、单词列表等。Set实战:用户ID去重与排序对比HashSet与TreeSet的性能对比在用户ID去重场景中,HashSet的性能明显优于TreeSet,但TreeSet能够保持元素的排序。Set选型的建议如果不需要排序,优先选择HashSet;如果需要排序,可以选择TreeSet。Map接口与键值宇宙04Map世界观:键唯一值重复Map接口的核心特性Map接口的核心特性是键的唯一性,每个键映射到一个值,值可以重复。Map接口的适用场景Map接口适用于需要通过键快速查找值的场景,如存储用户配置信息、商品库存等。HashMap:数组+链表+红黑树的三级跳HashMap的底层实现HashMap基于数组、链表和红黑树实现,通过哈希表提供高效的键值对存储和检索。HashMap的性能特点HashMap的添加、获取和删除操作的平均时间复杂度接近O(1),性能优异。HashMap的注意事项使用HashMap时,需要确保键的hashCode和equals方法正确实现,否则可能导致键值对无法正确存储或查找。TreeMap:有序键的Range利器

01TreeMap的底层实现TreeMap基于红黑树实现,键会按照自然排序或指定的Comparator进行排序。02TreeMap的性能特点TreeMap的添加、获取和删除操作的平均时间复杂度为O(logn),性能相对较低但仍然高效。03TreeMap的适用场景TreeMap适用于需要存储键值对且保持键的排序状态的场景,如存储商品价格区间、学生分数排名等。Map三种遍历模式性能对比Map的遍历方式Map可以通过keySet、values和entrySet三种方式进行遍历,各有优缺点。遍历方式的性能对比在大规模数据下,entrySet方式的性能最优,因为它避免了二次哈希计算。遍历、排序与泛型安全05Iterator:统一遍历与并发安全Iterator的基本使用Iterator提供了一种统一的方式来遍历集合中的元素,而无需关心集合的底层实现。Iterator的并发安全Iterator在遍历过程中如果检测到集合结构被修改,会抛出ConcurrentModificationException,保证并发安全。增强for循环:语法糖与局限增强for循环的语法糖增强for循环简化了集合的遍历代码,使代码更加简洁易读。增强for循环的局限性增强for循环无法在遍历过程中直接修改集合的结构,否则会抛出ConcurrentModificationException。Comparable:对象的自然顺序Comparable接口的作用Comparable接口定义了对象的自然排序规则,通过compareTo方法比较对象的大小。Comparable接口的实现实现Comparable接口时,需要确保compareTo方法满足自反性、对称性和传递性。Comparator:外置排序策略Comparator接口的作用Comparator接口提供了外置的排序策略,可以定义多种排序规则。Comparator接口的使用Comparator接口可以通过匿名类、Lambda表达式或方法引用实现,适用于需要多种排序规则的场景。泛型:编译期类型防火墙泛型的作用泛型在编译期进行类型检查,确保类型安全,避免运行时的ClassCastException。泛型的使用泛型通过在集合声明时指定类型参数,编译器在编译阶段对类型进行检查,提高代码的可读性和安全性。泛型通配符:PECS生产与消费PECS原则PECS原则指出,如果集合主要用于生产数据,使用extends通配符;如果主要用于消费数据,使用super通配符。泛型通配符的使用泛型通配符可以增加代码的灵活性和复用性,适用于不确定具体类型但需要进行通用操作的场景。泛型擦除与桥方法陷阱泛型擦除泛型在运行时会被擦除,仅保留上界信息,因此无法直接获取泛型参数的具体类型。桥方法陷阱在泛型类中,编译器会自动生成桥方法以保持多态,但在反射调用时需要注意桥方法的存在,否则可能抛出异常。实战案例与综合演练08购物车:Map+List混合架构购物车的实现购物车通过Map存储商品ID和数量,通过List展示订单快照,实现数据的一致性和高效访问。购物车的注意事项在购物车实现中,需要注意并发修改、数据一致性等问题。购物车的性能特点购物车的实现结合了Map和List的优点,既保证了高效的查找和更新操作,又支持快速的遍历和展示。最佳实践与常见误区09集合选型七问法集合选型的关键问题集合选型时需要考虑线程安全、元素重复、排序需求、操作频率、内存占用等因素。集合选型的决策清单通过一系列问题快速确定最适合的集合类型,减少拍脑袋决策带来的性能和维护问题。集合选型的实践建议根据具体需求选择合适的集合类型,如需要线程安全时选择ConcurrentHashMap,需要排序时选择TreeSet。感谢您的观看THANK

YOU

FOR

WATCHING第9章

输入输出目录CONTENTS01File类02字节流03字符流04案例:环保公益捐赠管理系统File类019.1File类File类是Java中用于处理文件和目录的类,它不提供读取或写入文件内容的功能,而是用来处理文件和目录的创建、删除、重命名、检查文件属性等操作。你可以将它想象成文件系统的“管家”,负责管理文件和文件夹的元数据。状态判断方法通过exists、isFile、isDirectory、canRead、canWrite等方法,可以判断文件或目录是否存在、是否为文件或目录、是否可读写等状态。9.1.1创建File对象1.使用单个字符串路径创建File对象(1)形式:File(Stringpathname)(2)特点:路径可以是绝对路径或相对路径;(3)用途:适合快速创建文件对象,适用于路径已知或无需动态拼接的场景。Filefile1=newFile("test.txt");//相对路径9.1.1创建File对象2.使用父路径字符串与子文件名创建File对象(1)形式:File(Stringparent,Stringchild)(2)特点:将父路径和子路径分开书写,增强可读性与灵活性;(3)用途:适用于动态拼接路径或将路径拆分管理的场景。Filefile2=newFile("/home/user","test.txt");//父路径+子文件名9.1.1创建File对象3.使用File对象作为父路径与子路径创建File对象(1)形式:File(Fileparent,Stringchild)(2)特点:父路径以File对象形式存在,适合在目录遍历、递归等场景中使用;(3)用途:便于以对象的方式处理路径层次结构,支持链式构造。Fileparent=newFile("/home/user");Filefile3=newFile(parent,"test.txt");//父路径为File对象9.1.2File类的常用方法方法名返回类型说明exists()boolean判断文件或目录是否存在isFile()boolean判断是否为普通文件isDirectory()boolean判断是否为目录createNewFile()boolean创建新文件mkdir()boolean创建单层目录mkdirs()boolean创建多层目录delete()boolean删除文件或空目录renameTo(Filedest)boolean重命名或移动文件/目录getName()String获取文件名getPath()String获取文件路径(构造时提供的)getAbsolutePath()String获取绝对路径length()long获取文件大小(字节)lastModified()long获取最后修改时间(时间戳)list()String[]获取目录中子文件/目录名称列表listFiles()File[]获取目录中子文件/目录File对象canRead()boolean判断是否有读取权限canWrite()boolean判断是否有写入权限canExecute()boolean判断是否可执行9.1.2File类的常用方法1.判断文件或目录是否存在(1)方法:booleanexists()(2)功能:判断指定路径是否存在//创建一个表示名为demo.txt的文件对象Filefile=newFile("demo.txt");if(file.exists()){System.out.println("文件存在");}else{System.out.println("文件不存在");}9.1.2File类的常用方法2.判断是文件还是目录(1)方法:booleanisFile()、booleanisDirectory()(2)功能:判断File对象表示的是文件还是目录//创建一个表示名为demo.txt的文件对象Filefile=newFile("demo.txt");if(file.exists()){if(file.isFile()){System.out.println("这是一个文件");}elseif(file.isDirectory()){System.out.println("这是一个目录");}}else{System.out.println("文件或目录不存在");}9.1.2File类的常用方法3.创建文件或目录(1)方法:booleancreateNewFile()、booleanmkdir()、booleanmkdirs()(2)功能:创建新文件、单层目录或多层嵌套目录//创建一个新文件Filef=newFile("newFile.txt");f.createNewFile();Filedir=newFile("myFolder");dir.mkdir();Filenested=newFile("parent/child/grandchild");nested.mkdirs();9.1.2File类的常用方法4.删除文件或空目录(1)方法:booleandelete()(2)功能:删除当前文件或空目录(不支持非空目录)//删除指定的文件FilefileToDelete=newFile("deleteMe.txt");if(fileToDelete.delete()){System.out.println("删除成功");}else{System.out.println("删除失败");}9.1.2File类的常用方法5.重命名或移动文件(1)方法:booleanrenameTo(Filedest)(2)功能:重命名文件,或将文件移动到新路径//重命名文件或将其移动到新位置FileoldFile=newFile("oldName.txt");FilenewFile=newFile("newName.txt");oldFile.renameTo(newFile);9.1.2File类的常用方法6.获取文件属性(1)方法:StringgetName():获取文件名StringgetPath():获取构造时的路径StringgetAbsolutePath():获取绝对路径longlength():获取文件大小(单位:字节)longlastModified():获取最后修改时间(时间戳)//获取文件的各种属性信息System.out.println("文件名:"+file.getName());System.out.println("路径:"+file.getPath());System.out.println("绝对路径:"+file.getAbsolutePath());System.out.println("文件大小:"+file.length()+"字节");9.1.2File类的常用方法7.获取文件或目录的列表(1)方法:String[]list()、File[]listFiles()(2)功能:列出目录中所有子文件或子目录//列出当前目录下的所有文件和子目录Filedir=newFile("./");File[]files=dir.listFiles();for(Filef:files){System.out.println(f.getName());}9.1.2File类的常用方法8.检查文件权限canRead():是否可读canWrite():是否可写canExecute():是否可执行//检查文件是否具有读取权限if(file.canRead()){System.out.println("文件可读");}9.1.3遍历目录下的文件1.使用list()方法(1)返回类型:String[](2)功能:返回当前目录下所有子文件和子目录的名称字符串数组。//创建一个File对象,表示当前路径下的docs目录//相对路径,表示当前项目目录下的子目录docsFilefolder=newFile("./docs");//获取目录下所有文件和子目录的名称//使用list()方法获取目录中的所有文件和子目录名称String[]names=folder.list();//遍历名称数组并输出//遍历名称数组并输出每一项(即文件或子目录名)for(Stringname:names){System.out.println("名称:"+name);}9.1.3遍历目录下的文件2.使用listFiles()方法(1)返回类型:File[](2)功能:返回当前目录下所有子文件和子目录的File对象数组。//创建一个File对象,表示C:/java目录//创建一个File对象,表示C:/java目录Filedir=newFile("C:/java");//获取该目录下的所有文件和子目录,以File对象数组返回//使用listFiles()方法获取File对象数组,包含所有子项File[]files=dir.listFiles();//遍历File数组,根据类型分别输出//遍历File数组,根据是文件或目录分类输出for(Filefile:files){

if(file.isDirectory()){System.out.println("目录:"+file.getName());}else{System.out.println("文件:"+file.getName());}}9.1.3遍历目录下的文件3.递归遍历子目录//递归列出指定目录及其所有子目录中的所有文件publicstaticvoidlistAllFiles(Filedir){//检查是否存在并且确实是一个目录if(dir.exists()&&dir.isDirectory()){//获取目录中的所有文件和子目录File[]entries=dir.listFiles();for(Fileentry:entries){//如果是目录,打印并递归进入if(entry.isDirectory()){

System.out.println("目录:"+entry.getAbsolutePath());listAllFiles(entry);//递归调用}else{//如果是文件,直接输出其绝对路径System.out.println("文件:"+entry.getAbsolutePath());}}}}9.1.4删除文件及目录1.删除单个文件//创建File对象,指向要删除的文件Filefile=newFile("test.txt");//判断文件是否存在并尝试删除if(file.exists()){booleansuccess=file.delete();if(success){System.out.println("文件删除成功。");}else{System.out.println("文件删除失败。");}System.out.println("目录:"+entry.getAbsolutePath());}else{System.out.println("文件不存在。");}

使用File.delete()方法可删除指定文件9.1.4删除文件及目录2.删除空目录//创建File对象,指向要删除的空目录Filedir=newFile("emptyDir");if(dir.exists()&&dir.isDirectory()){if(dir.delete()){System.out.println("空目录删除成功。");}else{System.out.println("空目录删除失败。");}}delete()方法也适用于空目录的删除9.1.4删除文件及目录3.递归删除非空目录//递归删除目录及其所有内容publicstaticvoiddeleteDirectory(Filedir){if(dir.exists()){File[]files=dir.listFiles();if(files!=null){for(Filefile:files){if(file.isDirectory()){deleteDirectory(file);//递归删除子目录}else{

System.out.println("目录:"+entry.getAbsolutePath());file.delete();//删除文件}}}dir.delete();//删除空目录}}递归删除目录中所有内容后,再删除目录本身字节流02字节流的概念Java中的字节流以InputStream和OutputStream为抽象基类,用于以字节为单位处理数据,适用于图片、音频、视频、压缩文件等非文本内容的读写操作。字节流以8位为基本单位,不涉及字符编码,因此是最基本的I/O流体系。字节流的概念在JDK中,提供了两个抽象类InputStream和OutputStream,它们是字节流的顶级父类,所有的字节输入流都继承自InputStream,所有的字节输出流都继承自OutputStream。1.InputStream概述(1)intread():从输入流读取单个字节(0-255),返回-1表示读到末尾;(2)intread(byte[]b):读取一定数量的字节并存储到字节数组中;(3)voidclose():关闭流,释放资源。2.OutputStream概述(1)voidwrite(intb):将指定字节写入输出流;(2)voidwrite(byte[]b):将字节数组写入输出流;(3)voidclose():关闭输出流并释放资源。9.2.1InputStream与OutputStream1.FileInputStream(1)继承自InputStream,用于从文件中读取字节;(2)适合读取二进制文件,如图片、音频、视频等;(3)常见构造方法:FileInputStreamfis=newFileInputStream("input.dat");2.FileOutputStream(1)继承自OutputStream,用于向文件写入字节;(2)默认覆盖文件内容,也可以追加;(3)常见构造方法:FileOutputStreamfos=newFileOutputStream("output.dat");9.2.2FilelnputStream与FileOutputStream1.缓冲流的作用(1)减少对磁盘的读写次数,提高效率;(2)适合处理大文件、频繁读写的场景;(3)工作原理:数据先进入内存缓冲区,达到阈值后才写入磁盘。9.2.3BufferedInputStream与BufferedOutputStream9.2.3BufferedInputStream与BufferedOutputStreamimportjava.io.*;publicclassBufferedFileCopy{publicstaticvoidmain(String[]args){try{//包装字节流,提升读写效率BufferedInputStreambis=newBufferedInputStream(newFileInputStream("video.mp4"));BufferedOutputStreambos=newBufferedOutputStream(newFileOutputStream("backup.mp4"));}byte[]buffer=newbyte[8192];//设置缓冲区大小intlength;while((length=bis.read(buffer))!=-1){bos.write(buffer,0,length);}//关闭流(包括底层File流)bis.close();bos.close();System.out.println("缓冲复制完成。");}catch(IOExceptione){System.out.println("复制失败:"+e.getMessage());}}字符流03字符流概念

Java中的字符流以Reader和Writer为顶层抽象类,主要用于处理文本数据(如.txt文件)。与字节流不同,字符流自动进行字符编码与解码,适更加适合处理中文或其他多字节字符的数据。字符流可以显著提高对文本内容的操作便捷性,特别是在输入输出包含非ASCII字符(如中文、日文、韩文等)时。1.Reader类概述(1)Reader是用于读取字符数据的抽象类;(2)常用方法:intread():读取单个字符;intread(char[]cbuf):读取多个字符到数组;voidclose():关闭流。2.Writer类概述(1)Writer是用于写出字符数据的抽象类;(2)常用方法:voidwrite(intc):写出单个字符;voidwrite(char[]cbuf):写出字符数组;voidwrite(Stringstr):写出字符串;voidclose():关闭流。9.3.1Reader与Writer9.3.2FileReader与FileWriterimportjava.io.*;publicclassFileCharExample{publicstaticvoidmain(String[]args){try{//写入文件内容FileWriterfw=newFileWriter("example.txt");fw.write("欢迎学习Java字符流!\n这是第二行文字。");fw.close();//读取文件内容FileReaderfr=newFileReader("example.txt");intch;while((ch=fr.read())!=-1){System.out.print((char)ch);}fr.close();}catch(IOExceptione){e.printStackTrace();}}}9.3.3BufferedReader与BufferedWriterimportjava.io.*;publicclassBufferedCharExample{publicstaticvoidmain(String[]args){try{//写入多行文本BufferedWriterbw=newBufferedWriter(newFileWriter("note.txt"));bw.write("第一行文本");bw.newLine();//写入换行符bw.write("第二行文本");bw.close();//逐行读取内容BufferedReaderbr=newBufferedReader(newFileReader("note.txt"));Stringline;while((line=br.readLine())!=null){System.out.println("读取:"+line);}br.close();}catch(IOExceptione){e.printStackTrace();}}}案例:环保公益捐赠管理系统04案例需求设计并实现一个环保公益捐赠管理系统。该系统主要功能包括:(1)用户可以通过控制台输入姓名和捐赠金额;(2)每次捐赠信息将以追加方式写入记录文件donations.txt;(3)用户可查看所有历史捐赠记录;(4)系统可计算并显示所有用户的捐赠总额。实现思路

01数据存储设计①使用文本文件"donations.txt"存储捐赠记录;②每条记录采用"姓名,金额"的格式存储;③使用逗号作为字段分隔符,确保数据格式统一;④采用追加写入模式,保留历史捐赠记录。02程序架构设计①使用BufferedWriter实现高效的文件写入;②使用BufferedReader实现逐行文件读取;③采用try-with-resources语句确保资源自动释放;④通过字符串分割和类型转换处理数据解析。03功能模块划分①捐赠记录模块:处理数据写入功能;②记录查询模块:实现数据读取与显示;③统计计算模块:完成金额汇总计算;用户界面模块:提供菜单驱动的交互界面。代码实现importjava.io.*;importjava.util.Scanner;publicclassDonationSystem{//方法:将捐赠者姓名和金额写入文件publicstaticvoiddonate(Stringname,doubleamount){try(BufferedWriterbw=newBufferedWriter(newFileWriter("donations.txt",true))){//写入一条记录,格式为“姓名,金额”bw.write(name+","+amount);bw.newLine();//换行分隔每条记录System.out.println("捐赠记录已保存。");}catch(IOExceptione){System.out.println("保存失败:"+e.getMessage());}}//方法:读取并打印所有捐赠记录publicstaticvoidshowAllDonations(){System.out.println("所有捐赠记录:");try(BufferedReaderbr=newBufferedReader(newFileReader("donations.txt"))){Stringline;//逐行读取并输出while((line=br.readLine())!=null){System.out.println(line);}}catch(IOExceptione){System.out.println("读取失败:"+e.getMessage());}}代码实现//方法:统计捐赠总金额publicstaticvoidcalculateTotal(){doubletotal=0.0;//初始化总额try(BufferedReaderbr=newBufferedReader(newFileReader("donations.txt"))){Stringline;while((line=br.readLine())!=null){//使用逗号分隔“姓名,金额”String[]parts=line.split(",");if(parts.length==2){total+=Double.parseDouble(parts[1]);//累加金额部分}}System.out.println("总捐赠金额为:"+total+"元");}catch(IOExceptione){System.out.println("读取失败:"+e.getMessage());}}代码实现//主函数:控制台交互入口publicstaticvoidmain(String[]args){Scannerscanner=newScanner(System.in);while(true){//显示菜单选项System.out.println("---环保公益捐赠系统---");System.out.println("1.捐赠\n2.查看捐赠记录\n3.统计总额\n4.退出");System.out.print("请选择:");intchoice=scanner.nextInt();scanner.nextLine();//读取回车符防止输入错误if(choice==1){System.out.print("请输入您的姓名:");Stringname=scanner.nextLine();System.out.print("请输入捐赠金额:");doubleamount=scanner.nextDouble();donate(name,amount);//调用捐赠方法}elseif(choice==2){showAllDonations();//查看历史记录}elseif(choice==3){calculateTotal();//统计总额}else{System.out.println("感谢参与环保公益活动!");break;//退出系统}}scanner.close();//关闭资源}}运行结果感谢您的观看THANK

YOU

FOR

WATCHING授课人:佟金丽时间:2025/11/01第10章

多线程目录CONTENTS01线程概述02线程的创建03线程的生命周期及状态转换04线程的调度05多线程同步0606综合实训案例线程概述0110.1.1进程与线程01进程的定义进程是程序的一次执行过程,是系统资源分配的基本单位,拥有独立的内存空间,多个进程间相互独立。02线程的定义线程是进程中的一个执行流程,是CPU调度的基本单位,共享进程的内存空间,多个线程间可以高效通信。10.1.1进程与线程进程与线程对比分析对比项目进程线程资源分配独立分配资源共享进程资源通信方式进程间通信(IPC)共享变量、方法调用切换开销大(上下文切换代价高)小(切换效率更高)稳定性互不影响一个线程出错可能影响其他线程并发能力较弱强,适合高并发处理10.1.2多线程的优势与应用场景多线程的优势多线程可以提高CPU利用率,改善程序响应性,充分利用多核处理器,简化复杂任务模型。典型应用场景多线程广泛应用于图形用户界面程序、网络服务器、文件下载、游戏开发和数据处理等领域。线程的创建0210.2.1继承Thread类创建线程实现步骤代码示例特点限制//自定义线程类,继承ThreadpublicclassMyThreadextendsThread{//重写run()方法,定义线程的任务publicvoidrun(){for(inti=0;i<5;i++){//输出当前线程的名称和循环变量System.out.println(Thread.currentThread().getName()+"执行中:"+i);}}publicstaticvoidmain(String[]args){//创建两个线程对象MyThreadt1=newMyThread();

MyThreadt2=newMyThread();

//启动线程,注意不要使用run()t1.start();t2.start();}}10.2.2实现Runnable接口创建线程实现步骤代码示例特点限制//自定义任务类,实现Runnable接口publicclassMyRunnableimplementsRunnable{publicvoidrun(){for(inti=0;i<5;i++){//输出当前线程的名称和循环变量System.out.println(Thread.currentThread().getName()+"执行中:"+i);}}publicstaticvoidmain(String[]args){//创建Runnable实例Runnabler=newMyRunnable();//将Runnable对象封装到Thread对象中

Threadt1=newThread(r);Threadt2=newThread(r);//启动线程t1.start();t2.start();}}线程的生命周期及状态转换0310.3.1线程状态定义状态英文中文描述说明NEW新建状态线程被创建,但未调用

start()方法RUNNABLE就绪状态线程已启动,等待

CPU分配时间片RUNNING(无枚举)运行状态虽未单独列出,但线程实际运行时处于该状态BLOCKED阻塞状态等待获取锁资源(如进入同步代码块被阻塞)WAITING等待状态无限期等待其他线程通知(如调用

wait())TIMED_WAITING计时等待状态等待指定时间后自动唤醒(如调用

sleep()、join(1000))TERMINATED终止状态线程执行完毕或被异常终止10.3.2线程启动与状态转换(1)新建状态(NEW):通过newThread()创建线程对象后,线程处于新建状态,此时线程只是一个普通的Java对象,尚未与操作系统的线程资源关联。(2)可运行状态(RUNNABLE):调用start()方法后,线程进入可运行状态,此时JVM为线程分配了必要的系统资源,线程等待CPU时间片调度。(3)计时等待状态(TIMED_WAITING):主线程通过Thread.sleep(100)短暂休眠,确保子线程执行到sleep(1000)语句,子线程执行sleep(1000)后进入计时等待状态,在指定时间内不会消耗CPU资源。(4)终止状态(TERMINATED):t.join()方法使主线程等待子线程执行完毕,子线程完成run()方法中的所有代码后进入终止状态。10.3.2线程启动与状态转换实现步骤代码示例特点限制publicclassThreadStateDemo{publicstaticvoidmain(String[]args)throwsInterruptedException{//创建线程,任务是休眠1秒Threadt=newThread(()->{try{Thread.sleep(1000);//进入TIMED_WAITING}catch(InterruptedExceptione){e.printStackTrace();}});System.out.println("状态1:"+t.getState());//NEWt.start();System.out.println("状态2:"+t.getState());//RUNNABLEThread.sleep(100);//主线程暂停,以便子线程进入TIMED_WAITINGSystem.out.println("状态3:"+t.getState());//TIMED_WAITINGt.join();//等待线程执行结束System.out.println("状态4:"+t.getState());//TERMINATED}}线程的调度0410.4.1线程的优先级优先级范围每个线程都拥有一个优先级,Java中的优先级为一个整数值,范围从1(Thread.MIN_PRIORITY)到10(Thread.MAX_PRIORITY),默认值为5(Thread.NORM_PRIORITY)。平台差异线程优先级只是对调度器的提示,具体调度策略由操作系统决定,不同平台可能有所不同。10.4.2线程休眠线程休眠是通过Thread.sleep(longmillis)方法实现的,让当前线程暂停执行指定的毫秒数,让出CPU给其他线程。publicclassSleepDemo{publicstaticvoidmain(String[]args)throwsInterruptedException{System.out.print("3...");Thread.sleep(1000);System.out.print("2...");Thread.sleep(1000);System.out.print("1...");}}10.4.3线程让步Thread.yield()方法会使当前线程主动让出CPU,让系统重新调度线程。它不会阻塞线程,只是把当前线程放回就绪队列中,有可能马上又被调度回来。publicclassYieldDemo{publicstaticvoidmain(String[]args){Runnabletask=()->{for(inti=0;i<3;i++){System.out.println(Thread.currentThread().getName()+"执行中");Thread.yield();//提示调度器切换线程}};newThread(task,"线程A").start();newThread(task,"线程B").start();}}10.4.4线程插队join()方法可以使一个线程等待另一个线程执行完成。主线程调用子线程的join(),表示“插队”,直到子线程执行完毕,主线程才继续执行。publicclassJoinDemo{publicstaticvoidmain(String[]args)throwsInterruptedException{Threadt=newThread(()->{System.out.println("子线程开始");try{Thread.sleep(2000);}catch(InterruptedExceptione){e.printStackTrace();}System.out.println("子线程结束");});t.start();t.join();//主线程等待t结束System.out.println("主线程继续");}}多线程同步05多线程同步概述线程安全问题在多线程程序中,多线程并发执行带来更高的程序效率和更强的响应能力,但也伴随着资源访问冲突的问题。多个线程对共享数据或资源的非同步访问,可能导致数据错误、状态不一致甚至程序崩溃。这些问题被统称为线程安全问题。原子性与可见性线程安全问题的根源在于操作非原子性和内存可见性问题,synchronized关键字可以解决这些问题。10.5.1线程安全问题当多个线程并发访问共享变量,并且至少有一个线程修改了该变量,而该变量的访问又没有采取同步机制控制时,就可能出现线程安全问题,导致运行结果不可预测。publicclassUnsafeBank{privatestaticintbalance=100;publicstaticvoidmain(String[]args){Runnabletask=()->{for(inti=0;i<5;i++){if(balance>0){System.out.println(Thread.currentThread().

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论