1、基本数据类型和引用数据类型的区别( 用内存的角度 ):基本数据类型 :数据值是存储在自己的空间中特点:赋的值也是真实的值引用数据类型 :数据值存储在其他空间中,自己空间存储的是地址值特点:赋的值是地址值 ★【 注意 :在静态代码块中,随着类的加载进行,而且只进行一次(语法:static{//方法体})】
2、 二维数组的学习: 语法:数据类型[][]数组名=new 数据类型[m][n]{{元素 1,元素2},{元素1,元素2}};注意:m表示可以存放多少个一维数组n表示每一个一维数组可以存放多少元素范例:int[][]arr=new int[2][3];表示可以存放2个一维数组,每一个一维数组可以存放3个int类型的元素赋值:arr[1][2]=10;将10赋值给第二个数组且索引为2的数据
3、 构造方法的特点:1、方法名和类名相同,大小也要一致。2、不能存在返回值,void不存在。3、可以带参数,没有具体的返回值,不能带有return。注意事项:·如果没有定义构造方法,系统会默认一个无参数的方法。·如果定义了构造方法,系统将不再提供默认的构造方法。
4、 什么是方法的重载?一个类中、方法名相同、但是参数不同。推荐使用:无论是否使用,都手动书写无参和有参构造。(快捷键: Alt+insert)
5、 对象的内存图注意:·堆内存里存储的是对象,每当我们通过new关键字建立对象,在堆里面都会开辟一个新的空间。(几个new几个独立的空间)·堆内存存储着成员变量和成员方法,可以将独立开辟的空间看做地址值。·在栈内存里面将堆内存里的地址值赋值给等号左边的变量。
6、 Object是所有java类的祖先,位于java.lang包中常见方法:1:toString();返回字符串对象2:boolean equals();返回是否是同一对象3:Object clone();返回当前对象的一个副本4:int hashCode();返回该对象的哈希代码5:getClass();返回运行时的类
7、继承[访问修饰符]class <子类>extends<父类·>方法重载和方法重写的区别是什么? 方法重载对返回值类型和访问修饰符无关
8、super关键字的作用--调用父类的属性和构造方法-访问构造方法super(参数)、super.(属性、方法)注意:1、必须出现在子类中2、可以访问父类的成员属性和构造方法3、无法通过super关键字访问private成员4、如果存在多级继承关系,构造方法的调用规则会多次向更高一级的父类传递,一直到执行顶级父类Object。5、子类的构造方法默认调用父类无参构造方法,这种情况,使用super()也无效。6、如果子类super调用父类的带参构造方法,则不在执行无参构造方法。7、 在类的构造方法中,super语句或this语句只能是第一条语句。
9、 static静态关键字修饰作用--调用方法:类名.属性或方法注意:1、在静态方法中不能直接访问实例方法,可以创建新的实例对象,使用对象名.出来。2、static修饰局部变量只改变生命周期,不改变作用域。3、静态方法中不能出现this关键字。4、static会改变成员变量和函数的链接属性,从而使作用域变小。(外部链接 属性被修改成内部链接属性)
10、 多态(具有表现多种形态的能力)<特定类型的变量可以引用不同类型的对象>一、实现多态的三个条件1、必须存在继承(没有继承就没有多态)2、子类重写父类的方法(多态调用的是子类重写或继承的方法)3、父类引用变量指向子类对象(向上转型)二、多态的优势----1.可替换性2.可扩充性3.灵活性4.简化性三、子类到父类的转型(向上转型)--父类到子类的转型(向下转型)向上转型(语法):<父类型><引用变量>=new<子类>();向下转型(语法):<子类型><引用变量>=(<子类型>)<父类引用变量>;(可以看成父类被强转为子类型)。注意:如果需要调用子类特有的方法,需用到向下转型,转换同时可能出现转换类型异常, 因为在向下转型时没有转换为真实的子类类型 ,就需要用到instance of可以译为“属于”或“是一个……的实例”。(向下转型必须转换为父类指向的真实子类类型)
11、instance of关键字的作用:检查对象的真实类型,再进行相应的强制类型转换,可以避免类型转换异常语法:<父类引用对象名>instance of<子类型>(一般用于if判断)。强转语法:((<子类型>)父类引用对象名).<属性或方法>。
12、 抽象类和接口(abstract关键字修饰)【抽象类不能被实例化,只能通过继承它的子类来创建对象来实现】抽象类可以默认为子类提供默认实现,实现了方法定义和方法实现分离,使代码实现松耦合,更易于维护。语法:<访问修饰符>abstract class<类名>----[访问修饰符] abstract<返回类型><方法名>([参数列表])注意:1、 抽象方法与普通方法最大的区别就是 :抽象方法没有方法体。2、抽象类中可以包括抽象方法和普通方法。3、 abstract不能和private、static、final共用。static:抽象方法只是声明,方法没有实现,而static通过类名去点直接访问。private:抽象方法需要在子类中重写,private不能被子类继承,只能用在本类中。final:final修饰的方法不能被子类重写
13、 final关键字: 不能再被继承,方法不能再重写,常量中,只能在初始化进行赋值,在修饰引用变量时,变量值不变,变量所指对象的属性值可变。
14、 接口的使用(继承只是单继承,但可以调用多个接口) 接口也可以看成一个抽象类。抽象类利于代码的复用,接口利于代码的扩展。定义接口的语法:[访问修饰符] interface 接口名{}类实现接口的语法:class 类名 implements 接口名{}复杂接口的继承:[访问修饰符] interface 接口名 extends 父接口1、父接口2……{}类继承接口的语法:class 类名 extends 父类名 implements 接口1、接口2……{}注意:1、在接口中属性系统会自动添加 public static final 修饰(在接口中变量是常量)2、方法系统会自动添加 public abstract 修饰(方法是抽象方法) 3、接口的实现类必须实现接口中定义的所有的抽象方法
15、 面向对象的设计原则1、摘取代码变化部分,形成接口。2、多用组合,少用继承(多组少继)。3、不依赖具体实现( 以抽象类或接口作为依赖的类型 )。4、遵循“开闭原则”(不修改原有的接口,定义一个新的接口)。
16、 异常try-catch-finally的使用(快捷键:Ctrl+Alt+T)input.hasNextInt()的作用是避免 输入不匹配的数据类型而引发异常。1 、 Exception 类型的常用方法 void printStackTrace() 输出异常堆栈信息。一般调用ex.printStackTrace() ,输出异常信息是最完整的。String getMessage() 返回异常的详细信息。是 printStackTrace() 方法的一部分。2 、怎么将 finally 语句块不被执行?在异常处理代码中使用 System.exit(1) 方法退出 JVM 。【括号里的 1 代表状态码,以非零状态退出, 0 代表成功退出,非零数字代表异常退出】3 、多重 catch 语句的使用 语法: catch( 异常类型 异常对象 ex)注意: · 系统会自动从上到下的顺序依次检测每个 catch 语句,当匹配到第一个catch ,后面不再执行。(相当于 if-else多重运用)。当异常类型为 Exception 的 catch 语句必须放在最后的位置,它包含所有异常类型。
17
、异常分类
Error
类和
Exception
类 【
Error
类一般指
JVM
的相关问题】
Exception
类:可以分为(
RunTimeException
)运行异常和(
Checked
)检查异
常、编译错误
( RunTimeException )运行异常:1. NullPointerException (空指针异常): 当试图在对象引用上调用方法或访问属性时,但该引用为空( null )时抛出。2. ArrayIndexOutOfBoundsException (数组越界异常): 当尝试访问数组中不存在的索引位置时抛出,通常是索引值小于 0 或者大于等于数组长度。3. ClassCastException (类转换异常): 当试图将对象强制类型转换为不兼容的类型时抛出,例如将一个不能转换为指定类型的对象强制转换为该类型。 4. NumberFormatException (数字格式异常): 当字符串转换为数字的过程中发生格式错误时抛出,通常是因为字符串中包含无法解析为数字的字符。5. IllegalArgumentException (非法参数异常): 当方法接收到的参数不合法或不合适时抛出,如参数值不在允许的范围内、类型不匹配等。6. IllegalStateException (非法状态异常): 当对象的状态无法支持正在执行的操作时抛出,例如尝试在对象处于不正确状态时调用方法。7. ArithmeticException (算术异常): 当出现除以零或者其他算术错误时抛出,例如整数除法时除数为零。8. ConcurrentModificationException (并发修改异常): 在使用迭代器遍历集合时,如果在迭代过程中修改了集合的结构(添加、删除元素等),则会抛出此异常。9. IndexOutOfBoundsException (索引越界异常): 当使用某种方法访问字符串、数组或集合等数据结构时,访问了无效的索引时抛出。10. NullPointerException (空指针异常): 当试图在 对象 引用上调用方法或访问属性时,但该引用为空( null )时抛出。11. UnsupportedOperationException (不支持的操作异常): 当调用不支持的操作时抛出,通常是由于对象的不可变性或者特定实现不支持的操作引起的。
(Checked)检查异常:1.IOException (输入 / 输出异常): 表示在输入输出操作期间发生的异常,例如文件无法找到、读取或写入文件时的错误等。2.SQLException ( SQL 异常): 表示与数据库操作相关的异常,例如连接数据库失败、执行 SQL 查询出错等。3.ClassNotFoundException (类未找到异常): 表示在运行时试图加载类时找不到对应的类的异常。4.NoSuchMethodException (方法未找到异常): 表示试图通过反射调用不存在的方法时抛出的异常。5.ParseException (解析异常): 表示在解析字符串、日期等数据时出现错误的异常。6.InstantiationException (实例化异常): 表示试图通过反射创建一个抽象类或者接口的实例时抛出的异常。7.IllegalAccessException (非法访问异常): 表示试图访问一个不可访问的类、字段或方法时抛出的异常。8.InvocationTargetException (调用目标异常): 表示通过反射调用方法时目标方法抛出异常时的异常,通常是作为其他异常的包装器。9.FileNotFoundException (文件未找到异常): 表示在尝试打开一个不存在的文件时抛出的异常。10.MalformedURLException ( URL 格式异常): 表示 URL 字符串格式错误时抛出的异常。11.ParseException (解析异常): 表示在解析字符串、日期等数据时出现错误的异常。 12.ClassNotFoundException (类未找到异常): 表示在运行时试图加载类时找不到对应的类的异常。
18、 throws 关键字的使用throws用于可能抛出异常方法的声明语法:public void 方法名()throws 异常类型1,异常类型2.......{//方法体}(第二种:throws+继承异常的父类)
19、抛出异常—— throw关键字语法:throw new 异常名-【异常类】(参数列表)注意:异常名不能为String,因为String类不是Throwable类的子类。
20、自定义异常(1):定义异常类,继承Exception类或RuntimeException(2):编写异常类的构造方法,并继承父类的实现。(3):实例化自定义异常对象,并使用throw关键字抛出 (throw new 异常名)常见四种构造方法:1、public Exception(){super()}2、public Exception(String message){super(message)}3、public Exception(String message,Throwable cause){super(message,cause)}4、public Exception(Throwable cause){super(cause)}
21 、日志框架Log4j 2(Java中记录日志之一) (下载log4j-2.13.3.jar和下载log4jcore-2.13.3.jar)【直接导包+右键Add as Library】Log4j 2配置——下载完成之后,打开idea中的file-Project StructureModules,右侧窗格中选择"Dependencies",点击右侧“+”按钮,选择“JARsor directories”命令,添加两个.jar文件或者:在项目中创建一个lib目录,导入.jar文件,右键Add as library就OK了。
22、Log4j记录日志的使用(1):编写配置文件 (log4j2.xml) XML即可扩展标记语言(2):定义日志记录器Logger——创建一个Logger对象,Logger 对象名=LogManager.getLogger(类名.class.getName());注意:getLogger(String类型的参数), 参数是通过类名.class.getName() ;(3):记录日志(Logger类常用记录日志的方法)【日志记录级别共八级,从低到高依次如下all(所有)<trace(追踪)<debug(调试)<info(消息)<warn(警告)<error(错误)<fatal(严重错误)<OFF(关闭)】例如:记录debug/info/warn/error/fatal级别日志:public voiddebug(Object msg) public void debug(Object msg,Throwable t)
常用API--包装类 (将基本数据类型转换为Object类型)【可以通过创建包装类来完成手动装箱-"value of()"】自动拆箱:将Object类型->基本数据类型 //创建包装类对象自动装箱:将基本数据类型->Object类型//调用包装类里的type.typeValue()方法【type指基本数据类型】 ★重点:Java以后键盘录入都使用String类型的nextLine()方法,再结合包装类的方法转换为基本数据类型。①value of()将其他数据类型转换为包装类型②将字符串转换为基本数据类型,通过包装类+点+parse大写基本数据类型【例:int result= Integer.parseInt(String s) 】③包装类Character没有提供parse(),可以通过 str.charAt(index) 方法获取,或者将字符转换为包装类来获取相应的值 Character.valueof().charValue()。【▲注意:②、③只使用于参数为String类型的数据】匿名内部类: (临时性、一次性)★【定义之后不能在其他地方调用, 只在一个具体的代码块或方法内部被实例化和使用 】
23、
Collection类(集合祖宗):
(框架) ▲注意:Collections是一个
工具
类
,包含了
sort()--排序(默认升序)->reverse()
反转元素顺序
->shuffle()--
打乱顺序,在Set集合中可以转换为List列表来运用。
【注意:Collection是个接口,不能实例化对象】
Collection接口常用的方法:
List接口 (继承Collection接口,Set集合的方法上基本上与Collection的API一致,但有扩展方法)【List接口不允许重复、有索引、有序】包括->(ArraysList->底层: 数组 )(LinkedList->底层: 链表(双向) )链表(双向): 数值左右都存储了一个null的地址值,便于增、删数据。ArraysList集合 (泛型类:可以约束集合里存储的数据类型)通过创建集合对象去调用集合的方法来实现▷ 使用局限:底层是数组,增、删、会频繁前后移动位置,导致效率低。LinkedList集合 (双链结构:可以频繁增、删)【 每个元素都被封装为一个节点(Node ),形成链表结构 】
Set接口
(继承Collection接口,Set集合的方法上基本上与Collection的AP一
致)
【不允许重复、无序、无索引】包括
- HashSet(允许插入一个null,无序)、
- TreeSet(不允许插入null元素,有序)、
- LinkedHashSet(有序:保证存和取的顺序一致【Linked双向链】)
HashSet(使用场景:集合需要去重)底层原理:(哈希表:在jdk8之前:数组+链表-----之后:数组+链表+红黑树)①创建一个默认长度16,默认 加载因子 0.75的数组,数组名table【加载因子就是HashSet集合的扩容,例如:16*0.75=12,当集合存储数量达到12时,集合容量翻倍成32】②根据元素的哈希值跟数组的长度计算出应存入的位置③判断当前位置是否为nul,如果是nul直接存入④如果位置不为nul,表示有元素,则调用equals方法比较属性值⑤一样:不存 不一样:存入数组,形成链表JDK8以前:新元素存入数组,老元素挂在新元素下面JDK8以后:新元素直接挂在老元素下面【链表:处理哈希碰撞 红黑树: 提高查找、插入和删除操作的效率 】JDK8以后,当链表长度超过8,而且数组长度大于等于64时,自动转换为红黑树哈希值:(通过哈希值计算索引的公式: int index=(集合长度-1)&哈希值【&在这里是按位运算符,返回一个 二进制 的数值】 )定义: 对象的整数表现形式1.如果没有重写hashCode方法,不同对象计算出的哈希值是不同的2,如果已经重写nashcode方法,不同的对象只要属性值相同,计算出的哈希值就是一样的3。但是在小部分情况下,不同的属性值或者不同的地址值计算出来的哈希值也有可能一样。(哈希碰撞)注意:HashSet利用HashCode()和equals()机制保证去重的如果集合中存储的是自定义对象,必须要重写hashCode和equals方法(快捷健:alt+insert选择equals()andHashcode())
TreeSet(使用场景:集合需要排序)底层原理:(红黑树)
Lambda(可用于函数式接口)表达式语法:
(参数1,参数2...) ->{//方法体}
【
由
->
组成,表示将参数与表达式或代码块进行关联。
】
★Lambda表达式只能
简化函数式接口的匿名内部类
的写法
1.TreeSet:集合的特点是怎么样的?
●可排序、不重复、无索引,底层基于红黑树实现排序,增删改查性能较好
2.TreeSet集合
自定义
排序规则有几种方式【数值型:默认从小到大;字符型:
字典a->z】
●方式一:Javabean类实现Comparable
接口
,重写Comparable里的抽象方法
【快捷健:选中接口+Alt+回车】指定比较规则(例如:参数为-自定义对象)
●方式二:创建集合时,自定义Comparator
比较器
对象,(Comparator属于
函数类接口, 可以使用
Lambda
表达式,它是一种便捷的方式来创建
函数式接
口
的实例
)指定比较规则(使用场景:根据长度去排序)
【
Comparator
排序通常根据返回的整数值来确定对象的顺序
】
①函数类接口实现:
//1.创建集合
//o1:表示当前要添加的元素
/o2:表示己经在红黑树存在的元素
//返回值差值为负左正右
TreeSet<String>ts new TreeSet<>(new Comparator<String>(){
@Override
public int compare(String o1,String o2){
//按照长度排序
int i=o1.length()-o2.length();
//如果一样长则按照首字母排序
i=i==0?o1.compareTo(o2):i;
return i;
}
});
②Lambda表达式实现:
TreeSet<string>ts new Treeset<>((o1,o2)->{
//按照长度排序
int i=o1.length()-o2.length();
//如果一样长则按照首字母排序
i=i==0?o1.compareTo(o2):i;
return i;
});
▲
Lambda使用注意:
1:Lambda会自动推断数据类型->可省略。2:可从函数式接口删除到方法名。
★3.方法返回值的特点【 Comparable 还是 Comparator 接口进行排序,都涉及到通过 返回正负数值 来确定对象的顺序 】●负数:表示当前要添加的元素是小的,存左边●正数:表示当前要添加的元素是大的,存右边●0:表示当前要添加的元素已经存在,舍弃
Collection集合的遍历:
① 迭代器遍历 (Iterator):是否存在下一个遍历元素--boolean hasNext(); 遍历下一元素--Object next();删除上一次next()返回的元素--void remove();1.迭代器在遍历集合的时候是不依赖索引的2.迭代器需要掌握三个方法:
- Iterator<String>it =list.iterator();//创建迭代器对象
- while(it.hasNext()){//使用hasNext()方法判断是否存在下一个元素
- String str it.next();//next()方法遍历下一个元素
- System.out.println(str);}//打印输出
3.迭代器的四个细节:▪如果当前位置没有元素,还要强行获取,会报NoSuchElementException▪迭代器遍历完毕,指针不会复位▪循环中只能用一次next()方法▪重点:迭代器遍历时,不能用集合的方法进行增加或者删除【可以调用迭代器 中自带的增、删方法】
②
增强for遍历
(底层:迭代器)【使用场景:
所有单列集合(List、Set)和数
组
】
语法:for(数据类型 变量名: 数组或集合){//方法体}
③
Lambda表达式
(
forEach()
方法遍历-->后接必须是函数式接口)【机制:通过匿名内部类改成Lambda表达式】
//forEach方法的底层其实就是·个循环遍历,依次得到集合中的每一个元素
/并把每一个元素传递给下面的accept方法
/accept方法的形参s,依次表示集合中的每一个元素
list.forEach(new Consumer<String>(){
@Override
public void accept(String s){
System.out.println(s);
}
});
④
列表迭代器遍历
(ListIterator):ListIterator<String>it =list.listIterator();//创建列表迭代器对象
⑤
普通for循环
(List集合中存在索引)
总结(五种遍历方式的使用场景):
迭代器遍历:在遍历的过程中需要
删除元素
,使用普通迭代器。
列表迭代器:在遍历的过程中需要
添加元素
,请使用列表迭代器。
增强for遍历或者Lambda:表达式:仅仅想遍历,那么使用增强for或Lambda表达式。
普通for:如果遍历的时候想操作索引,可以用普通for。
24、Map集合 (存储若干个键-值对象<key-value>)【双列集合】 ★注意:Linked系列的集合都可以保证元素存、取的顺序。【◆注意:Hashtable 不允许空键或空值, Properties 对象来存储和管理 属性 配置数据】Properties:( 双列集合,拥有 Map 集合的所有方法 )①Properties类提供了load()和store()方法,用于从输入流加载属性并将属性写入输出流(store方法可以向文件中添加注释信息)②Properties类提供了setProperty()和getProperty()方法,用于设置和获取属性值。③可以使用stringPropertyNames()方法获取所有属性的键,并通过键获取相应的值(使用场景:增强for)。双列集合(Map)的特点:①双列集合一次需要存一对数据,分别为键和值②键不能重复,值可以重复③键和值是一一对应的,每一个键只能找到自己对应的值④键+值这个整体我们称之为“键值对”或者“键值对对象”,在Java中叫做“Entry对象”。▲注意:Map集合在添加数据的时候:①键不存在,直接添加在集合里--②键存在,会将原有的键值对(对象)覆盖,并返回被覆盖的值(value)。Map中定义的另一种接口Map.Entry,获取元素形式如“key-value”。Map.Entry接口的常用方法:获取Key值:Object getKey()--获取value值:Object getValue()--返回键值对的哈希值:int hashCode()--修改value值:Object setValue(Object value);Map集合的三种遍历方式: ▲注意: Map 接口用于存储键值对 映射 ,不属于Collection的子类。① 迭代器遍历: 通过keySet()和entrySet()方法返回一个Set集合【因为迭代器依赖于Collection集合】,再创建迭代器对象(Interator)。② 增强for遍历: (底层:迭代器)【使用场景: 所有单列集合(List、Set)和数组, 但是可以通过keySet()和entrySet()转换为Set集合 】语法:for(数据类型 变量名: 数组或集合){//方法体}③ Lambda表达式: ( forEach() 方法遍历-->后接必须是函数式接口)【机制:通过匿名内部类改成Lambda表达式】
HashMap集合类 :(底层:哈希表结构)☆ 注意:如果 键 存储的是自定义对象,需要重写hashCode和equals方法----如果 值 存储自定义对象,不需要重写hashCode和equals方法LinkedHashMap集合类:● 由键决定: 有序、不重复、无索引。●这里的有序指的是保证存储和取出的元素顺序一致●原理:底层数据结构是依然哈希表,只是每个键值对元素又额外的多了一个双链表的机制记录存储的顺序。1.TreeMap集合的特点是怎么样的?●不重复、无索引、可排序●底层基于红黑树实现排序,增删改查性能较好2.TreeMap集合排序的两种方式●实现Comparable接口,指定比较规则●创建集合时传递Comparator比较器对象,指定比较规则 25、 可变参数: (本质:数组;作用:在形参中接收多个数据)【格式:数据类型..参数名称->举例:int..a】【注意事项:①形参列表中可变参数只能有一个②可变参数必须放在形参列表的最后面】
26、不可变集合的特点->定义完成后不可以修改,或者添加、删除(创建方式:List、Set、Map接口中,都存在 of() 方法)▲注意:Map:元素不能重复、键值对数量最多是10个,超过10个用 ofEntries() 方法。
27、枚举的使用( 表示一组固定的、相关的常量 )【常量集合--调用方式:枚举名.常量名】语法:访问修饰符 enum 枚举名{常量1,常量2...}(在单独的一个类中定义)枚举的遍历: 调用枚举中的 values() 方法。▲注意:int compareTo()方法比较机制:在枚举中定义的位置-> 索引之差 。枚举的作用:① 提高代码可读性和可维护性 ② 限制取值范围 ③ 增加类型安全性 ④ 支持迭代和循环
28、
日期类
(易用性差、不是线性安全的)【常见的日期类:LocalData、LocalTime、LocalDataTime-->日期类的实例是不可变的对象,无法直接修改属性值,通常重新实例化】
1、日期类通用方法:①返回当前时间:日期类 now()【也可通过创建Date对象, 创建SimpleDateFormat对象[日期类格式器]并指定格式,调用formatter()】②指定日期/时间:日期类 of()-->获取所有盘符:listRoots();③返回月份:Month getMonth()【★注意:Month属于枚举类型】④返回月份天数:int getDayOfMonth()⑤返回年数:int getYear()⑥在指定的日期上添加年/月/日/周:日期类plusYears/Months/Days/Weeks();⑦在指定的日期上减少年/月/日/周:日期类minusYears/Months/Days/Weeks();⑧将字符串转换为日期类型:日期类.parse();【例如: LocalDatedate=LocalDate. parse (str.next() 】 2、创建格式化器:【注意:MM->月份--mm->分钟--ofPattern:指定日期格式】DateTimeFormatter fm2 DateTimeFormatter.ofPattern("yyyy-MM-dd,HH:mm:ss");3、直接通过format()方法将日期格式化为字符串(两种形式)形式一:日期类对象.format(格式化对象)形式二:格式化对象.format(日期类对象)4、如何将long类型的最后修改时间lastModified()指定格式化?//将文件最后修改时间转换为LocalDateTime对象 Long lastModifiedTime file.lastModified(); //ofEpochMilli()方法通常用于将时间戳(毫秒数)转换为Instant实例 Instant instantInstant.ofEpochMilli(lastModifiedTime); /从Instant和区域ID获取LocalDateTime的实例 LocalDateTime fileLastModifiedTime LocalDateTime.ofInstant(instant,ZoneId.systemDefault()); /格式化文件最后修改时间 String formattedFileLastModifiedTime fileLastModifiedTime.format(formatter); System.oUt.println("文件最后修改时间为:"+formattedFileLastModifiedTime);
29、 Random类 (生成随机数)【注意:rd.nextInt()->左闭右开区间】构造方法:①Random():创建一个随机数生成器 ②Random(long seed):单个long种子创建随机数生成器【注意: 生成可重现的随机数序列 】【 ASCII 编码( 字符编码系统):例如: "A":->65----"a"->97 】
30
、
File
类
(操作文件和目录)【
parent:
父级路径
child:
子级路径
--
注意:路径分隔符"/"
或
"\\"
,其中
"\\"
第一个
"\"
表示转义符。】
File
类常见构造方法:
①File(File parent,String child)
②
★
File(String pathname)
③File(String parent,String child)
★【注意:delete()方法删除文件和空文件夹,不走回收站。(mkdirs()方法可创建多级文件夹、单级也行)
createNewFile()方法创建文件时,必须处理异
常
】
File类获取属性值:
①获取文件名:getName()
②获取文件路径:getPath()
③获取绝对路径:getAbsolutePath()
④检查文件是否存在:exists()
⑤获取文件大小:length()
⑥获取最后修改时间:lastModified()
⑦获取当前该路径下所有内容(返回值类型:数组)- > File[] listFiles();
★注意:
在
File
类中使用
递归思想(自己调用自己)
能够有效地处理文件系统中
的复杂结构,
方便对文件和文件夹进行各种操作(先遍历)
。
① 删除多级文件 :
private static void delete
(File aaa)
File[]files aaa.listFiles();
for (File file files){
if(file.isFile()){
file.delete();
}else{
delete (file);
}
aaa.delete();
}//递归思想
②返回多级文件的总长度:
public static long getLen(File aaa){
long len =0;
File[]files aaa.listFiles();
for (Filefile files){
if(file.isFile()){
len len file.length();
}elsef
lenlen getLen(file);
return len;
【注意:单位换算->
1 KB= 1024
字节(
Bytes
)
1MB= 1024 KB 1 GB= 1024 MB
】
31
、
I/O
流概述
(流,是指一连串流动的字符,是以先进先出的方式发送和接收
数据的通道)【
▲
注意:字节流和字符流都为抽象类,
必须使用子类实例化对
象
】
--
《重点:随用随创建,在编写代码中,必须要处理可能会发生的异常,处理完
流之后,需要关闭流【
按照逆序关闭流
】》
【输入流:读取数据--输出流:写出数据】
1、
字节流
(字节输入流/输出流--InputStream/OutputStream)
byte
[]
bytes=
new byte
[
1024
]
InputStream
抽象类的主要方法:(
将字符串转换为byte[]数组:
str.getBytes()--
将byte[]数组转换为字符串:
new String(byte[]b,int off,int len)--
将int转换为char:(char)int)
- ①读取一个字节数据:int read()
- ②将数据读取到字节数组中:int read(byte[]b)
- ③确定范围返回byte数组中:int read(byte[]b,int off,int len)【▲注意:off->
- 开始位置--len->读取的长度】
- ④关闭输入流:void close()
- ⑤返回输入流读取的字节数:int avilable()
OutputStream
抽象类的主要方法:
⑴
字节类
--
(文件输入流/输出流--FileInputStream/FileOutputStream):
FileInputStream类常见的构造方法:
① FileInputStream(File,file) ② FileInputStream(String name)
【注意: name表示路径名称】
循环read()读取数据:【
重点:
一定要定义第三方变量(data),read():表示 读取数据,而且是读取一个数据就移动一次指针
】
//执行读取操作
int data=0;
while (
(data=input.read())!=-1
){//-1表示输入流已经读到末尾,while中括
号里的循环条件就可以理解为已经读取过了。
System.out.print((char)data);}
FileOutputStream类常见的构造方法:
- ①FileOutputStream(File file)
- ②FileOutputStream(String name)
- ③FileOutputStream(String name,boolean append)
- 【▲注意:append(续写开关)表示是否在文件末尾追加数据--换行需要输出的话:write("\r\n")】
◆如何拷贝文件?定义一个参数为(资源文件夹、拷贝文件夹)->关键代码:
new File(dest,file.getName())
◆如何简单对文件加密:【结合
异或^
,判断两边是否相等】
①结合FileOutputStream/FileOutputStream创建对象关联原始文件和加密文
件
②加密处理:在循环遍历时进行
异或
处理;1:int b;2:while((b
fis.read())!=-1){3:fos.write(b^2);
-- (字节缓冲输入流/输出流--BufferedInputStream/BufferedOutputStream)【 减少系统调用次数, 可以提高读取数据的效率 】BufferedInputStream常见的构造方法:【注意:基于输入流对象,size:指定缓冲流的大小】①BufferedInputstream(Inputstream in)《建议:创建字节数组,采用read(bytes)方法进行读取》②BufferedInputstream(Inputstream in,int size)BufferedOutputStream常见的构造方法:①BufferedOutputStream(Inputstream in)②BufferedOutputStream(Inputstream in,int size)
--( 数据操作输入流/输出流DataInputStream/DataOutputStream )【 以二进制格式处理基本数据类型 】Ⅰ构造方法:DataInputStream(InputStream in); 【注意:可以直接读取或输出UTF-8字符编码的字符串】提供额外的读取方法:readInt/Double/Float/Char/Boolean/ UTF() …Ⅱ构造方法:DataOutputStream(OutputStream out);提供额外的输出方法:writeInt/Double/Float/Char/Long/ UTF() …
-( 序列化流/对象输入流->ObjectInputStream--反序列化流/对象输出流->ObjectOUtputStream )【使用合格证:Serializable接口】《▲注意:使用序列化流之前必须调用 Serializable接口 ,接口中没有定义方法,是个标识接口。如果在序列化的过程中遇到版本兼容性问题时,需要设置 序列号、版本号, 默认的定义方式:private static final long serialVersionUID=1L》①序列化流/对象输入流->ObjectInputStream:-构造方法:ObjectInputStream(InputStream in)读取对象的方法:final void readObject(Object obj)②反序列化流/对象输出流->ObjectOUtputStream:-构造方法:ObjectOutputStream(OutputStream out)输出对象的方法:final void writeObject(Object obj)①使用序列化流将对象写到文件时,需要让Javabean类实现 Serializable 接口。否则,会出现NotSerializableException.异常②序列化流写到文件中的数据是不能修改的,一旦修改就无法再次读回来了 ③序列化对象后,修改了Javabean类,再次反序列化,会不会有问题?会出问题,会抛出InvalidClassException异常,解决方案:给javabean类添加serialVersionUID ( 序列号、版本号 )④如果一个对象中的某个成员变量的值不想被序列化,又该如何实现呢?解决方案:给该成员变量加 transient 关键字修饰,该关键字标记的成员变量不参与序列化过程
--( 解压缩流/压缩流--ZipInputStream/ZipOutInputStream )【通过创建 ZipEntry 对象:表示需要添加到Zip中的文件或目录,ZipEntry对象的参数是Zip 内部 中文件的 相对路径 或者是 根目录 】常见的构造方法:①ZipInputstream(Inputstream in)②ZipInputstream(Inputstream in,Charset charset)常见的两种成员方法:①获取压缩包中的文件和文件夹:zip.getNextEntry() ②将压缩包对象(ZipEntry)放到压缩包中:zip.putNextEntry() ③获取父级路径:getParentFile();常见的五大步骤:①选择解压缩流/压缩流类型 ②创建输入流/输出流 ③通过创建ZipEntry对象来获取解压缩/压缩条目④读取/输出数据⑤释放资源(关流->close())->压缩包文件处理完毕:closeEntry()。▶ 解压缩文件夹思路( 定义一个参数为资源文件 src 和目的文件 dest 的方法 ): ①创建ZipInputStream解压缩流(参数为:FileInputStream)。②创建ZipEntry(压缩文件)对象,通过解压缩流的getNextEntry()方法转换成ZipEntry对象,可结合循环遍历。★ ③考虑两个点,第一压缩文件为文件夹,file.mkdirs()创建文件夹,否则结合文件输出流循环遍历写进write();④关闭压缩文件closeEntry()及其它流。《▲注意:ZipInputStream会 自动 遍历所有条目,不需要使用 递归 思想》
▶ 压缩文件夹思路(难点:定义一个参数为资源文件夹src和 压缩流-> ZipOutInputStream 和name:压缩文件内部路径):①测试类中创建ZipOutputStream 压缩流 ( 参数为: FileOutputStream)。②通过循环遍历资源文件的所有文件,将其转换成压缩文件( ZipEntry )对象【注意:创建 ZipEntry 对象时,参数应为name+File.separator("\\")+资源文件名称】,使用 putNextEntry() 方法将压缩对象添加到压缩流中。③创建字节输入流,结合循环read()和write()方法读取并写进。④关闭压缩文件 closeEntry() 和其他流。【▲注意: 压缩流 放在循环外关闭】⑤结合递归思想遍历其他文件。
Java中编码的方法:↓ ->String类中的方法(说明:charsetName字符编码类型)使用默认方式进行编码->public byte[]getBytes()使用指定方式进行编码->public byte[]getBytes(String charsetName)Java中解码的方法:↓String(byte[]bytes)->使用默认方式进行解码String(byte[]bytes,String charsetName)->使用指定方式进行解码注意: 如何不产生乱码?1,不要用字节流读取文本文件2,编码解码时使用同一个码表,同一个编码方式 ⑵ 字符类 (常见的三种字符:ASCII,GBK,Unicode)1.在计算机中,任意数据都是以 二进制 的形式来存储的2.计算机中最小的存储单元是一个字节3.ASCII字符集中,一个英文占一个字节4.简体中文版Windows,默认使用GBK字符集5.GBK字符集完全兼容ASCII字符集:一个英文占一个字节,二进制第一位是0一个中文占两个字节,二进制高位字节的第一位是1Unicode字符集的UTF-8编码格式:一个英文占一个字节,二进制第一位是0,转成十进制是正数一个中文占三个字节,二进制第一位是1,第一个字节转成十进制是负数
字符
--(字符输入流/输出流--Reader/Writer)
Reader
抽象类的主要方法:
- ①读取一个字节数据:int read()
- ②将数据读取到字节数组中:int read(byte[]b)
- ③确定范围返回byte数组中:int read(byte[]b,int off,int len)【▲注意:off->
- 开始位置--len->读取的长度】
- ④关闭输入流:void close()
【
●
重点:空参read()和有参read()的区别:有参方法里包含了读取、解码、强转,有参相当于
空参read()+类型强转
】
Writer抽象类的主要方法:
字符
--(文件字符输入流/输出流--FileReader/FileWriter)
FileWriter类常见的构造方法:
- ①FileWriter(File file)
- ②FileWriter(File file,boolean append)
- ③FileWriter(String fileName)
- ④FileWriter(String fileName,boolean append)
FileReader类常见的构造方法:
①FileReader(File file)
②FileReader(String fileName)
--●( 字符缓冲输入流/输出流--BufferedReader/BufferedWriter )【 缓冲流通过在内存中设置缓冲区来提高 I/O 操作的效率 】常用构造方法:【类对象形式的参数可以直接new类】->{使用场景:数据量大、性能高、处理复杂数据、网络传输}①BufferedReader(Reader in) ②BufferedReader (Reader in,int size)①BufferedWriter(Writer out) ②BufferedWriter (Writer out,int size)字符缓冲流提供两个特殊方法: ①按整行读取数据: br.readLine() ②换行方法: bw.newLine();
--( 字符转换输入流/输出流--InputStreamReader/OutputStreamWriter )【 字节流与字符流的桥梁 ->> 可结合电脑基本单位是字节( byte )来理解 】常用构造方法:【类对象形式的参数可以直接new类】 ①InputStreamReader(Inputstream in) ②InputStreamReader(Inputstreamin,string charsetName)①OutputstreamWriter(Outputstreamout) ②OutputstreamWriter(Outputstream out,string charsetName)⑴InputStreamReader: 是一个从字节流到字符流的桥梁。⑵OutputStreamWriter: 是一个从字符流到字节流的桥梁。例如:(将字节流文件转换为字符流):BufferedReader br =newBufferedReader(new InputStreamReader(new FileInputStream( String name )));
字节打印流/字符打印流--PrintStream/PrintWriter
(只写不读)【▲注意:字
节打印流会默认自动刷新,因为字节流底层没有缓冲区,开不开自动刷新都一样】
常用的构造方法:
idea查看构造方法的快捷键(
Ctrl+P
)
常用的成员方法:
32、
常用工具包--Commons-io(处理IO流)
使用步骤:
- ①在项目中创建一个文件夹:lib
- ②将jar包复制粘贴到lib文件夹
- ③ 右键点击jar包,选择Add as Library->OK
- ④在类中导包使用
Commons-io常见的两大类的常见方法:【FileUtils类和IOUtils类】
33、 Hutool工具包(提供了和很多类的简便方法)API文档: https://apidoc.gitee.com/dromara/hutool/中文使用文档: https://hutool.cn/docs/#/FileUtil类常见的方法:①file:根据参数创建一个file对象--②copy:拷贝文件或者文件夹③touch:根据参数创建文件(父级路径不存在也可自动创建)④writeLines:把集合中的数据写出到文件中,覆盖模式。⑤appendLines:把集合中的数据写出到文件中,续写模式⑥readLines:指定字符编码,把文件中的数据,读到集合中。⑦readUtf8 Lines:按照UTF-8的形式,把文件中的数据,读到集合中
34、
多线程的运用
(最大程度利用CPU的高效程序,提高程序的效率和性能)
Thread类:【线程对象】->
开启多线程都必须new Thread类,调用start()方法。
线程的状态转换:
即->新建、就绪、运行、阻塞、死亡
线程调度的成员方法:
【中断线程:Thread.currentThread().interrupt()】
【▲注意:①setDaemon守护线程(备胎线程):启动前调用,非守护线程运行完毕,它也会随之运行完毕【负责后台线程】②sleep休眠:给较低优先级线程运行机会③礼让yield:给相同优先级或更高优先级运行机会】
Thread类提供了三个静态常量设置优先级:(1~10)
①MAX_PRIOITY->10 ②NORM_PRIOITY->5 ③MIN_PRIOITY->1
多线程实现的三种方式:
- ①继承Thread类的方式进行实现,书写run()方法。
- ②实现Runnable接口的方式进行实现,重写run()方法,创建接口类对象放入Thread类。
- ③利用Callable接口和Future(异步计算)接口方式实现【获取多线程结果】
- 操作:指定相应的线程结果类型(泛型),重写call()方法,创建类对象(表示
- 多线程要执行的任务),创建FutureTask对象(管理多线程运行结果)并get()返回线程结果。
synchronized关键字在多线程的作用 (创建同步代码块或同步方法)同步代码块:synchronized(obj){//代码块} synchronized(this){} 【this和obj都属于锁的对象】【▲注意:当一个线程进入一个synchronized代码块或方法时,它会尝试获取该代码块或方法所属对象的锁。获得锁的线程就可以共享数据,完成代码块的所有代码才会放锁,使其他线程,同步代码块不能嵌套使用,容易造成死锁。】synchronized锁都是自动开锁、关锁,怎么可以自动获得、释放锁呢?--可以创建一个Lock(锁)对象。【◆注意:Lock接口不能实例化,可以通过实现类ReentrantLock的空参构造来实例化】①获得锁:void lock();②释放锁:void unlock()->为了确保正常释放锁,常把这串代码放在finally{}里。