JavaSE第一阶段基础知识总结
一、面向对象
1.1 基本知识点
类:是相同事物共同特征(行为,属性)的描述。
对象:是一类事物的具体体现。格式:类名 对象名 = new 类名();
ps:类是对象的模板,对象是类的实体
成员变量:类中方法外,有默认值,堆内存中,作用范围是类;
局部变量:方法内或方法声明处,没有默认值,栈内存中,作用范围是方法内。
构造方法:主要是完成对象数据的初始化;方法名与类名相同。
super:代表的是父类对象的引用;
this:代表的是当前对象的引用。
final:修饰不可改变内容;可以用于修饰类、方法和变量。被修饰的–>>
- 类:被修饰的类,不能被继承。
- 方法:被修饰的方法,不能被重写。
- 变量:被修饰的变量,不能被重新赋值。
static:静态修饰符,修饰成员,被多个对象共享,静态只能访问静态,静态中午this关键字。
抽象类/方法:被abstract修饰的类/方法。可以被单继承,不能多继承。
- 意义:是为了被子类继承,否则抽象类将毫无意义,体现模板思想。
注意:
-
抽象类不能创建对象,如果创建,编译无法通过而报错。只能创建其非抽象子类的对象。
-
抽象类中,不一定包含抽象方法,但是有抽象方法的类必定是抽象类。
-
抽象类的子类,必须重写抽象父类中所有的抽象方法,否则子类也必须定义成抽象类,编译无法通过而报错。
-
抽象类存在的意义是为了被子类继承,抽象类体现的是模板思想。
接口:被interface修饰的类(替代class);不能创建对象,但可以被实现(implements
,类似于被继承)可以多实现。
内部类:将一个类A定义在另一个类B里面,里面的那个类A就称为内部类,B则称为外部类。
- 成员内部类:是定义在一个类中的类。
- 匿名内部类:本质是一个带具体实现的父类或者父接口的匿名的 子类对象。
代码块:
- 构造代码块:定义在成员位置的代码块{};执行:每次创建对象都会执行构造代码块。
- 静态代码块:定义在成员位置,使用static修饰的代码块{ }。类中方法外。随着类的加载而执行且执行一次,优先构造方法的执行。
权限修饰符:
public | protected | (空的) | private | |
---|---|---|---|---|
同一类中 | √ | √ | √ | √ |
同一包中(子类与无关类) | √ | √ | √ | |
不同包的子类 | √ | √ | ||
不同包中的无关类 | √ |
1.2 封装
封装是为了让代码的功能更加的安全,让细节被进一步的隐藏起来。原则上应该合理隐藏,合理暴露。
步骤:
- 使用
private
关键字来修饰成员变量。表示成员变量不能被直接访问。 - 使用public修饰方法,提供对应的一对用public修饰的
getXxx方法 、setXxx
方法来暴露成员变量的访问。
注意:public关键字是公开访问权限,private关键字是隐藏访问权限。
好处:提高了代码的安全性;提高了代码的复用性。
基本使用:JavaBean标准类的制作。
1.3 继承
就是子类继承父类的属性和行为,使得子类对象可以直接具有与父类相同的属性、相同的行为。子类可以直接访问父类中的非私有的属性和行为。(父类拥有子类的共有属性)。
好处:提高代码的复用性(减少代码冗余,相同代码重复利用);使类与类之间产生了关系。
注意:
-
子类不能继承父类的构造器,因为子类有自己的构造器。
值得注意的是子类可以继承父类的私有成员(成员变量,方法),只是子类无法直接访问而已,可以通过getter/setter方法访问父类的private成员变量。 -
对于子父类中成员重名,采用就近原则。
1.4 多态
是指同一行为,具有多个不同表现形式。当使用多态方式调用方法时,首先检查父类中是否有该方法,如果没有,则编译错误;如果有,执行的是子类重写后方法。
好处:提高程序的灵活性,扩展性
向上转型:多态本身是子类类型向父类类型向上转换的过程,这个过程是默认的。
向下转型:父类类型向子类类型向下转换的过程,这个过程是强制的。
二.常用API
2.1String和StringBuilder
String特点:字符串的值在创建后不能被更改。
常用方法:
方法 | 说明 |
---|---|
equals() | 将此字符串与指定对象进行比较 |
equalsIgnoreCase() | 将此字符串与指定对象进行比较,忽略大小写 |
contains () | 判断参数字符串在当前字符串中是否存在(区分大小写)。存在,返回true,否则,返回false |
endsWith(String suffix) | 测试此字符串是否以指定的后缀结尾(区分大小写) |
startsWith(String prefix) | 测试此字符串是否以指定的前缀开始(区分大小写) |
length () | 返回此字符串的长度 |
concat (String str) | 将指定的字符串连接到该字符串的末尾 |
charAt (int index) | 返回指定索引处的 char值 |
indexOf (String str) | 返回指定子字符串第一次出现在该字符串内的索引 |
lastIndexOf(String str) | 返回指定子字符串最后一次出现的字符串中的索引。 如果不包含,则返回-1 |
substring (int beginIndex) | 返回一个子字符串,从beginIndex开始截取字符串到字符串结尾 |
substring (int beginIndex, int endIndex) | 返回一个子字符串,从beginIndex到endIndex截取字符串。含beginIndex,不含endIndex |
toCharArray () | 将此字符串转换为新的字符数组 |
getBytes () | 使用平台的默认字符集将该 String编码转换为新的字节数组 |
toLowerCase() | 使用默认语言环境的规则将此 String所有字符转换为小写 |
toUpperCase() | 将此 String所有字符转换为大写,使用默认语言环境的规则 |
replace () | 将与target匹配的字符串使用replacement字符串替换 |
split(String regex) | 将此字符串按照给定的regex(规则)拆分为字符串数组 |
trim() | 去掉当前字符串的前后空格,并返回一个新字符串,原字符串不变 |
StringBuilder特点:是一个可变的字符串类–可以看作一个容器。
常用方法:
方法 | 说明 |
---|---|
append() | 添加数据,并返回对象本身 |
reverse() | 返回相反的字符序列 |
StringBuilder和String相互转换:
方法 | |
---|---|
StringBuilder转换为String | toString() |
String转换为StringBuilder | StringBuilder(String s) |
2.2 Object,Objects
Object类两个主要方法:
-
public String toString()
:返回该对象的字符串表示。(可以在标准类中重写覆盖) -
public boolean equals(Object obj)
:指示其它某个对象是否与此对象“相等”。
2.3 native本地方法
在Object类的源码中定义了 native 修饰的方法, native 修饰的方法称为本地方法。
作用:就是Java调用非Java代码的接口。方法的实现由非Java语言实现,比如C或C++。
Objects类:
public static boolean equals(Object a, Object b)
:判断两个对象是否相等。
2.4 Date
方法 | 说明 |
---|---|
Date() | 获取当前时间 |
Date(long date) | 根据参数毫秒值获取时间 |
常用方法:
方法 | 说明 |
---|---|
getTime() | 把日期对象转换成对应的时间毫秒值 |
setTime(long time) | 把方法参数给定的毫秒值设置给日期对象 |
DateFormat类构造方法:
方法 | 说明 |
---|---|
SimpleDateFormat(String pattern) | 用给定的模式和默认语言环境的日期格式符号构造SimpleDateFormat。参数pattern是一个字符串,代表日期时间的自定义格式。 |
格式规则:
y | M | d | H | m | s |
---|---|---|---|---|---|
年 | 月 | 日 | 时 | 分 | 秒 |
方法 | 说明 |
---|---|
public String format(Date date) | 将Date对象格式化为字符串。 |
public Date parse(String source) | 将字符串解析为Date对象。 |
Calendar类—日历类:
方法名 | 说明 |
---|---|
public static Calendar getInstance() | 获取一个它的子类GregorianCalendar对象。 |
public int get(int field) | 获取某个字段的值。field参数表示获取哪个字段的值, 可以使用Calender中定义的常量来表示: Calendar.YEAR : 年 Calendar.MONTH :月 Calendar.DAY_OF_MONTH:月中的日期 Calendar.HOUR:小时 Calendar.MINUTE:分钟 Calendar.SECOND:秒 Calendar.DAY_OF_WEEK:星期 |
public void set(int field,int value) | 设置某个字段的值 |
public void add(int field,int amount) | 为某个字段增加/减少指定的值 |
2.5 Math
方法名 | 说明 |
---|---|
public static int abs(int a) | 获取参数a的绝对值: |
public static double ceil(double a) | 向上取整 |
public static double floor(double a) | 向下取整 |
public static double pow(double a, double b) | 获取a的b次幂 |
public static long round(double a) | 四舍五入取整 |
2.6 System
方法名 | 说明 |
---|---|
public static void exit(int status) | 终止当前运行的 Java 虚拟机,非零表示异常终止 |
public static long currentTimeMillis() | 返回当前时间(以毫秒为单位) |
2.7 BigInteger
方法声明 | 描述 |
---|---|
add(BigInteger value) | 返回其值为 (this + val) 的 BigInteger,超大整数加法运算 |
subtract(BigInteger value) | 返回其值为 (this - val) 的 BigInteger,超大整数减法运算 |
multiply(BigInteger value) | 返回其值为 (this * val) 的 BigInteger,超大整数乘法运算 |
divide(BigInteger value) | 返回其值为 (this / val) 的 BigInteger,超大整数除法运算,除不尽取整数部分 |
2.8 BigDecimal类
作用:针对Java中小数运算有可能会有精度问题,解决这种精度问题.
方法声明 | 描述 |
---|---|
public BigDecimal add(BigDecimal value) | 加法运算 |
public BigDecimal subtract(BigDecimal value) | 减法运算 |
public BigDecimal multiply(BigDecimal value) | 乘法运算 |
public BigDecimal divide(BigDecimal value) | 除法运算 |
2.9 Arrays
方法 | 说明 |
---|---|
public static void sort(int[] a) | 按照数字顺序排列指定的数组 |
public static String toString(int[] a) | 返回指定数组的内容的字符串表示形式 |
2.10 包装类
自动拆箱装箱操作,完成对应类型转换。
基本类型 | 对应的包装类(位于java.lang包中) |
---|---|
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
boolean | Boolean |
注意:
-
String -->> Integer类型:parseInt();
-
Integer类型 -->> String:直接在数字后加一个空字符串/通过String类静态方法valueOf()。
三.集合
- 集合:集合是java中提供的一种容器,可以用来存储多个数据。
集合和数组既然都是容器,它们有什么区别呢?
- 数组的长度是固定的。集合的长度是可变的。
- 数组中存储的是同一类型的元素,可以存储任意类型数据。集合存储的都是引用数据类型。如果想存储基本类型数据需要存储对应的包装类型。
3.1 Collection
常用方法:
方法 | 说明 |
---|---|
public boolean add(E e) | 把给定的对象添加到当前集合中 |
public void clear() | 清空集合中所有的元素 |
public boolean remove(E e) | 把给定的对象在当前集合中删除 |
public boolean contains(Object obj | 判断当前集合中是否包含给定的对象 |
public boolean isEmpty() | 判断当前集合是否为空 |
public int size() | 返回集合中元素的个数 |
public Object[] toArray() | 把集合中的元素,存储到数组中 |
List接口:
有序,可重复,有索引。
特有方法 | 说明 |
---|---|
public void add(int index, E element) | 指定的元素,添加到该集合中的指定位置上 |
public E get(int index) | 返回集合中指定位置的元素 |
public E remove(int index) | 移除列表中指定位置的元素, 返回的是被移除的元素 |
public E set(int index, E element) | 用指定元素替换集合中指定位置的元素,返回值的更新前的元素 |
ArrayList集合:
底层数组结构,元素增删慢,查找快。
方法名 | 说明 |
---|---|
public boolean remove(Object o) | 删除指定的元素,返回删除是否成功 |
public E remove(int index) | 删除指定索引处的元素,返回被删除的元素 |
public E set(int index,E element) | 修改指定索引处的元素,返回被修改的元素 |
public E get(int index) | 返回指定索引处的元素 |
public int size() | 返回集合中的元素的个数 |
public boolean add(E e) | 将指定的元素追加到此集合的末尾 |
public void add(int index,E element) | 在此集合中的指定位置插入指定的元素 |
LinkedList集合:
底层链表结构,增删快,查找慢。
LinkedList常用方法 | 说明 |
---|---|
public void addFirst(E e) | 将指定元素插入此列表的开头 |
public void addLast(E e) | 将指定元素添加到此列表的结尾。 |
public E getFirst() | 返回此列表的第一个元素。 |
public E getLast() | 回此列表的最后一个元素 |
public E removeFirst() | 移除并返回此列表的第一个元素 |
public E removeLast() | 移除并返回此列表的最后一个元素 |
public E pop() | 从此列表所表示的堆栈处弹出一个元素 |
public void push(E e) | 将元素推入此列表所表示的堆栈 |
public boolean isEmpty() | 果列表不包含元素,则返回true。 |
Collections工具类
Collections常用方法 | 说明 |
---|---|
public static void shuffle(List<?> list) | 打乱集合顺序 |
public static void sort(List list) | 集合中元素按照默认规则排序 |
public static void sort(List list,Comparator<? super T> ) | 将集合中元素按照指定规则排序 |
HashSet:
底层哈希表(数组+链表+红黑树),无序,不重复。
TreeSet:
无索引,不重复;使用元素的自然顺序
对元素进行排序,或者根据创建 TreeSet 时提供的 Comparator
比较器进行排序,具体取决于使用的构造方法:
public TreeSet(): 根据其元素的自然排序进行排序
public TreeSet(Comparator<E> comparator): 根据指定的比较器进行排序
3.2 Map集合
- 每个元素由键和值组成,一般通过键找值。
注意:键不可以重复,会覆盖;值可以重复。
-
Map集合不能直接使用迭代器或者foreach进行遍历。但是转成Set之后就可以使用了。
-
HashMap<K,V>:存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
-
LinkedHashMap<K,V>:HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。
-
TreeMap<K,V>:TreeMap集合和Map相比没有特有的功能,底层的数据结构是红黑树;可以对元素的键进行排序,排序方式有两种:自然排序和比较器排序。
Map的常用方法 | 说明 |
---|---|
public V put(K key, V value) | 把指定的键与指定的值添加到Map集合中 |
public V remove(Object key) | 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值 |
public V get(Object key) | 根据指定的键,在Map集合中获取对应的值 |
public Set keySet() | 获取Map集合中所有的键,存储到Set集合中 |
public Set<Map.Entry<K,V>> entrySet() | 获取到Map集合中所有的键值对对象的集合(Set集合) |
public boolean containKey(Object key) | 判断该集合中是否有此键 |
public K getKey() | 获取Entry对象中的键 |
public V getValue() | 获取Entry对象中的值 |
3.3 迭代器和增强for
即Collection集合元素的通用获取方式。在取元素之前先要判断集合中有没有元素,如果有,就把这个元素取出来,继续再判断,如果还有就再取出来。一直把集合中的所有元素全部取出。这种取出方式专业术语称为迭代。
原理:首先通过调用t集合的iterator()方法获得迭代器对象,然后使用hashNext()方法判断集合中是否存在下一个元素,如果存在,则调用next()方法将元素取出,否则说明已到达了集合末尾,停止遍历元素。
常用方法 | 说明 |
---|---|
public E next() | 返回迭代的下一个元素 |
public boolean hasNext() | 如果仍有元素可以迭代,则返回 true |
增强for:用于遍历Collection和数组。通常只进行遍历元素,不要在遍历的过程中对集合元素进行增删操作。
注意:
(1)增强for循环必须有被遍历的目标,目标只能是Collection或者是数组;
(2)增强for(迭代器)仅仅作为遍历操作出现,不能对集合进行增删元素操作,否则抛出ConcurrentModificationException并发修改异常 。
(3)Collection是所有单列集合的根接口,如果要对单列集合进行遍历,通用的遍历方式是迭代器遍历或增强for遍历。
3.4 泛型
- 可以在类或方法中预知地使用未知的类型。
通配符:
泛型的上限:
格式: 类型名称 <? extends 类 > 对象名称
意义: 只能接收该类型及其子类
泛型的下限:
格式: 类型名称 <? super 类 > 对象名称
意义: 只能接收该类型及其父类型
3.5 数据结构
数据存储的常用结构有:栈、队列、数组、链表和红黑树。
3.6 异常
概念:指的是程序在执行过程中,出现的非正常的情况,最终会导致JVM的非正常停止。
Throwable体系 | 说明 |
---|---|
Error | 严重错误Error,无法通过处理的错误,只能事先避免,好比绝症。 |
Exception | 表示异常,异常产生后程序员可以通过代码的方式纠正,使程序继续运行,是必须要处理的。好比感冒、阑尾炎 |
Throwable中的常用方法 | 说明 |
---|---|
public void printStackTrace() | 打印异常的详细信息 |
public String getMessage() | 获取发生异常的原因 |
public String toString() | 获取异常的类型和异常描述信息(不用) |
异常(Exception)的分类:根据在编译时期还是运行时期去检查异常?
-
编译时期异常:checked异常。在编译时期,就会检查,如果没有处理异常,则编译失败。(如日期格式化异常)
-
运行时期异常:runtime异常。在运行时期,检查异常.在编译时期,运行异常不会编译器检测(不报错)。(如数学异常)
异常的处理:
- 抛出异常throw,总要处理。
- 声明异常throws,告诉调用问题,调用者处理。
- 捕获异常try…catch…finally
- 自定义异常。
异常的注意事项:
-
运行时异常被抛出可以不处理。即不捕获也不声明抛出。
-
如果父类的方法抛出了多个异常,子类覆盖(重写)父类方法时,只能抛出相同的异常或者是他的子集。
-
父类方法没有抛出异常,子类覆盖父类该方法时也不可抛出异常。此时子类产生该异常,只能捕获处理,不能声明抛出
-
当多异常分别处理时,捕获处理,前边的类不能是后边类的父类
-
在try/catch后可以追加finally代码块,其中的代码一定会被执行,通常用于资源回收。
四.多线程
- 并行:指两个或多个事件在同一时刻发生(同时执行)。
- 并发:指两个或多个事件在同一个时间段内发生(交替执行)。
- 进程:是指一个内存中运行的应用程序。
- 线程:是进程中的一个执行单元。
4.1 Thread类
常用方法 | 说明 |
---|---|
public String getName() | 获取当前线程名称 |
public void start() | 导致此线程开始执行; Java虚拟机调用此线程的run方法 |
public void run() | 此线程要执行的任务在此处定义代码 |
public static void sleep(long millis) | 使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行) |
public static Thread currentThread() | 返回对当前正在执行的线程对象的引用 |
创建线程的方式:
- 继承Thread类
- 实现Runnable接口
实现Runnable接口比继承Thread类所具有的优势:
- 适合多个相同的程序代码的线程去共享同一个资源。
- 可以避免java中的单继承的局限性。
- 增加程序的健壮性,实现解耦操作,代码可以被多个线程共享,代码和线程独立。
- 线程池只能放入实现Runable或Callable类线程,不能直接放入继承Thread的类。
匿名内部类方式:
方便的实现每个线程执行不同的线程任务操作。
4.2 高并发及线程安全:
-
高并发:是指在某个时间点上,有大量的用户(线程)同时访问同一资源。
-
线程安全:在某个时间点上,当大量用户(线程)访问同一资源时,由于多线程运行机制的原因,可能会导致被访问的资源出现"数据污染"的问题。
-
多线程的安全性问题-可见性/ /有序性/ /原子性。
volatile关键字:
-
使用:修饰"成员变量",它能强制线程每次从主内存获取值,禁止代码重排,并能保证此变量不会被编译器优化。
-
作用:解决变量的可见性,有序性;但不能解决变量的原子性问题。
原子类:
-
AtomicInteger可以保证对“变量”操作的:原子性、有序性、可见性。
-
工作原理:CAS机制;CAS机制也被称为:乐观锁。因为大部分比较的结果为true,就直接修改了。只有少部分多线程并发的情况会导致CAS失败,而再次循环。
synchronized关键字:
表示“同步”的。它可以对“多行代码”进行“同步”——将多行代码当成是一个完整的整体,一个线程如果进入到这个代码块中,会全部执行完毕,执行结束后,其它线程才会执行。这样可以保证这多行的代码作为完整的整体,被一个线程完整的执行完毕。
- 使用:a).同步代码块 b).同步方法【常用】
- 注意:synchronized被称为“重量级的锁”方式,也是“悲观锁”——效率比较低。
Lock锁:
public void lock() :加同步锁
public void unlock():释放同步锁
并发包:
保证线程安全,取代一般集合对象。
线程不安全的 | 线程安全的 |
---|---|
ArrayList | CopyOnWriteArrayList |
HashSet | CopyOnWriteArraySet |
HashMap | ConcurrentHashMap |
4.3 线程池
概念:其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象 的操作,无需反复创建线程而消耗过多资源。
好处:
- 降低资源消耗。减少了创建和销毁线程的次数,每个工作线程都可以被重复利用,可执行多个任 务。
- 提高响应速度。当任务到达时,任务可以不需要的等到线程创建就能立即执行。
- 提高线程的可管理性。可以根据系统的承受能力,调整线程池中工作线线程的数目,防止因为消耗 过多的内存,而把服务器累趴下(每个线程需要大约1MB内存,线程开的越多,消耗的内存也就越 大,最后死机)。
使用:
public static ExecutorService newFixedThreadPool(int nThreads) :返回线程池对象。(创建的是有界线程池,也就是池中的线程个数可以指定最大数量)。
public Future<?> submit(Runnable task) :获取线程池中的某一个线程对象,并执行。
死锁:在多线程程序中,使用了多把锁,造成线程之间相互等待.程序不往下走了。尽量避免。
线程状态:
线程状态 | 导致状态发生条件 |
---|---|
NEW(新建 | 线程刚被创建,但是并未启动。还没调用start方法。MyThread t = new MyThread只有线程对象,没有线程特征。 |
Runnable(可 运行) | 线程可以在java虚拟机中运行的状态,可能正在运行自己代码,也可能没有, 这取决于操作系统处理器。调用了t.start()方法 :就绪(经典教法) |
Blocked(锁阻 塞) | 当一个线程试图获取一个对象锁,而该对象锁被其他的线程持有,则该线程进 入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。 |
Waiting(无限 等待) | 一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状 态。进入这个状态后是不能自动唤醒的,必须等待另一个线程调用notify或者 notifyAll方法才能够唤醒。 |
Timed Waiting(计时 等待) | 同waiting状态,有几个方法有超时参数,调用他们将进入Timed Waiting状 态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常 用方法有Thread.sleep 、Object.wait。 |
Teminated(被 终止) | 因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死 亡 |
等待和唤醒机制:
public void wait() : 让当前线程进入到等待状态 此方法必须锁对象调用.
public void notify() : 唤醒当前锁对象上等待状态的线程 此方法必须锁对象调用.
五.Lambda表达式和Stream流
- 函数式编程思想:强调做什么,而不是以什么形式做。
Lambda表达式
前提条件:
- 使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法。 无论是JDK内置的 Runnable 、 Comparator 接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可 以使用Lambda。
- 使用Lambda必须具有上下文推断。 也就是方法的参数或局部变量类型必须为Lambda对应的接口 类型,才能使用Lambda作为该接口的实例。
标准格式:(参数类型 参数名称) -> { 代码语句 }
Stream流:
方法名 | 方法作用 | 方法种类 | 是否支持链式调用 |
---|---|---|---|
count | 统计个数 | 终结 | 否 |
forEach | 逐一处理 | 终结 | 否 |
filter | 过滤 | 函数拼接 | 是 |
limit | 取用前几个 | 函数拼接 | 是 |
skip | 跳过前几个 | 函数拼接 | 是 |
map | 映射 | 函数拼接 | 是 |
concat | 组合 | 函数拼接 | 是 |
六.IO流
6.1 File类
常用方法 | 说明 |
---|---|
String getAbsolutePath() | 返回此File的绝对路径名字符串。 |
String getPath() | 将此File转换为路径名字符串 |
String getName() | 返回由此File表示的文件或目录的名称。 |
long length() | 返回由此File表示的文件的长度。 不能获取目录的长度。 |
常用判断方法 | 说明 |
---|---|
boolean exists() | 此File表示的文件或目录是否实际存在 |
boolean isDirectory() | 此File表示的是否为目录。 |
boolean isFile() | 此File表示的是否为文件 |
常用删除方法 | 说明 |
---|---|
boolean createNewFile() | 当且仅当具有该名称的文件尚不存在时,创建一个新的空 文件 |
boolean delete() | 删除由此File表示的文件或目录(必须为空才可以) |
boolean mkdir() | 创建由此File表示的目录 |
boolean mkdirs() | 创建由此File表示的目录,包括任何必需但不存在的父目录 |
目录的遍历 | 说明 |
---|---|
File[] listFiles() | 返回一个File数组,表示该File目录中的所有的子文件或目录 |
6.2 IO流分类
根据数据的流向分为:输入流和输出流。
输入流 :把数据从 硬盘 上读取到 内存 中的流。
输出流 :把数据从 内存 中写出到 硬盘 上的流。
根据数据的类型分为:字节流和字符流。
字节流 :以字节为单位,读写数据的流。
InputStream流,OutputStream
字符流 :以字符为单位,读写数据的流
字符输入流 :Reader 字符输出流:Writer
6.3 字节输出流OutputStream
字节输出流共性方法 | 说明 |
---|---|
void close() | 关闭此输出流并释放与此流相关联的任何系统资源 |
void write(byte[] b) | 将 b.length字节从指定的字节数组写入此输出流 |
void write(byte[] b, int off, int len) | 从指定的字节数组写入 len字节,从偏 移量 off开始输出到此输出流 |
FileOutputStream类
构造方法 | 说明 |
---|---|
FileOutputStream(File file) | 创建文件输出流以写入由指定的 File对象表示的文 件 |
FileOutputStream(String name) | 创建文件输出流以指定的名称写入文件 |
**注意:**当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有这个文件,会创建该文件。如果 有这个文件,会清空这个文件的数据。
数据追加续写:
方法 | 说明 |
---|---|
FileOutputStream(File file, boolean append) | 创建文件输出流以写入由指定的 File对象表示的文件 |
FileOutputStream(String name, boolean append) | 创建文件输出流以指定的名称写入文件 |
6.4 字节输入流 InputStream
字节输入流共性方法 | 说明 |
---|---|
void close() | 关闭此输入流并释放与此流相关联的任何系统资源 |
abstract int read() | 从输入流读取数据的下一个字节 |
int read(byte[] b) | 从输入流中读取一些字节数,并将它们存储到字节数组 b中 |
FileInputStream类:
构造方法 | 说明 |
---|---|
FileInputStream(File file) | 通过打开与实际文件的连接来创建一个 FileInputStream ,该 文件由文件系统中的文件对象 file命名 |
FileInputStream(String name) | 通过打开与实际文件的连接来创建一个 FileInputStream , 该文件由文件系统中的路径名 name命名 |
注意:当你创建一个流对象时,必须传入一个文件路径。该路径下,如果没有该文件,会抛出 FileNotFoundException。
读取方法 | 说明 |
---|---|
read(byte[] b) | 每次读取b的长度个字节到数组中,返回读取到的有效字 节个数,读取到末尾时,返回-1 |
6.5 字符输入流 Reader
共性方法 | 说明 |
---|---|
void close() | 关闭此流并释放与此流相关联的任何系统资源 |
int read() | 从输入流读取一个字符 |
int read(char[] cbuf) | 从输入流中读取一些字符,并将它们存储到字符数组 cbuf 中 |
FileReader类:
构造方法 | 说明 |
---|---|
FileReader(File file) | 创建一个新的 FileReader ,给定要读取的File对象 |
FileReader(String fileName) | 创建一个新的 FileReader ,给定要读取的文件的名称 |
注意:当你创建一个流对象时,必须传入一个文件路径。类似于FileInputStream 。
读取字符方法 | 说明 |
---|---|
read() | 每次可以读取一个字符的数据,提升为int类型,读取到文件末尾,返 回-1 ,循环读取 |
read(char[] cbuf) | 每次读取多个字符到数组中,返回读取到的有效字符 个数,读取到末尾时,返回-1 |
6.6 字符输出流 Writer
共性方法 | 说明 |
---|---|
abstract void close() | 关闭此输出流并释放与此流相关联的任何系统资源 |
abstract void flush() | 刷新此输出流并强制任何缓冲的输出字符被写出 |
void write(int c) | 写出一个字符 |
void write(char[] cbuf) | 将 b.length字符从指定的字符数组写出此输出流 |
abstract void write(char[] b, int off, int len) | 从指定的字符数组写出 len 字符,从偏移量 off开始输出到此输出流 |
void write(String str) | 写出一个字符串 |
FileWriter类:
构造方法 | 说明 |
---|---|
FileWriter(File file) | 创建一个新的 FileWriter,给定要读取的File对象 |
FileWriter(String fileName) | 创建一个新的 FileWriter,给定要读取的文件的名称 |
注意:当你创建一个流对象时,必须传入一个文件路径,类似于FileOutputStream。
字符流:只能操作文本文件,不能操作图片,视频等非文本文件。
6.7 Properties类
基本的存储方法 | 说明 |
---|---|
Object setProperty(String key, String value) | 保存一对属性 |
String getProperty(String key) | 使用此属性列表中指定的键搜索属性值 |
Set stringPropertyNames() | 所有键的名称的集合 |
与流相关的方法 | 说明 |
---|---|
void load(InputStream inStream) | 从字节输入流中读取键值对 |
注意:参数中使用了字节输入流,通过流对象,可以关联到某文件上,这样就能够加载文本中的数据了。
6.8 缓冲流
缓冲流,也叫高效流,是对4个基本的 FileXxx 流的增强,所以也是4个流,按照数据类型分类:
- 字节缓冲流: BufferedInputStream , BufferedOutputStream
- 字符缓冲流: BufferedReader , BufferedWriter
字节缓冲流:
构造方法 | 说明 |
---|---|
BufferedInputStream(InputStream in) | 创建一个 新的缓冲输入流 |
BufferedOutputStream(OutputStream out) | 创建一个 新的缓冲输入流 |
字符缓冲流:
构造方法 | 说明 |
---|---|
BufferedReader(Reader in) | 创建一个 新的缓冲输入流 |
BufferedWriter(Writer out) | 创建一个新的缓冲输出流 |
特有方法 | 说明 |
---|---|
String readLine() | 读一行文字 |
void newLine() | 写一行行分隔符,由系统属性定义符号 |
6.9 转换流
InputStreamReader类:
构造方法 | 说明 |
---|---|
InputStreamReader(InputStream in) | 创建一个使用默认字符集的字符流 |
InputStreamReader(InputStream in, String charsetName) | 创建一个指定字符集的字符流 |
OutputStreamWriter类:
构造方法 | 说明 |
---|---|
OutputStreamWriter(OutputStream in) | 创建一个使用默认字符集的字符流 |
OutputStreamWriter(OutputStream in, String charsetName) | 创建一个指定字符集的字符流 |
6.10 打印流
PrintStream类:
public PrintStream(String fileName) : 使用指定的文件名创建一个新的打印流。
例如:PrintStream ps = new PrintStream(“ps.txt”);
七.网络编程
7.1 基本知识点
- 网络通信协议,TCP/IP协议—》总结来说就是通信的规则。
TCP–面向连接的协议;
只能由客户端主动发送数据给服务器端,服务器端接收到数据之后,可以给客户端响应数据。
- 通过三次握手建立连接,连接成功形成数据传输通道。
- 通过四次挥手断开连接
- 基于IO流进行数据传输
- 传输数据大小没有限制
- 因为面向连接的协议,速度慢,但是是可靠的协议。
TCP协议相关的类:
- Socket 一个该类的对象就代表一个客户端程序。
- ServerSocket 一个该类的对象就代表一个服务器端程序。
UDP—面向无连接协议。
- 文件上传和下载
- 邮件发送和接收
- 远程登录
网络编程三要素:协议,IP地址,端口号。
计算机简单dos命令:
查看本机IP地址:ipconfig
检查网络是否连通:
ping 空格 IP地址
ping 220.181.57.216
ping www.baidu.com
7.2 Junit单元测试
Junit是Java语言编写的第三方单元测试框架(工具类) * 类库 ==> junit.jar
单元测试概念
* 单元:在Java中,一个类、一个方法就是一个单元
* 单元测试:程序员编写的一小段代码,用来对某个类中的某个方法进行功能测试或业务逻辑测试。
Junit单元测试框架的作用
* 用来对类中的方法功能进行有目的的测试,以保证程序的正确性和稳定性。
* 能够让方法独立运行起来。
Junit单元测试框架的使用步骤
* 编写业务类,在业务类中编写业务方法。比如增删改查的方法
* 编写测试类,在测试类中编写测试方法,在测试方法中编写测试代码来测试。
* 测试类的命名规范:以Test开头,以业务类类名结尾,使用驼峰命名法
* 每一个单词首字母大写,称为大驼峰命名法,比如类名,接口名...
* 从第二单词开始首字母大写,称为小驼峰命名法,比如方法命名
* 比如业务类类名:ProductDao,那么测试类类名就应该叫:TestProductDao
* 测试方法的命名规则:以test开头,以业务方法名结尾
* 比如业务方法名为:save,那么测试方法名就应该叫:testSave
测试方法注意事项
* 必须是public修饰的,没有返回值,没有参数
* 必须使用JUnit的注解@Test修饰
如何运行测试方法
* 选中方法名 --> 右键 --> Run '测试方法名' 运行选中的测试方法
* 选中测试类类名 --> 右键 --> Run '测试类类名' 运行测试类中所有测试方法
* 选中模块名 --> 右键 --> Run 'All Tests' 运行模块中的所有测试类的所有测试方法
如何查看测试结果
* 绿色:表示测试通过
* 红色:表示测试失败,有问题
Junit常用注解(Junit4.x版本)
* @Before:用来修饰方法,该方法会在每一个测试方法执行之前执行一次。
* @After:用来修饰方法,该方法会在每一个测试方法执行之后执行一次。
* @BeforeClass:用来静态修饰方法,该方法会在所有测试方法之前执行一次,而且只执行一次。
* @AfterClass:用来静态修饰方法,该方法会在所有测试方法之后执行一次,而且只执行一次。
7.3 NIO
同步与异步(synchronous/asynchronous):同步是一种可靠的有序运行机制,当我们进行同步 操作时,后续的任务是等待当前调用返回,才会进行下一步;而异步则相反,其他任务不需要等待当前调用返回,通常依靠事件、回调等机制来实现任务间次序关系 。
阻塞与非阻塞:在进行阻塞操作时,当前线程会处于阻塞状态,无法从事其他任务,只有当条件就 绪才能继续,比如ServerSocket新连接建立完毕,或者数据读取、写入操作完成;而非阻塞则是不管IO操作是否结束,直接返回,相应操作在后台继续处理。
注意:NIO之所以是同步,是因为它的accept/read/write方法的内核I/O操作都会阻塞当前线程 。
NIO的三个重要组成部分:
Buffer(缓冲区):
使用 Buffer 读写数据一般遵循以下四个步骤:
- 写入数据到 Buffer;
- 调用 flip() 方法;
- 从 Buffer 中读取数据;
- 调用 clear() 方法或者 compact() 方法。
当向 Buffer 写入数据时,Buffer 会记录下写了多少数据。一旦要读取数据,需要通过 flip() 方法将 Buffer 从写模式切换到读模式。在读模式下,可以读取之前写入到 Buffer 的所有数据。一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。
Channel(通道):
服务器端:ServerSocketChannel类用于连接的服务器端,它相当于:ServerSocket。
- 调用ServerSocketChannel的静态方法open():打开一个通道,新频道的套接字最初未绑定; 必 须通过其套接字的bind方法将其绑定到特定地址,才能接受连接。
- 调用ServerSocketChannel的实例方法bind(SocketAddress add):绑定本机监听端口,准备接受连接。
客户端:SocketChannel类用于连接的客户端,它相当于:Socket。
- 先调用SocketChannel的open()方法打开通道:
ServerSocketChannel serverChannel = ServerSocketChannel.open()
- 调用SocketChannel的实例方法connect(SocketAddress add)连接服务器:
socket.connect(new InetSocketAddress("localhost", 8888));
Selector(选择器):
Selector被称为:选择器,也被称为:多路复用器,它可以注册到很多个Channel上,监听各个 Channel上发生的事件,并且能够根据事件情况决定Channel读写。这样,通过一个线程管理多个 Channel,就可以处理大量网络连接了。
创建一个Selector:
Selector selector = Selector.open();
注册Channel到Selector :
channel.configureBlocking(false); //设置非阻塞
SelectionKey key =channel.register(selector,SelectionKey.OP_READ);//绑定
register()方法的第二个参数:是一个int值,意思是在通过Selector监听Channel时对什么事件感兴 趣。可以监听四种不同类型的事件,而且可以使用SelectionKey的四个常量表示:
- 连接就绪–常量:SelectionKey.OP_CONNECT
- 接收就绪–常量:SelectionKey.OP_ACCEPT (ServerSocketChannel在注册时只能使用此项) 。
- 读就绪–常量:SelectionKey.OP_READ
- 写就绪–常量:SelectionKey.OP_WRITE
注意:对于ServerSocketChannel在注册时,只能使用OP_ACCEPT,否则抛出异常
- 当一个"通道"注册到选择器Selector后,选择器Selector内部就创建一个SelectionKey对象,里面封 装了这个通道和这个选择器的映射关系。 - 通过SelectionKey的channel()方法,可以获取它内部的通道对象。
八.反射,注解
8.1 反射
-
类加载器::是负责将磁盘上的某个class文件读取到内存并生成Class的对象。
-
获取:“类名.class”,或者"对象.getClass()"方法获取这个Class对象。
-
Java中有三种类加载器,它们分别用于加载不同种类的class:
- 启动类加载器(Bootstrap ClassLoader):用于加载系统类库<JAVA_HOME>\bin目录下的 class,例如:rt.jar。
- 扩展类加载器(Extension ClassLoader):用于加载扩展类库<JAVA_HOME>\lib\ext目录下的 class。
- 应用程序类加载器(Application ClassLoader):用于加载我们自定义类的加载器。
(1)Class对象的三种获取方法
* 方式1: 通过类名.class获得
* 方式2:通过对象名.getClass()方法获得
* 方式3:通过Class类的静态方法获得: static Class forName("类全名")
* 每一个类的Class对象都只有一个。
(2)Class类常用方法
String getSimpleName(); 获得类名字符串:类名
String getName(); 获得类全名:包名+类名
T newInstance() ; 创建Class对象关联类的对象
(3)Class类中与Constructor相关的方法
1. Constructor getConstructor(Class... parameterTypes)
* 根据参数类型获得对应的Constructor对象。
* 只能获得public修饰的构造方法
2. Constructor getDeclaredConstructor(Class... parameterTypes)
* 根据参数类型获得对应的Constructor对象
* 可以是public、protected、(默认)、private修饰符的构造方法。
3. Constructor[] getConstructors()
* 获得类中的所有构造方法对象,只能获得public的
4. Constructor[] getDeclaredConstructors()
* 获得类中的所有构造方法对象
* 可以是public、protected、(默认)、private修饰符的构造方法
注意:成员方法和变量的获取与上述类似。(Method,Field)
(4)Constructor对象常用方法
1. T newInstance(Object... initargs)"——
根据指定的参数创建对象
2. void setAccessible(true)
设置"暴力反射"——是否取消权限检查,true取消权限检查,false表示不取消
8.2 注解
注解(Annotation)相当于一种标记,在程序中加入注解就等于为程序打上某种标记,以后,javac 编译器、开发工具和其他程序可以通过反射来了解你的类及各种元素上有无何种 标记,看你的程 序有什么标记,就去干相应的事,标记可以加在包、类,属性、方法,方法的参数以及局部变量上。
作用:给程序带入参数。
自定义注解:格式-->public @interface 注解名{。。。}
特殊属性value
* 如果注解中只有一个属性且名字叫value,则在使用该注解时可以直接给该属性赋值,而不需要 给出属性名。
* 如果注解中除了value属性之外还有其他属性且只要有一个属性没有默认值,则在给属性赋值时value属性名也不能省略了。
小结:如果注解中只有一个属性时,一般都会将该属性名命名为value
元注解:定义注解的注解。
常用的元注解:
* @Target
* 作用:用来标识注解使用的位置,如果没有使用该注解标识,则自定义的注解可以使用在任意位 置。
* 可使用的值定义在ElementType枚举类中,常用值如下
TYPE,类,接口 FIELD, 成员变量
METHOD, 成员方法 PARAMETER, 方法参数
CONSTRUCTOR, 构造方法 LOCAL_VARIABLE, 局部变量
* @Retention
* 作用:用来标识注解的生命周期(有效范围)
* 可使用的值定义在RetentionPolicy枚举类中,常用值如下
* SOURCE:注解只作用在源码阶段,生成的字节码文件中不存在
* CLASS:注解作用在源码阶段,字节码文件阶段,运行阶段不存在,默认值
* RUNTIME:注解作用在源码阶段,字节码文件阶段,运行阶段
九.XML,Dom4j,单例设计模式,枚举,正则表达式
9.1 XML
作用:XML在企业开发中主要有两种应用场景:
-
XML可以存储数据 , 作为数据交换的载体(使用XML格式进行数据的传输)
-
XML也可以作为配置文件,例如后面框架阶段我们学习的Spring框架的配置 (applicationContext.xml)都是通过XML进行配置的(企业开发中经常使用的)。
常见的xml约束:DTD、Schema。
解析方式和解析器:
- 开发中比较常见的解析方式有三种,如下:
-
DOM:要求解析器把整个XML文档装载到内存,并解析成一个Document对象
a)优点:元素与元素之间保留结构关系,故可以进行增删改查操作。 b)缺点:XML文档过大,可能出现内存溢出。
-
SAX:是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。并以事件驱 动的方式进行具体解析,每执行一行,都触发对应的事件。(了解)
a)优点:处理速度快,可以处理大文件。
b)缺点:只能读,逐行后将释放资源,解析操作繁琐。
-
PULL:Android内置的XML解析方式,类似SAX。(了解)
-
解析器,就是根据不同的解析方式提供具体实现。有的解析器操作过于繁琐,为了方便开发人员, 有提供易于操作的解析开发包。
-
常见的解析开发包
- JAXP:sun公司提供支持DOM和SAX开发包。
- Dom4j:比较简单的的解析开发包(常用)。
- JDom:与Dom4j类似。
- Jsoup:功能强大DOM方式的XML解析开发包,尤其对HTML解析更加方便(项目中讲解)
9.2 单例设计模块
单例模式,是一种常用的软件设计模式。通过单例模式可以保证系统中,应用该模式的这个类只有一个 实例。即一个类只有一个对象实例。
实现步骤:
-
将构造方法私有化,使其不能在类的外部通过new关键字实例化该类对象。
-
在该类内部产生一个唯一的实例化对象,并且将其封装为private static类型的成员变量。
-
定义一个静态方法返回这个唯一对象
类型:
饿汉单例设计模式:饿汉单例设计模式就是使用类的时候已经将对象创建完毕,不管以后会不会使用到该实例化对象,先创 建了再说。很着急的样子,故被称为“饿汉模式”。
懒汉单例设计模式:懒汉单例设计模式就是调用getInstance()方法时实例才被创建,先不急着实例化出对象,等要用的时候 才实例化出对象。不着急,故称为“懒汉模式”。
注意:懒汉单例设计模式在多线程环境下可能会实例化出多个对象,不能保证单例的状态,所以 加上关键字:synchronized,保证其同步安全。
9.3 枚举
作用:一个方法接收的参数是固定范围之内的时候,那么即可使用枚举。
本质:是一个类。
定义格式:
enum 枚举名 {
第一行都是罗列枚举实例,这些枚举实例直接写大写名字即可。(必须第一行)
例如:BOY,GIRL;//男,女
}
应用:枚举通常可以用于做信息的分类,如性别,方向,季度等。
9.4 正则表达式
概念:正则表达式就是用来验证各种字符串的规则。它内部描述了一 些规则,我们可以验证用户输入的字符串是否匹配这个规则。
例:使用正则表达式验证:
public class Demo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入你的QQ号码:");
String qq = sc.next();
System.out.println(checkQQ2(qq));
}
//使用正则表达式验证
private static boolean checkQQ2(String qq){
String regex = "[1-9]\\d{4,14}";//正则表达式
return qq.matches(regex);
}
}