Java高级阶段总结
在结束了面向对象阶段的学习后,我们迎来了Java高级内容的学习,这部分的学习包含了大量记忆的内容,需要大量的练习才能熟练的掌握。
字符串
String类
一个引用类型的类,Java程序中一切使用“引起来”的内容,都是这个类的实例,称为字符创对象。
创建方法
1.使用""赋值创建,如下
String str = "hello你好"
2.使用构造方法创建,如下
常用构造方法 | 说明 |
String() | 创建一个空白字符串对象,实际创建一个空字符数组 |
String(String str) | 创建一个指定的字符串对象,实际是创建一个形参字符串的副本 |
String(char[] list) | 创建一个指定字符数组的字符串对象。 |
String(byte[] list) | 按默认编码格式创建一个指定字节数组的字符串对象。 |
String(byte[] list,String charsetName) | 按指定的编码格式创建一个指定字节数组的字符串对象。 |
字符串的常用方法,如下
方法名 | 返回值 | 作用 |
length() | int | 获取字符串的长度 |
trim() | String | 去除字符串首尾的所有空格 |
toLowerCase() | String | 转换字符串为小写 |
toUpperCase() | String | 转换字符串为大写 |
isEmpty() | boolean | 判断是否为一个空字符串 |
getBytes() | byte[] | 按默认编码格式将字符串转换为字节数组 |
toCharArray() | char[] | 将字符串转换为字符数组 |
equalsIgnoreCase(String str) | boolean | 忽略大小写比较指定字符串是否相同 |
equals(String str) | boolean | 判断字符串是否相同 |
charAt(int index) | char | 获取index位置上的字符串 |
indexOf(String str) | int | 获取str第一次出现的位置,如果没有返回-1 |
lastIndexOf(String str) | int | 获取str最后一次出现的位置,如果没有返回-1 |
contains(字符序列) | boolean | 判断指定的字符序列(字符串)是否存在于原字符串中 |
concat(String str) | String | 将str拼接到原字符串末尾 |
startsWith(String str) | boolean | 判断是否以指定字符串开头 |
endsWith(String str) | boolean | 判断是否以指定字符串结尾 |
substring(int index) | String | 截取原字符串在[index,数组长度)区间内的字符。(从指定位置截取至末尾,包含指定位置) |
substring(int from,int to) | String | 截取原字符串在[from,to)区间内的字符。(从from截取至to,包含from不包含to) |
split(String reg) | String[] | 按指定字符串或正则表达式切分原字符串。如果指定内容不在末尾,n个指定字符能得到n+1个子串;如果指定内容在末尾,n个指定字符能得到n个子串(不包含末尾的无效字符)。 |
replace(char oldChar,char newChar) | String | 使用newChar替换oldChar |
可变字符串
String字符串对象是一个常量,在定义后其值不可改变。
如果使用String类的对象,对其频繁更新时,就会不停地创建新的对象,重新引用。
所以如果要执行1000次重新赋值的过程,就要创建1000个字符串对象,花费很多时间和内存空间,所以效率很低。这时就需要使用可变字符串类。
StringBuilder类
用于表示可变字符串的一个类,是非线程安全的,建议在单线程环境下使用,效率略高于StringBuffer。
StringBuffer类
用于表示可变字符串的一个类,是线程安全的,建议在多线程环境下使用,效率略低于StringBuilder。
StringBuilder和StringBuffer中的方法作用都一致,只不过StringBuffer中的方法使用了synchronized关键字修饰,表示一个同步方法,在多线程环境下不会出现问题。
其中其StringBuilder类为例
构造方法
常用构造方法 | 作用 |
StringBuilder() | 创建一个大小为16的字符数组。类似于String str=""; |
StringBuilder(int capacity) | 创建一个指定大小的字符数组 |
StringBuilder(String str) | 创建一个str长度+16的字符串数组后,将str添加到其中。类似于String str="初始值"; |
普通方法
方法 | 作用 |
append(Object obj) | 将指定内容添加到原可变字符串对象末尾 |
delete(int start,int end) | 删除[start,end)范围内的字符 |
insert(int index,Object obj) | 将obj添加到index位置上 |
replace(int start,int end,String str) | 将[start,end)范围内的字符替换为str |
reverse() | 翻转原字符串 |
deleteCharAt(int index) | 删除指定索引的字符 |
其中需要注意
- 以上方法都是在直接操作原字符串,每个方法调用后,原字符串都会发生变化。
- StringBuilder或StringBuffer中并没有重写equlas方法,所以要比较两个可变字符串对象的值是否相同时,需要将可变字符串对象转换为String对象后,调用equals方法比较。
可变字符串与不可变字符串之间的转换
不可变字符串转换为可变字符串
//定义一个不可变字符串对象
String str="hello";
//创建一个可变字符串对象,将不可变字符串对象作为参数
StringBuilder sb = new StringBuilder(str);
可变字符串转换为不可变字符串
//创建一个可变字符串对象
StringBuilder sb = new StringBuilder("hello");
//调用toString()转换为String类型
String str=sb.toString();
System类
这个类包含了一些系统相关 的信息和操作数组的方法。其中的方法和属性都是静态的。
常用属性和方法 | 作用 |
System.in | 获取系统输入流对象,通常用于获取输入信息 |
System.out | 获取系统打印输出流对象,通常用于打印普通信息 |
System.err | 获取系统打印输出流对象,通常用于打印异常信息 |
System.exit(int statues) | 终止虚拟机运行,0表示正常结束 |
System.getenv(String key) | 获取系统指定的环境变量信息 |
System.arraycopy(原数组,原数组起始位置,目标数组,目标数组起始位置,原数组要赋值的元素数量) | 将原数组中指定长度的元素复制到新数组中 |
System.currentTimeMills() | 获取从1970.1.1 0:0:0(UTC)至今经过了多少毫秒。中国是UTC(+8)所以是从1970.1.1 8:0:0至今经过了多少毫秒,返回long类型 |
Runtime类
Runtime类的对象,用于表示程序运行时对象(程序运行环境对象)。
包含了程序运行环境相关的信息。常用于获取运行环境信息(如虚拟机内存)或执行某个命令。
但这个类不是一个抽象类,但不能创建对象,因为其构造方法是私有的。
以下是Runtime类的简单使用
package com.hqyj;
import java.io.IOException;
public class Test4 {
public static void main(String[] args) throws IOException, InterruptedException {
//通过静态方法getRuntime()获取一个Runtime类的对象
Runtime runtime = Runtime.getRuntime();
//获取程虚拟机空闲内存,单位为字节
System.out.println("当前虚拟机空闲内存" + runtime.freeMemory() / 1024 / 1024 + "MB");
//获取虚拟机总内存
System.out.println("当前虚拟机最大内存" + runtime.totalMemory() / 1024 / 1024 + "MB");
//获取虚拟机支持的最大内存
System.out.println("当前虚拟机支持的最大内存" + runtime.maxMemory() / 1024 / 1024 + "MB");
//让系统运行某个指令或程序,返回当前运行的进程对象
Process mspaint = runtime.exec("mspaint");//打开画图工具
Thread.sleep(3000);
//通过进程对象调用destroy()销毁进程,关闭程序
mspaint.destroy();
runtime.exec("calc");//打开计算器
runtime.exec("notepad");//打开记事本
//打开某个可执行文件
runtime.exec("D:\\xiaopw84in1111\\disland.xiaopw84in1\\smynesc.exe");
//300s后关机
runtime.exec("shutdown -s -t 300");
//取消关机任务
runtime.exec("shutdown -a");
}
}
包装类
Java是纯面向对象语言,宗旨是将一切事物视为对象处理。
但原始类型不属于对象,不满足面向对象的思想,但原始类型使用时无需创建对象,保存在栈中,效率更改。
为了让原始类型也有对象的类类型,达到"万物皆对象"的思想,所以就有了包装类的概念。
包装类就是原始类型对应的类类型。包装类通常用于将字符串转换为对应的原始类型。
在web应用中,从浏览器中获取到后台的数据,全是String类型,一定要使用转换的方法。
包装类 | 原始类型 | 将字符串转换为原始类型 |
Byte | byte | Byte.parseByte(String str) |
Short | short | Short.parseShort(String str) |
Integer | int | Integer.parseInt(String str) |
Long | long | Long.parseLong(String str) |
Float | float | Float.parseFloat(String str) |
Double | double | Double.parseDouble(String str) |
Boolean | boolean | Boolean.parseBoolean(String str) |
Character | char | 无 |
字符串与原始类型之间的转换
原始类型转换为字符串
int num = 123;
String str = String.valueOf(num);
字符串转换为原始类型
String num="123";
int i=Integer.parseInt(num);
Date类
用于表示日期时间的类
构造方法
常用构造方法 | 说明 |
Date() | 创建当前瞬间的日期对象 |
Date(long l) | 创建指定毫秒数对应的日期对象。(从1970.1.1起经过了的毫秒数) |
Date(int year,int month,int date) | 该构造方法已过时。创建指定年月日的日期对象。(年从1900年起经过的年数,月用0-11表示1-12月) |
常用方法
常用方法 | |
getTime() | 得到对应Date对象指定的毫秒数。 |
setTime(long l) | 设置毫秒数 |
after(Date when) | 判断调用日期对象是否在when之后 |
before(Date when) | 判断调用日期对象是否在when之前 |
SimpleDateFormat类
是一个用于格式化日期的类。
构造方法
//参数为一个日期模板
SimpleDateFormat(String pattern);
//如定义这样的一个模板对象
SimpleDateFormat sdf=new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
//创建一个Date对象
Date now = new Date();
//调用格式化方法,参数为一个Date对象
String res=sdf.formart(now);
//输出的形式为2022/07/28
System.out.println(res);
常用方法
常用方法 | 返回值 | 作用 |
format(Date date) | String | 将Date对象按日期模板转换为字符串 |
parse(String str) | Date | 将满足日期模板的字符串转换为Date对象 |
Calendar类
用于表示日历的类。包含了很多日历相关的信息。
是一个抽象类,无法直接创建对象,可以通过该类的静态方法getInstance()获取该类的实例。
//获取Calendar类的实例
Calendar c = Calendar.getInstance();
日历字段
值 | 说明 |
Calendar.YEAR | 获取年份 |
Calendar.MONTH | 获取月份(0-11表示1-12月) |
Calendar.DATE | 获取日期 |
Calendar.DAY_OF_WEEK | 获取星期(1-7表示周天到周六) |
Calendar.HOUR_OF_DAY | 获取二十四小时制的小时 |
Calendar.MINUTE | 获取分钟 |
Calendar.SECOND | 获取秒 |
Calendar.DAY_OF_MONTH | 本月中的第几天 |
Calendar.DAY_OF_YEAR | 本年中的第几天 |
Calendar.WEEK_OF_MONTH | 本月中的第几周 |
Calendar.WEEK_OF_YEAR | 本年中的第几周 |
常用方法
常用方法 | |
get(日历字段) | 获取指定日历字段实际的值 |
getTime() | 获取对应的Date对象(Calendar转换为Date) |
getMaximum(日历字段) | 获取指定日历字段支持的最大值。如Calendar.DATE支持最大值为31 |
getActualMaximum(日历字段) | 获取指定日历字段在实际时间下的最大值。如4月下Calendar.DATE实际最大值为30 |
getTimeZone() | 获取当前日历在实际时间下的时区信息 |
set(日历字段,值) | 将指定日历字段设置为指定值 |
set(年,月,日) | 设置指定的年月日,没有设置的部分沿用当前日期。 |
异常
当程序没有按程序员的意愿正常执行,中途出错导致程序中断,出现这种情况,就称为异常。
学习异常就是认识异常的种类和如何避免异常出现。
为了让程序能正常执行,就需要学会解决异常。
异常的产生
异常在程序中以对象的形式存在。当代码执行时出现异常,虚拟机会自动创建一个相应的异常对象,如果没有对该异常进行处理,就会导致程序中断。
异常的分类
错误和异常的区别
Error错误
如果出现XXXXXError,如StackOverflowError栈空间溢出时,无法通过额外的代码去解决,只能修改源码。
Exception异常
如果出现XXXXException,如NullPointerException空指针异常时,可以通过额外代码去避免。
运行时异常和非运行时异常
如果一个异常属于RuntimeException异常类的子类,称为运行时异常,可以通过编译,运行时可能抛出异常对象。
如果一个异常属于Exception异常类的子类,称为非运行时异常,无法通过编译,只有处理后才能编译运行。
运行时异常(RuntimeException)
常见运行时异常 | 说明 | 出现的情景 |
NullPointerException | 空指针异常 | 用空对象null调用方法或属性 |
ArrayIndexOutOfBoundsException | 数组下标越界异常 | 使用数组时,下标超出范围 |
ClassCastException | 对象转型异常 | Dog dog=(Dog)new Person();(Person类和Dog类不是继承关系) |
InputMismatchException | 输入类型不匹配异常 | 如需要int类型的数据,输入String类型的数据。 |
ArithmeticException | 算术运算异常 | 0当分母 |
IllegalArgumentException | 非法参数异常 | 调用方法的参数不合理 |
非运行时异常(除了RuntimeException以外的异常)
常见非运行时异常 | 说明 | 出现的情景 |
IOException | 输入输出流异常 | 当使用流对象 |
SQLException | 数据库SQL相关异常 | 操作数据库时 |
FileNotFoundException | 文件未找到异常 | 方法的参数为文件 |
处理异常的方式
方式一:通过try-catch-finally语句处理异常
try{ //可能出现异常的代码 }catch(异常类 异常对象){ //如果出现异常对象,且与catch中的异常类匹配,则执行 }catch(异常类 异常对象){//后续的catch中的异常类型只能与之前的异常类型同级或是父类 //如果出现异常对象,且与catch中的异常类匹配,则执行 }finally{ //无论程序是否会抛出异常,一定要执行的代码 }
方式二:通过throws关键字声明异常
public class Test{ public void fun() throws InterruptException{//在定义方法时,声明可能抛出的异常类型 //如果直接写这句话,会报错,因为sleep()方法会抛出一个非运行时异常,必须要处理 Thread.sleep(5000); } }
throw和throws的区别
throws表示用于方法声明异常。使用时写在方法的小括号之后
//用于声明方法的异常
public void fun() throws Exception{
}
throw用于手动抛出异常对象。使用时写在{}中,通常用于满足某种条件时,强制中断程序。
public void fun(){
//用于手动抛出一个异常对象
RuntimeException e = new RuntimeException();
throw e;
}
自定义异常
可以自定义异常,在满足某种条件下,手动通过throw关键字抛出异常,人为中断程序。
步骤
- 定义一个类,继承某个异常类。
如果继承的是RuntimeException,表示自定义的异常类属于运行时异常,该异常对象可以不用处理。
如果继承的是非RuntimeException,表示自定义的异常类属于非运行时异常,该异常对象必须要处理。 - [可选操作]定义一个无参数的构造方法,调用父类中无参的构造方法,定义一个带字符串参数的构造方法,调用父类带字符串参数的构造方法。
数组与集合
特点
数组
- 数组中保存的元素都是有序的,可以通过下标快速访问
- 数组中保存的数据都是同一种类型
- 数组的长度在定义后,无法改变
- 数组无法获取其中保存的实际元素数量
集合
- 能保存一组数据,可以有序也可以无序
- 集合的容量可变
- 集合中可以保存不同类型的数据
- 可以获取集合中实际的元素数量
Collection接口
核心的两个子接口:Set和List。
这两个接口都可以保存一组数据,Set接口保存数据时,是无序不重复的;List接口保存数据时,是有序可重复的。
Collections集合工具类
- Collection是集合的根接口,定义了集合的方法
- Collections是集合的工具类,定义了很多静态方法,直接通过类名使用
常用方法
常用方法 | |
Collections.shuffle(List list) | 打乱有序集合中的元素顺序 |
Collections.swap(List list,int i,int j) | 交换有序集合中i和j索引上的元素 |
Collections.replaceAll(List list,Object oldVal,Object newVal) | 将有序集合中的旧元素替换为新元素 |
Collections.fill(List list,Object obj) | 将有序集合使用obj填充 |
Collections.rotate(List list,int distance) | 将最后distance个元素放在最前 |
Collections.sort(List list) | 对有序集合中的元素进行排序,元素必须实现了Comparable接口 |
Collections.max(Collection list) | 得到有序集合中的最小元素,元素必须实现了Comparable接口 |
Collections.min(Collection list) | 得到有序集合中的最大元素,元素必须实现了Comparable接口 |
List接口
有序集合,元素可以重复,允许保存null,可以通过索引获取对应位置上的元素。
在接口中定义了一些操作元素的方法,如获取元素数量、添加、删除、替换、截取等。
Set接口
无序集合,元素不可以重复,允许保存null,没有索引。
在接口中定义了一些操作元素的方法,如获取元素数量、添加、删除、替换、截取等。
ArrayList实现类
- 采用数组实现的集合
- 可以通过索引访问元素、可以改变集合大小。如果要在其中插入或删除元素时,会影响其余元素。该集合查询效率高、增删中间元素效率低。
- 该集合对象中保存的元素,都是引用类型(对象的内存地址)。即使保存了123,其实不是保存的int类型的123,而是Integer类型的123.
构造方法
常用构造方法 | 说明 |
ArrayList() | 创建一个无参的ArrayList对象。实际是创建了一个空的Object数组。在调用添加元素方法时,才会初始化该数组大小为10。 |
ArrayList(int capacity) | 创建一个指定容量的ArrayList对象,实际是创建一个指定大小的Object数组,如果参数为负,会抛出IllegalArgumentException异常 |
常用方法
常用方法 | 作用 | 返回值 |
add(Object obj) | 添加obj到集合的末尾 | boolean |
add(int index,Object obj) | 添加obj到index索引上 | void |
get(int index) | 得到指定index索引的元素 | Object |
set(int index,Object obj) | 使用obj覆盖index索引的元素,返回被覆盖的元素 | Object |
size() | 获取集合中的元素数量 | int |
isEmpty() | 判断集合是否为空 | boolean |
clear() | 清空集合 | void |
remove(Object obj) | 删除指定obj对象 | boolean |
remove(int index) | 删除指定Index索引的元素,返回被删除的元素 | Object |
contains(Object obj) | 判断是否存在obj元素 | boolean |
indexOf(Object obj) | 得到元素obj第一次出现的索引 | int |
lastIndexOf(Object obj) | 得到元素obj最后一次出现的位置 | int |
subList(int from,int to) | 得到[from,to)区间内的元素 | List |
toArray() | 将集合转换为数组 | Object[] |
LinkedList实现类
构造方法
常用构造方法 | 说明 |
LinkedList() | 创建一个空链表 |
常用方法
常用方法 | |
addFirst() | 添加头结点 |
addLast() | 添加尾结点 |
getFirst() | 得到头结点 |
getLast() | 得到尾结点 |
remove() | 删除头结点 |
removeFirst() | 删除头结点 |
removeLast() | 删除尾结点 |
push(Object obj) | 添加头结点(入栈) |
pop() | 得到并移除头结点(出栈) |
peek() | 得到头结点 |
poll() | 删除头结点 |
offer(Object) | 添加尾结点 |
ArrayList和LinkedList的区别
- 两者都是List接口的实现类,保存的元素有序可重复,允许保存null,拥有一些公共的方法,如size(),isEmpty(),subList(int from,int to)等
- ArrayList采用数组实现,对于随机读取效率更高,通常用于查询;LinkedList采用双向链表实现,插入删除不影响其他元素位置,通常用于中间插入删除。
哈希表Hash table
哈希表,也称为散列表,是一种数据结构,能更快地访问数据。
要保存的数据称为原始值,这个原始值通过一个函数得到一个新的数据,这个函数称为哈希函数,这个新数据称为哈希码,哈希码和原始值之间有一个映射关系,这个关系称为哈希映射,可以构建一张映射表,称为哈希表。在哈希表中,可以通过哈希码快速访问对应的原始值。
哈希码的特点
- 如果两个对象的hashCode不同,这两个对象一定不同
- 如果两个对象的hashCode相同,这两个对象不一定相同
- 如"通话"和"重地"这两个字符串的hashCode相同,但是两个对象
- hashCode相同,对象不同,称为哈希冲突
HashSet实现类
- 采用哈希表实现
- 元素不能重复,无序保存,允许保存null
- 本质是一个HashMap对象,调用add()方法,实际调用的也是HashMap中的put()方法,参数作为put()方法的键,new Obejct()作为put()方法的值
构造方法
常用构造方法 | 说明 |
HashSet() | 创建一个默认的集合对象,实际是创建了一个大小为16,加载因子为0.75的HashMap对象 |
HashSet(int capacity) | 创建一个指定容量的集合对象,实际是创建了一个指定大小,加载因子为0.75的HashMap对象 |
HashSet(int capacity,float loadFactor) | 创建一个指定容量和指定加载因子的集合对象。 |
常用方法
常用方法 | 说明 |
add(Object obj) | 添加元素到集合中 |
size() | 得到元素数量 |
isEmpty() | 判断集合是否为空 |
remove(Object obj) | 根据对象删除元素 |
contains(Object obj) | 判断是否存在某个元素 |
toArray() | 将集合转换为Object数组 |
clear() | 清空集合 |
TreeSet实现类
- 特殊的Set实现类,数据可以有序保存,可以重复,不能添加null元素
- 采用红黑树(自平衡二叉树)实现的集合
- 二叉树表示某个节点最多有两个子节点
- 某个节点右侧的节点值都大于左侧节点值
- 只能添加同一种类型的对象且实现了Comparable接口的对象
- 实现Comparable接口后必须要重写compareTo方法
- 每次调用添加时,参数会自动调用该方法
- 添加的元素可以自动排序
- compareTo方法的返回值决定了能否添加新元素和新元素的位置
- 如果返回0,视为每次添加的是同一个对象,不能重复添加
- 如果返回正数,将新元素添加到现有元素之后
- 如果返回负数,将新元素添加到现有元素之前
构造方法
常用构造方法 | 说明 |
TreeSet() | 实际会创建一个TreeMap对象 |
常用方法
常用方法 | 作用 |
add(Object obj) | 添加元素到集合中 |
size() | 得到元素数量 |
isEmpty() | 判断集合是否为空 |
clear() | 清空集合 |
ceiling(Object obj) | 得到比指定元素大的最小元素 |
floor(Object obj) | 得到比指定元素小的最大元素 |
first()/last() | 得到第一个/最后一个元素 |
HashMap实现类
- JDK1.8之后,HashMap的数据结构采用"数组+链表+红黑树"实现
- 当没有哈希冲突时,元素保存到数组中
- 如果哈希冲突,在对应的位置上创建链表,元素保存到链表中
- 当链表元素数量大于8,转换为红黑树
- 数据采用"键值对"的形式保存,键称为key,值称为value ,键不能重复,允许null,值没有限制,键和值都是引用类型
- 在哈希表中,哈希码就是键,保存的数据就是值,可以通过键得到相应的值。
构造方法
常用构造方法 | 说明 |
HashMap() | 创建一个空的集合对象,默认大小为16,加载因子为0.75 |
实现方法
常用方法 | 作用 |
put(Object key,Object Value) | 添加一组键值对 |
get(Object key) | 根据键得到值 |
size() | 得到键值对的数量 |
clear() | 清空所有键值对 |
keyset() | 得到所有键的集合 |
values() | 得到所有值的集合 |
containtsKey(Object key) | 判断是否包含某个键 |
containsValue(Object value) | 判断是否包含某个值 |
remove(Object key) | 根据键删除键值对 |
集合与数组之间的转换
集合转换为数组
Object[] 数组 = 集合对象.toArray(); List list = new ArrayList(); list.add(123); Object[] obj = list.toArray(); System.out.println((Integer)obj[0]);
数组转换为集合
int[] ints={1,2,3,9,22,16}; //将数组保存到一个数组集合中,上边定义的那个数组就是集合中的第一个元素 List<int[]> ints1 = Arrays.asList(ints); //遍历转换后的数组 for (int[] ints2 : ints1) { //遍历数组中的元素 for (int i : ints2) { System.out.println(i); } }
File文件
Java中可以将本地硬盘中的文件(文件和目录)以对象的形式表示。
就能通过Java代码对本地文件进行读取或操作。
构造方法
常用构造方法 | 说明 |
File(String pathName) | 根据文件的完整路径创建对象 |
File(String parent,String name) | 根据文件所在的父目录路径和自身文件名创建对象 |
File(File parent,String name) | 根据文件所在父目录文件对象和自身文件夹创建对象 |
常用方法
常用方法 | 说明 | 返回值 |
exists() | 判断文件是否存在 | boolean |
isFile() | 判断是否为文件 | boolean |
isDirectory() | 判断是否为目录 | boolean |
getName() | 得到文件名 | String |
getPath() | 得到文件所在相对路径 | String |
getAbsolutePate() | 得到文件所在绝对路径 | String |
getParent() | 得到父目录的名称 | String |
getParentFile() | 得到父目录的对象 | File |
lastModified() | 得到文件最后一次修改时间对应的毫秒数 | long |
length() | 得到文件的所占字节大小 | long |
isHidden() | 判断文件是否为隐藏 | boolean |
list() | 得到目录下的第一层子文件名的字符串数组 | String[] |
listFiles() | 得到目录下的第一层子文件的文件数组 | File[] |
delete() | 删除某个文件或空目录 | boolean |
mkdir() | 创建一个空目录 | boolean |
renameTo(File newFile) | 将原文件命名为新文件(新文件可以指定新位置) | boolean |
IO流
I:Input输入
O:Output输出
流:在Java中,流用于表示计算机硬盘与内存之间传输数据的通道。
将内存中的数据存入到硬盘中,称为写write,也称为输出
将硬盘中的数据存入到内存中,称为读read,也称为输入
流的分类
InputStream字节输入流
FileInputStream文件字节输入流 ObjectInputStream对象字节输入流(反序列化)
OutputStream字节输出流
FileOutputStream文件字节输出流 ObjectOutputStream对象字节输出流(序列化)
Writer字符输出流
FileWriter文件字符输出流 BufferedWriter缓冲字符输出流(包装流) OutputStreamWriter字节输出流转换为字符输出流(转换流)
Reader字符输入流
FileReader文件字符输入流 BuffedredReader缓冲字符输入流(包装流) InputStreamReader字节输入流转换为字符输入流(转换流)
按方向分类
输入流:InputStream、Reader
作用:将硬盘中的数据读取到内存中
输出流:OutputStream、Wrtiter
作用:将内存中的数据写入到硬盘中
按类型分类
字节流:InputStream、OutputStream
作用:适用于非文本类型,如图片、文件等的读写
字符流:Reader、Writer
作用:适用于文本类型,尤值txt格式文件的读写
FileInputStream文件字节输入流
构造方法
常用构造方法 | 说明 |
FileInputStream(String pathName) | 根据文件名创建文件字节输入流对象 |
FileInputStream(File file) | 根据文件对象创建文件字节输入流对象 |
常用方法
常用方法 | 作用 |
read() | 读取一个字节。返回读取到的字节本身。 |
read(byte[] b) | 按字节数组读取。返回读取到的字节数量。读取到的内容保存在了字节数组中 |
close() | 关闭流对象 |
FileOutputStream文件字节输出流
构造方法
常用构造方法 | 说明 |
FileOutputStream(String pathName) | 根据文件名创建文件字节输出流对象,写入内容时覆盖原内容 |
FileOutputStream(String pathName,boolean append) | 根据文件名创建文件字节输出流对象,写入内容时追加在原内容之后 |
FileOutputStream(File file) | 根据文件对象创建文件字节输出流对象,写入内容时覆盖原内容 |
FileOutputStream(File file,boolean append) | 根据文件对象创建文件字节输出流对象,写入内容时追加在原内容之后 |
常用方法
常用方法 | 作用 |
write(int i) | 写入一个字节 |
write(byte[] bytes) | 写入一个字节数组 |
write(byte[] bytes,int off,int len) | 写入字节数组中从off开始的len个字节 |
flush() | 将数据冲刷到本地文件中 |
close() | 关闭流对象 |
FileReader文件字符输入流
构造方法
常用构造方法 | 说明 |
FileReader(String fileName) | 根据文件名创建文件字符输入流对象 |
FileReader(File file) | 根据文件对象创建文件字符输入流对象 |
常用方法
常用方法 | 作用 |
ready() | 判断是否还有下一个字符 |
read() | 读取下一个字符,返回读取到的字符 |
read(char[] chars) | 按字符数组读取字符,返回读取到的字符数量,读取到的字符保存在了字符数组中 |
close() | 关闭流对象 |
FileWriter文件字符输出流
构造方法
常用构造方法 | 说明 |
FileWriter(String fileName) | 按文件名创建字符输出流对象 |
FileWriter(String fileName,boolean append) | 按文件名创建字符输出流对象,允许追加写入 |
FileWriter(File file) | 按文件对象创建字符输出流对象 |
FileWriter(File file,boolean append) | 按文件对象创建字符输出流对象,允许追加写入 |
常用方法
常用方法 | 作用 |
write(String str) | 按字符串写入 |
write(char[] c) | 按字符数组写入 |
write(String str,int off,int len) | 按字符串写入,从off开始写入len个字符 |
write(char[] c,int off,int len) | 按字符数组写入,从off开始写入len个字符 |
flush() | 冲刷流中的数据到硬盘中(必须调用该方法或close方法后,才能真正写入) |
close() | 关闭流对象 |
BufferedReader字符缓冲输入流
自带字符数组(缓冲区)的字符输入流。默认字符数组大小为8192,每次最多读取8192个字符
在读取纯文本文件(txt或md等)时,首选该类。
构造方法
常用构造方法 | 说明 |
BufferedReader(Reader reader) | 创建一个带有缓冲区(字符数组)的字符输入流对象,默认缓冲区大小为8192。参数注意是一个Reader类型的对象,但Reader是一个抽象类,所以要使用其子类,如FileReader,然后在FileReader中定义要读取的文件信息 |
BufferedReader(Reader reader,int size) | 创建一个指定缓冲区(字符数组)大小的字符输入流对象 |
常用方法
常用方法 | 作用 |
ready() | 判断是否还有字符 |
readLine() | 读取整行字符 |
close() | 关闭流对象 |
BufferedWriter字符缓冲输出流
自带字符数组(缓冲区)的字符输出流。
构造方法
常用构造方法 | 说明 |
BufferedWriter(Writer writer) | 创建一个带有缓冲区(字符数组)的字符输出流对象,参数为一个Writer对象,但Writer是一个抽象类,所以要使用其子类,如FileWriter对象,在FileWriter中定义要写入的文件 |
BufferedWriter(Writer writer,int size) | 创建一个指定缓冲区(字符数组)大小的字符输出流对象 |
常用方法
常用方法 | 作用 |
write(String str) | 写入一个字符串 |
newLine() | 换行 |
flush() | 将输出流中的字符冲刷到文件中 |
close() | 关闭流对象 |
ObjectOutputStream对象字节输出流
序列化:将对象转换为文件的过程
被序列化的对象,必须要实现Serializable接口。
这个接口是一个特殊的接口,没有定义方法,只是给这个类打上标记,表示该类可以被序列化。
构造方法
常用构造方法 | 说明 |
ObjectOutputStream(OutputStream os) | 创建一个对象字节输出流对象,参数为一个字节输出流对象,由于是抽象类,所以要使用其子类,如FileOutputStream对象,在其中定义要写入的文件。 |
常用方法
常用方法 | 作用 |
writeObject(Object obj) | 将一个对象写入到本地文件中 |
close() | 关闭流对象 |
ObjectInputStream对象字节输入流
构造方法
常用构造方法 | 说明 |
ObjectInputStream(InputStream is) | 创建一个对象字节输入流对象,参数为一个字节输入流对象,由于是抽象类,所以要使用其子类,如FileInputStream对象,在其中定义要读取的文件 |
常用方法
常用方法 | 作用 |
readObject() | 读取序列化后的文件,返回对象Object |
close() | 关闭流对象 |
转换流
实际属于字符流,作用为将一个字节流对象转换为字符流对象
OutputStreamWriter
将字节输出流转换为字符输出流
InputStreamReader
将字节输入流转换为字符输入流
网络编程
InetAddress类
表示IP对象的一个类,实现效果如下
package com.hqyj.NetTest; import java.io.IOException; import java.net.InetAddress; public class Test { public static void main(String[] args) throws IOException { //InetAddress用于表示当前计算机所在网络地址的类(IP地址对象) InetAddress localHost = InetAddress.getLocalHost();//getLocalHost()获取计算机名和当前网络环境下的IP地址 System.out.println(localHost); //getByName(域名) www.baidu.com 得到域名对应的ip地址 InetAddress byName = InetAddress.getByName("www.taobao.com"); System.out.println(byName); //得到IP地址 System.out.println(byName.getHostAddress()); //得到域名部分 System.out.println(byName.getHostName()); } }
Socket类和ServerSocket类
都属于Socket(套接字)对象,表示网络中的某个端点。
- ServerSocket指服务器端
- Socket指普通端点
具体的实现过程如下
服务器端
package com.hqyj.NetTest;
import java.io.*;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
//InetAddress表示一个IP对象类
//根据当前自己电脑的IP地址创建一个IP对象
InetAddress ip = InetAddress.getByName("192.168.3.46");
//服务器端套接字对象(网络中的某个服务节点) 节点的端口号 连接数 IP对象
ServerSocket server = new ServerSocket(9527, 20, ip);
System.out.println("服务器端已经部署,等待连接");
//等待另一个套接字对象连接,程序处于阻塞状态,直到另一个套接字对象连接才会继续
Socket client = server.accept();//client表示连接成功的客户端对象
//创建一个最终客户端上传上来的目标文件对象和将其保存到本地的输出流对象
File file = new File("upload/test.zip");
FileOutputStream fos = new FileOutputStream(file);
//获取客户端和服务器端的输入流对象
InputStream is = client.getInputStream();
//按字节数组读写
byte[] bytes = new byte[1024 * 1024 * 8];
//使用字节数组获取客户端发送过来的字节
int count = is.read(bytes);
while (count != -1) {
fos.write(bytes, 0, count);
//将读取到的字节保存到服务器本地硬盘中
count = is.read(bytes);
}
is.close();
fos.close();
}
}
客户端
package com.hqyj.NetTest;
import java.io.*;
import java.net.Socket;
public class Client {
public static void main(String[] args) throws IOException {
//创建一个客户端套接字对象,需要写明要连接的服务端套接字对象的IP地址和端口号
Socket client = new Socket("192.168.3.46", 9527);
//获取客户端与服务端的输出流对象
OutputStream os = client.getOutputStream();
//读取本地文件
File file = new File("d:/信息.zip");
//读取本地文件的输入流对象
FileInputStream fis = new FileInputStream(file);
//按字节数组读写
byte[] bytes = new byte[1024 * 1024 * 8];
int count = fis.read(bytes);
while (count != -1) {
//将读取到的字节数组马上写入到与服务器端的输入流对象中
os.write(bytes, 0, count);
count = fis.read(bytes);
}
fis.close();
os.close();
}
}
进程和线程
进程Process
进程就是操作系统中执行的程序。一个进程就是一个执行的程序实体。
每个运行中的进程,都有属于它独立的内存空间。各个进程之间互不影响。
线程Thread
线程是一个进程中的执行单元,一个进程中可以有多个线程。
多线程之间,可以访问同一个进程中的资源。
每个线程都有一个独立的栈空间。这些线程所在的栈空间位于同一个进程空间中。
获取当前正在运行的线程对象
//获取当前运行的线程对象
Thread ct = Thread.currentThread();
构造方法
常用构造方法 | 说明 |
Thread() | 创建一个默认的线程对象 |
Thread(String name) | 创建一个指定线程名的线程对象 |
Thread(Runnable target) | 将一个Runnable对象包装为线程对象 |
Thread(Runnable target,String name) | 将一个Runnable对象包装为线程对象同时命名 |
常用方法
常用方法 | 作用 |
setName(String str) | 设置线程名称 |
setPriority(int i) | 设置线程优先级(1~10),数字越大优先级越高,线程越先执行完 |
setDaemon(boolean f) | 是否将该线程设置为守护线程 |
getId() | 获取线程ID |
getName() | 获取线程名,主线程名默认main,自定义线程名默认Thread-N |
getPriority() | 获取线程优先级 |
getState() | 获取线程状态 |
isDaemon() | 判断该线程是否属于守护线程 |
start() | 启动线程 |
run() | 线程启动后执行的方法 |
Thread.currentThread() | 获取当前运行的线程对象 |
Thread.sleep(long m) | 设置当前线程休眠m毫秒 |
Thread.yield() | 线程让步,让其他线程执行 |
多线程
如果一个进程中,同时在执行着多个线程,就称为多线程。
其实每个执行的Java程序,都是多线程的,虽然看似只有main方法所在的主线程在执行,其实还有一个gc线程(守护线程)。
如有一个工厂,工厂中有很多车间,车间中有很多流水线。
工厂就是内存,车间就是各个进程,拥有一块属于该进程的内存空间,每个流水线都是一个线程,属于对应进程下的一块子空间。
实现多线程的方式
方式一:继承Thread类
- 1.让某个类成为Thread类的子类
- 2.重写Thread类中的run方法,将要让该线程执行的内容写在该方法中
- 3.创建Thread类的对象后,调用start()方法,启动线程
方式二:实现Runnable接口
由于Java中是单继承,所以如果某个类已经使用了extends关键字去继承了另一个类,这时就不能再使用extends继承Thread类实现多线程,就需要使用实现Runnable接口的方法实现多线程。
- 1.自定义一个类,实现Runnable接口
- 2.重写run方法,将要多线程执行的内容写在该方法中
- 3.创建Thread线程对象,将自定义的Runnable接口实现类作为构造方法的参数
- 4.调用线程对象的start()方法启动线程
方式三:使用匿名内部类
如果不想创建一个Runnable接口的实现类,就可以使用匿名内部类充当Runnable接口的实现类
并行和并发
并行
多个进程各自执行,称为并行。
并发
多个线程同时执行,称为并发。
同步和异步
同步
所有的任务排队执行,称为同步执行。
异步
在执行任务A的同时,执行任务B,称为异步执行。
线程的生命周期
线程的生命周期
线程的初始化到终止的整个过程,称为线程的生命周期
新生状态
当线程对象被实例化后,就进入了新生状态。new Thread()
就绪状态
当某个线程对象调用了start()方法后,就进入了就绪状态。
在该状态下,线程对象不会做任何事情,只是在等待CPU调用。
运行状态
当某个线程对象得到运行的机会后,则进入运行状态,开始执行run()方法。
不会等待run()方法执行完毕,只要run()方法调用后,该线程就会再进入就绪状态。这时其他线程就有可能穿插其中。
阻塞状态
如果某个线程遇到了sleep()方法或wait()等方法时,就会进入阻塞状态。
sleep()方法会在一段时间后自动让线程重新就绪。
wait()方法只有在被调用notify()或notifyAll()方法唤醒后才能进入就绪状态。
终止状态
当某个线程的run()方法中所有内容都执行完,就会进入终止状态,意味着该线程的使命已经完成。
synchronized关键字
这个关键字可以修饰方法或代码块。
修饰方法
写在方法的返回值前。这样该方法就称为同步方法,在执行的时候,其他线程要排队等待该方法执行完毕后才执行。
public synchronized void fun(){
//要同步的代码
}
修饰代码块
写在{}前,这样这段{}中的内容称为同步代码块,在执行的时候,其他线程要排队等待该方法执行完毕后才执行。
//要同步的代码
}
原理
每个对象都默认有一把"锁",当某个线程运行到被synchronized修饰的方法时,该对象就会拥有这把锁,在拥有锁的过程中,其他线程不能同时访问该方法,只有等待其执行结束后,才会释放这把锁。
使用synchronized修饰后拥有的锁称为"悲观锁",在拥有的时候,不允许其他线程访问。
方法被synchronized修饰后,成为了同步方法,就会让原本的多线程成为了单线程(异步变为同步),虽然效率变低,但是数据安全是首位。