Java语言高级特性
jie
2020-10-10
阻塞解除
导致阻塞事件
关系解析
Java语言高级特性
1.Java多线程编程
2.线程常用操作方法
3.线程的同步与死锁
4.综合实战:“生产者消费者模型
5.多线程深入话题
6.多线程综合案例
7.Java基础类库
8.数字操作类
9.日期操作类
10.正则表达式
11.国际化程序实现
12.开发支持类库
13.比较器
14.类库使用案例分析
15.文件操作
16.字节流与字符流
17.I0操作深入
18.输入与输出支持
19.对象序列化
20.JavalO编程案例
21.认识反射机制
22.反射应用案例
23.反射与类操作
24.反射与简单Java类
25.ClassLoader类加载器
26.反射与代理设计模式
27.反射与Annotation
28.类集框架简介
29.List集合
30.Set集合
31.集合输出
32.Map集合
33.集合工具类
34.Stream数据流
35.网络编程
36.Java数据库编程基础操作
37.Statement数据库操作接口
38.PreparedStatement数据库操作接口
进程与线程
Thread类
实现多线程
Runnable接口
实现多线程
Thread
与
Runnable
关系
Callable接口
实现多线程
多线程运行状态
线程的命名和取得
线程休眠
线程中断
线程强制运行
线程礼让
线程优先级
同步问题引出
线程同步处理
线程死锁
生产者与消费者基本程序模型
解决生产者-消费者同步问题
利用Object类解决重复操作
优雅的停止线程
后台守护线程
volatile关键字
数字加减
生产电脑
竞争抢答
StringBuffer类
CharSequence接口
AutoCloseable接口
Runtime类
System类
Cleaner类
对象克隆
Math数学计算类
Random随机数生成类
大数字处理类
Date日期处理类
SimpleDateFormat类日期处理类
认识正则表达式
常用正则标记
String类对正则的支持
java. util.regex包支持
国际化程序实现原理
Locale类
ResourceBundle读取资源文件
实现国际化程序开发
格式化文本显示
UUID类
Optional类
ThreadLocal类
定时调度
Base64加密与解密
比较器问题引出
Comparable比较器
Comparator比较器
二叉树结构简介
二叉树基础实现
二叉树数据删除
红黑树原理简介
StringBuffer使用
随机数组
Email验证
扔硬币
IP验证
HTML拆分
国家代码
学生信息比较
File类基本操作
File类操作深入
获取文件信息
综合案例:列出目录结构
综合案例:文件批量更名
流的基本概念
OutputStream字节输出流
InputStream字节输入流
Writer字符输出流
Reader字符输入流
字节流与字符流的区别
转换流
综合实战:文件拷贝
字符编码
内存操作流
管道流
RandomAccessFile
打印流
System类对IO的支持
BufferedReader缓冲输入流
Scanner扫描流
对象序列化基本概念
序列化与反序列化处理
transient关键字
数字大小比较
文件保存
字符串逆序显示
数据排序处理
数据排序处理深入
奇偶数统计
用户登录.
投票选举
反射机制简介
Class类对象的三种实例化模式
反射实例化对象
反射与工厂设计模式
反射与单例设计模式
反射获取类结构信息
反射调用构造方法
反射调用普通方法
反射调用成员
Unsafe工具类
传统属性赋值弊端
属性自动赋值实现思路
单级属性赋值
ClassLoader类载器简介
自定义ClassLoader处理类
静态代理设计模式
动态代理设计模式
CGLIB实现代理设计模式
反射取得Annotation信息
自定义Annotation
工厂设计模式与Annotation整合
类集框架简介
Collection接口简介
List接口简介
ArrayList子类
ArrayList保存自定义类对象
LinkedList子类
Vector子类
Set接口简介
HashSet子类
TreeSet子类
分析TreeSet子类排序操作
分析重复元素消除
Iterator迭代输出
ListIterator双向迭代输出
Enumeration枚举输出
foreach输出
Map接口简介
HashMap子类
LinkedHashMap子类
Hashtable子类
Map.Entry内部接口
利用Iterator输出Map集合
自定义Map的key类型
Stack栈操作
Queue队列
Properties属性操作
Collections工具类
Stream基本操作
MapReduce基础模型
网络编程简介
Echo程序模型
BIO处理模型
UDP程序
JDBC简介
连接Oracle数据库
Statement接口简介
Statement实现数据更新
Statement实现数据查询
Statement问题分析
PreparedStatement接口简介
使用PreparedStatement实现数据查询操作
进程
线程
传统的DOS中如果出现病毒, 所有程序将无法执行, 因为用的是单进程处理
后来Windows的时代开启了多进程的设计, 所有进程轮流抢占执行, 但同一时间
点只会有一个进程执行
线程是在进程的基础上创建的, 依赖于进程,但
线程启动速度比进程快很多
Java是多线程的编程语言,所以Java在进行并发访问处理时可以得到更高的处理性
能
需要有一个线程的主体类来实现多线程的定义,该定义必须要实现特定的接口或继
承特定的类
Java中有java.lang.Thread程序类,一个类只要继承了此类就表示这个类为线程的
主体类
实现
继承Thread类
覆写Thread类中的run()方法
(这个就是线程的主方法)
用Thread类中的start()方法调用run()
, 要实现多线程不能直接调用run()方法, 因为
这里涉及到系统调用的问题
例
;
new MyThread("线程A").start();
如果是new MyThread("线程A").run(); 则会按顺序执行
执行顺序是交替的, 不可控的
注意
每个线程类的对象值允许启动一次, 如果重复启动则抛出异
常"java.lang.
illegalThreadStateException
"
Thread的执行分析
在
开发中对于多线程的实现, 优先考虑Runnable接口实现
, 然后通过Thread类对象
启动多线程
例 :
由于只是实现了Runnable接口对象, 此时线程主体类
没有单继承的局限
, 这样的设
计才是一个标准型设计
Runnable接口使用了函数式接口定义, 所以也可以直接利用Lambda表达式进行线
程类定义
public
Thread
(
Runnable
target)
Runnable有一个缺点 : 线程执行完后没有返回值(run()方法没有返回值), JDK1.5后
就提出了一个新的线程实现接口 : java.util.concurrent.Callable 接口
Callable定义时可设置一个泛型
所有多线程的实现都要通过Thread类中的start()方法
Thread接收Runnable对象
面试题 : Runnable于Callable的区别
Runnable是在JDK1.0时提出的接口, Callable时在1.5后提出的
java.lang.Runnable接口中值提供一个run()方法, 没有返回值
java.util.concurrent.Callable接口提供有call()方法, 可以有返回值
例 :
创建
public class
Thread
extends Object implements
Runnable
Thread 是Runnable的子类
多线程设计中使用了代理设计模式, 用户自定义的线程主体只是负责项目核心功能
的实现, 而所有的辅助功能全交由Thread处理
通过Thread类实现Runnable接口对象时, 该接口对象会被Thread中的target属性保
存 :
在start()方法执行时会调用Thread中的run()方法, 而这个run()方法会调用
Runnable接口子类覆写过的run()方法
start()
就绪状态
← 调度 →
运行状态
终止
阻塞状态
构造方法
public
Thread
(
Runnable
target,
String name)
设置名字
取得名字
public final String
getName
()
public final void
setName
(String name)
如果没有设置则会自动生成一个不重复的名字"Thread-编号"
关系
FutureTask
(
Callable
<V> callable)
FutureTask类接收Callable对象, Callable有个call()方法, Future(FutureTask的实
现接口)的get()返回call()方法返回值
Thread和FutureTask都是Runnable的子类
public interface
RunnableFuture
<V>
extends
Runnable
,
Future
<V>
Future
<V>里有个
get()
方法
//
由get()获得Callable对象里call()的返回值
public class
FutureTask
<V>
extends Object
implements
RunnableFuture
<V>
简化 : FucturetTask接收到Callable,再传递到Thread里实现调用
可以这样记 :
Thread接收的参数都是Runnable接口的子类对象
返回正在执行的线程对象
public static
Thread
currentThread
()
例 : Thread.
currentThread
().getName() 返回当前线程名字
发现主方法是个名字为"main"的线程
说明
java命令执行程序启动时就启动了一个JVM进程, 一台电脑可以同时启动多个JVM
进程
任何开发中, 主线程可以创建若干个子线程, 创建子线程的目的是为了将一些复杂比
较耗时的逻辑交由子线程处理
public static void
sleep
(long millis) throws InterruptedException
public static void
sleep
(long millis, int nanos) throws InterruptedException
millis(毫秒)
中断异常 "InterruptedException"必须被处理
特点 : 定时自动实现线程的唤醒
多个线程对象休眠是有轮流的, 并不是同步的
public boolean isInterrupted()
检测线程是否被中断
public void interrupt()
中断线程执行
例 :
让某一个线程可以独占资源, 一直执行, 直到结束
public final void
join
(long millis) throws InterruptedException
超时设为0,或不填,表示永远等待
例 :
public static void yield()
每一次调用yield()方法都只会礼让一次当前的资源
线程的优先级越高越有可能先执行(越有可能先抢占资源)
public final void setPriority(int newPriority)
priority(优先)
public final int getPriority()
参数 : MAX_PRIORITY(10), NORM_PRIORITY(5), MIN_PRIORITY(1)
主方法和默认创建的线程都是中等优先级
例 :
Runnable描述多个线程的操作资源, 而Thread描述每一个线程对象, 多个线程访问
同一资源时处理不当会产生数据的错误操作
例 :
解决同步问题的关键时锁, 即当某一线程正在执行时其他线程外面等待
同步代码块
synchronized(同步对象){
同步代码操作 ;
}
例 :
注意 : 同步实际上会造成性能的下降
同步方法
两种方案
例 : public synchronized void 方法名(){ }
系统中许多同步处理用的都是同步方法
死锁指的是若干个线程彼此互相等待的状态
例 :
public final void
wait
() throws InterruptedException
等待线程,直到被notified(唤醒)或interrupted
public final void wait(long timeoutMillis) throws InterruptedException
public final void wait(long timeoutMillis, int nanos) throws
InterruptedException
等待线程
设置等待时间
唤醒
public final void
notify
()
唤醒第一个等待线程, 其他的继续等待
public final void
notifyAll
()
唤醒所有等待线程, 线程优先级高级有可能先执行
例 :
设计更改某一属性就能让线程退出, 或其他方式, 让线程运行完毕, 而不是强制停止
主线的程序或其他的线程还在执行时, 守护线程将一直存在, 并且运行在后台状态,
如果用户线程结束, 守护线程也将结束, JVM里最大的守护线程就是GC线程
public final void
setDaemon
(boolean on)
public final boolean
isDaemon
()
设置守护线程
判断是否时守护线程
在属性定义上使用,
表示此属性为直接数据操作, 而不进行副本的拷贝
(不要将其错误
地理解为同步属性) ,
正常变量处理步骤 : 获取变量原有数据内容→
利用副本为变量
进行数学计算→将计
算后的变量保存到原始空间之中
作用 : 更快地进行变量修改处理
append()
insert()
public StringBuffer
delete
(int start, int end)
删除指定范围数据
public StringBuffer
replace
(int start, int end, String str)
替换指定范围字符串
public StringBuffer
reverse
()
字符串内容反转, StringBuffer的最大特征
调用wait()的方法需是synchronized的, 用super.wait()或wait()
例
面试题 : String, StringBuffer, StringBuilder类最大区别
String类是字符串的首选类型, 最大特点是内容不允许修改
StringBuffer与StringBuilder类的内容允许修改
StringBuffer是在JDK1.0的时候提供,属于线程安全的操作, 而StringBuidler是
JDK1.5后提供的,属于非线程安全操作
描述字符串结构的接口, String, StringBuffer和StringBuffer都实现了该接口
方法
char
charAt
(int index)
CharSequence
subSequence
(int start, int end)
int
length
()
获取字符串长度
获取指定索引字符串
截取字符串
实现资源的自动关闭, 释放资源
JDK1.7后提供的, 只有提供有一个方法
void
close
() throws Exception
描述的是运行时的状态, 是唯一一个与JVM运行状态有关的类,并且默认提供有一个
实例化对象
每一个JVM进程里只允许提供有一个Rnutime对象(单列设计模式)
public static Runtime
getRuntime
()
获取Runtime实例化对象
public static void
arraycopy
(Object src, int srcPos, Object dest, int destPos,
int length)
public int
availableProcessors
()
获取本机中的CPU内核数
例 :
内核数决定了最佳并发访问量
public long
maxMemory
()
返回最大可用内存空间, 默认配置为本机系统内存的1/4
public long
freeMemory
()
返回可用空闲内存空间, 默认配置为本机系统内存的1/64
public long
totalMemory
()
返回全部可用内存空间
public void
gc
()
手工GC处理
面试题 :
GC(Garbage Collector)垃圾收集器, 可以由系统自动调用的垃圾释放功能 或由
Runtime类中的GC()手工调用
public static long
currentTimeMillis
()
数组拷贝
返回当前时间戳, 可用于计时
public static void gc()
进行垃圾回收(这个gc()是调用了Runtime类中的gc操作:
Runtime.getRuntime().gc() ;)
JDK1.9之后提供的一个对象清理操作, 替代之前的finalize()方法(对象回收前的收尾
操作)
JDK1.9之后建议使用AutoCloseable()或者使用java.lang.ref.Cleaner类进行回收处
理(Cleaner类也支持AutoCloseable处理)
例 :
新版本的对象回收前的处理通常单独通过一个线程完成,以防止由可能造成的延迟处
理, 以提高进程的整体执行性能
指对象的复制, 创建一个新的对象
protected Object
clone
() throws CloneNotSupportedException
被克隆的对象要求实现Cloneable接口(该接口描述的是"能力", 没有方法,是一个表
示接口)
例 :
实际开发中很少会用到对象克隆需求
public final class
Math
extends Object
Math提供有很多计算的基础公式,具体看JavaDoc
自定义一个四舍五入功能
public int
nextInt
(int bound)
返回一个int类型随机数,bound: 上限
例 :
超过double范围的数字处理
BigInteger类
BigDecimal类
public BigInteger
add
(BigInteger val)
加法
public BigInteger
subtract
(BigInteger val)
相减
public BigInteger
multiply
(BigInteger val)
相乘
public BigInteger
divide
(BigInteger val)
相除
......
例 :
大数字的计算过程是很缓慢的
public BigInteger[]
sqrtAndRemainder
()
求余除法, 返回第一个是商, 二是余数
public BigInteger[]
divideAndRemainder
(BigInteger val)
开根
小数计算, BigInteger是整数计算, 注意这个涉及到进位问题
......
将long(时间戳)转为日期
public
Date
(long date)
public long
getTime
()
将日期转为时间戳
例 : System.out.println(
new Date().getTime()
);
S例 : ystem.out.println(new
Date
(1594566383));
对日期显示格式进行格式化处理
public final String
format
(Date date)
构造方法 : public
SimpleDateFormat
(String pattern)
public
Date
parse
(String source) throws ParseException
将日期格式化
将字符串转为日期,parse(解析)
--日期格式: 年(yyyy), 月(MM), 日(dd), 时(HH),分(mm), 秒(ss), 毫秒(SSS)
其他看JavaDoc
例 :
设置日期格式
字符串格式为设置的日期格式
如定义格式时时间日期超过合理范围, 则会自动进行进位处理
其他 : 数字也可格式化, NumberFomat类
JDK1.4后正则已经默认被JDK支持
特点 : 方便进行
验证处理
, 以及
复杂字符串的修改处理
java.util.regex(regular expression)包里的Pattern类定义有所有支持的正则标记
字符匹配(单个)
任意字符
\\ : 表示"\"
\n : 匹配换行
\t : 匹配制表符
字符集(单个)
可以从里面任选一个
[abc] : 表示可能是a, b, c中的任意一个
[^abc] : 表示没有有a,b,c中的任意一个
[a-zA-Z] : 表示有一个字母组成, 不区分大小写
[0-9] : 表示由一位数字组成
单个数量
. : 表示任意一个字符
\d : 表示一个数字, 等价于[0-9]
\D : 表不是一个数字, 等价于[^0-9]
\s : 匹配任意一个空格, 可以是换行符, 制表符
\w : 匹配任意字母, 数字, 下划线,等价于[a-zA-Z_0-9]
\W : 匹配非字母,数字, 下划线
^ : 匹配边界开始
边界匹配
$ : 匹配边界结束
数量表示
默认情况下只有添加了数量单位才可以匹配多位字符
表达式? : 该正则可以出现0次或1次
表达式* : 该正则可以出现0次, 1次或多次
表达式+ : 该正则可以出现1次或多次
表达式{n} : 表达式长度为n
表达式{n,} : 表达式长度为n个次以上
表达式{n, m} : 表达式长度n~m次
逻辑表达式
可以连接多个正则
XY : 表达式X紧跟表达式Y,
X|Y : 有一个表达式满足即可
(X) : 为表达式X设置整体描述, 可以为整数描述设置数量单位
public boolean
matches
(String regex)
matcher类 : public boolean
matches
()
例 : str.
matches
("[abc]")
大部分正则操作用的都是String类
将指定字符串进行正则判断
public String
replaceAll
(String regex, String replacement)
public String
replaceFirst
(String regex, String replacement)
public String[]
split
(String regex, int limit)
public String[]
split
(String regex)
替换全部
替换第一个
正则拆分指定个数
正则拆分
简单例 :
验证邮箱格式 :
这个包定义有两个类 : Pattern(正则表达式编译), Matcher(匹配)
public static Pattern
compile
(String regex)
将正则表达式编译成pattern
public String[]
split
(CharSequence input)
也提供字符串拆分, 但是String类的正则拆分更方便
public Matcher
matcher
(CharSequence input)
如果只是拆分, 替换, 匹配三种操作, 只用String类就可以实现了
Pattern类提供的方法, 获得Matcher类对象
Pattern类
Matcher类
public String
replaceAll
(String replacement)
字符串替换
public boolean
matches
()
正则匹配
String类不具备的功能
分组, 例 :
专门描述区域和语言的类
public
Locale
(String language)
构造方法
public
Locale
(String language,
String country)
public
Locale
(String language,
String country,
String variant)
中文 : zh_CN, 美国 : en_US
public static Locale
getDefault
()
获取默认语言环境
Locale.CHINA ;
常量, 方便使用
例 :
public abstract class
ResourceBundle
extends Object
是一个抽象类
public static final ResourceBundle
getBundle
(String baseName)
获取ResourceBundle类对象
baseName : 描述的是资源文件的名称,但是没有后缀
根据key读取资源内容
public final String
getString
(String key)
属性文件 : *.properties
以key = values格式存储文件
一般这个文件作为一些参数的存储, 有利于以后的代码重构,维护
用于适应多语言环境,随着系统的语言环境的变化,读取不同的属性文件,显示对
应语言的UI
例 : info=jerrys
读取时key一定要存在, 否则会出现以下异常
java.util.
MissingResourceException
读取顺序 : 指定区域的资源文件>默认的本地资源>公共资源(没有区域设置)
Message_zh_CN.properties
Message_en_US.properties
指定国家的区域资源文件
baseName是"Message"时,会读取系统默认区域的文件(根据文件名末尾区域代码)
可用Locale修改当前Locale环境
例 :
例 :
Message.properties
公共资源
info=欢迎{0}, date : {1}
有需要可以继续添加{2},{3}...
要将占位符的信息读取出来, 要利用MessageFormat类进行格式化处理
public static String
format
(String pattern, Object... arguments)
例 :
Object... arguments用逗号分隔, 依次对应{0}, {1}, {2} ...
开发中看到资源文件有"{0}", "{1}"的结构表示的都是占位符, 该信息一定要进行格式
化处理
universally unique identifier(通用唯一标识符), 生成无重复字符串的程序类
public static UUID
randomUUID
()
获取UUID对象, 返回的是UUID类型, 一般用toString()输出字符串类型
public static UUID
fromString
(String name)
根据字符串获取UUID内容
对一些文件自定命名处理的情况下, UUID非常好用
主要进行null的处理
public static <T> Optional<T>
empty
()
返回空的数据
public T
get
()
获取数据
public static <T> Optional<T>
of
(T value)
保存数据, 不允许出现空
如果保存数据时存在空,会抛出"NullPointerException"
public static <T> Optional<T>
ofNullable
(T value)
保存数据, 允许为空
public T
orElse
(T other)
空的时候返回其他数据
解决核心资源与多线程并发访问的情况
public
ThreadLocal
()
构造方法, 创建一个新的对象
public T
get
()
设置数据
public void
set
(T value)
取出数据
public void
remove
()
删除数据
例 :
每一个线程通过ThreadLocal只允许保存一个数据
进行定时任务的处理, 这种任务处理只实现了一种间隔触发的操作
需要一个定时操作的主体类, 以及一个定时任务的控制
public abstract class
TimerTask
extends Object
implements Runnable
public class
Timer
extends Object
设置定时任务处理
进行任务的启动, 启动的方法
public void
schedule
(TimerTask task, long delay)
任务启动, delay : 延迟(毫秒)
public void
scheduleAtFixedRate
(TimerTask task, long delay, long period)
间隔触发, period: 间隔时间(毫秒)
Base64.Decoder类
Base64.Encoder类
进行解密处理
进行加密处理, Encoder(编码器)
public byte[]
encode
(byte[] src)
public byte[]
decode
(byte[] src)
由于这是一个公版的算法, 直接对数据加密并不安全, 可使用盐值操作, 并且多次加
密。最好把盐值也给加密了, 同时使用几种加密程序, 找到一种不可解密的加密算法
例 :
public static Base64.Encoder
getEncoder
()
public static Base64.Decoder
getDecoder
()
Base64类
例 :
进行大小关系的确定判断,
使用java.util.Arrays的操作类完成, 这个类里提供有对象数组的排序支持
public static void
sort
(Object[] a)
例 :
int
compareTo
(T o)
public interface
Comparable
<T>
o: 要比较的对象 ; return: 当前数据比对象小返回负数, 大于则返回整数, 等于返回0
例 :
实现了comparable的类可以实现排序, 有对象数组的排序需求就用comparable
定义排序规则
程序开发时没考虑对象数组的排序, 后面需要排序对象又不能修改类时使用,
Comparator是一种挽救排序规则, 尽可能用comparable,不用comparator
public interface
Comparator
<T>
int
compare
(T o1, T o2)
例 :
与Comparable区别
java.lang.Comparable 主要用于定义排序规则, 只有一个compareTo()方法
java.util.Comparator 是挽救的比较操作, 需要定义单独的比较器规则类实现排序,
里面有compare()方法
以尽可能减少检索次数为出发点进行设计, 进行数据检索时要进行每个节点的判断,
但它的判断时区分左右的, 那么它的时间复杂度时O(logn)
原理 : 取第一个数据为保存的根节点, 取小于等于根节点的数据放在节点的左子树,
而大于节点的数据放在节点的右子树
数据获取有三种形式
前序遍历(根-左-右)
中序遍历(左-根-右)
后续遍历(右-根-左)
思路
创建BinaryTree<T>类 继承 Comparable<T>类(用于比较数据)
创建内部类Node(Comparable<T> data), 定义有父接点Node parent, 右子树
Node right, 左子树
创建功能实现方法,add(E data)为例
在Node类里创建addNode(Node newNode)方法用于保存节点在合适位置
如果待删除节点没有子节点,那么直接删掉即可;
如果待删除节点只有一一个子节点,那么直接删掉,并用其子节点去顶替它
如果待删除节点有两个子节点,这种情况比较复杂: 首选找出它的后继节点,然后处
理“后继节点”和"被删除节点的父节点”之间的关系,最后处理“后继节点的子节
点”和 "被删除节点的子节点”之间的关系。
要达到良好的查询效果的二叉数应该是个平衡二叉树, 同时所有节点的层次深度应
该相同
红黑树本质上是一种二叉查找树,但它在二叉查找树的基础上额外
添加了一个标记(颜色) , 同时具有一定的规则。这些规则使红黑
树保证了一种平衡,插入、删除、查找的最坏时间复杂度都为
O(logn)。
public class
File
extends Object
implements Serializable,
Comparable
<File>
public
File
(String pathname)
构造方法
public
File
(String parent,
String child)
设置父路径与目录
public boolean
createNewFile
() throws IOException
创建新文件
public boolean
exists
()
判断文件是否存在
public boolean
delete
()
删除文件
Window分隔符 "\" , Linux分隔符 "/"
提供
separator
分隔符常量解决此问题
new File("D:"+File.
separator
+"textFile.txt")
new File("D:\\textFile.txt")
例 :
分隔符问题
但是随着系统的发展, 现在分隔符"\", "/" 也通用了
程序 → JVM → 操作系统函数 → 文件处理
注意 :
在进行同一文件复制删除或创建的时候可能会右延迟的问题的时候, 所以最好的方
案是别重名
文件操作时文件的父路径必须存在
获取文件父路径
public File
getParentFile
()
public boolean
mkdirs
()
创建多级目录
这样反复判断会影响一点性能, 最好是保证目录存在, 少做判断
例 :
public boolean
canRead
()
public boolean
canWrite
()
判断文件是否可读
判断文件是否可写
public long
length
()
返回文件大小(字节长度)
public long
lastModified
()
返回最后一次日期时间(时间戳)
public boolean
isFile
()
判断是否是文件
public boolean
isDirectory
()
判断是否是路径
public File[]
listFiles
()
列出目录内容, 返回Filie对象数组
例 :
例 :
例 :
更改目录下所有文件后缀名, 包括子目录
数据流指的是字节数据(二进制数据)
流的分类
字节处理流
OutputStream, InputStream
字符处理流
Writer, Reader
流操作步骤(以文件处理为例)
1.通过File类找到一个文件路径
2.通过字节流或字符流的子类为父类对象实例化
3.利用字节流或字符流中的方法实现数据的输入与输出操作
4.流的操作属于资源操作, 必须进行关闭处理
public
abstract
class
OutputStream
extends Object
implements
Closeable
,
Flushable
public void
write
(byte[] b) throws IOException
输出一组字节数据
public abstract void
write
(int b) throws IOException
输出单个字节数据
public void
write
(byte[] b, int off, int len) throws IOException
输出部分数据(off: 开始点, len: 长度)
方法
public class
FileOutputStream
extends OutputStream
OutputStream属于抽象类, 需要通过子类向上转型获得实例
构造方法
public
FileOutputStream
(File file)
throws FileNotFoundException
public
FileOutputStream
(File file, boolean append)
throws FileNotFoundException
覆盖
追加
例 :
public
FileInputStream
(File file)
throws FileNotFoundException
public
abstract
class
InputStream
extends Object
implements
Closeable
方法
public abstract int
read
() throws IOException
读取当个字节数据 , 如果读取到底返回-1
public int
read
(byte[] b) throws IOException
读取一组字节数据,保存在字节数组b中, 并返回读取的个数, 读取到底则返回-1
public int
read
(byte[] b, int off, int len) throws IOException
读取部分数据(off: 开始点, len: 长度)
public byte[] readAllBytes() throws IOException
可以直接读取所有字节数据, 但是如果读取文件过大不能用
例 :
public void
write
(char[] cbuf) throws IOException
输出字符数组
public void
write
(String str) throws IOException
输出字符串
方法
public
abstract
class
Writer
extends Object
implements
Appendable
,
Closeable
,
Flushable
public class
FileWriter
extends OutputStreamWriter
public class OutputStreamWriter
extends
Writer
例 :
public
abstract
class
Reader
extends Object
implements
Readable
,
Closeable
方法
public int
read
(char[] cbuf) throws IOException
public abstract int
read
(char[] cbuf, int off, int len) throws IOException
public class
FileReader
extends InputStreamReader
public class InputStreamReader
extends
Reader
public int
read
() throws IOException
返回单个字符
读取字符数组保存到cbuf, 并且返回字符数组长度
读取部分字符数组(off: 开始点, len: 长度)
例 :
使用OutputStream和Writer时 最后都使用了close()方法
OutputStream没有用close()方法关闭输出流, 依然可以实现正常的输出, Writer不
行, 因为Writer使用了缓冲区
Close()方法会强制刷新缓存区, 想在不关闭的情况下输出全部内容, 可以使用
flush()
方法强制清空缓存区
字节流没有使用缓冲区, 字符流使用了缓冲区, 使用缓冲区的
字符流更适合中文数据
的处理
指实现字节流与字符流的功能转换
java.io包里提供右两个类
InputStreamReader
OutputStreamWriter
public class
OutputStreamWriter
extends
Writer
public class
InputStreamReader
extends
Reader
构造方法
public
OutputStreamWriter
(OutputStream out)
构造方法
public InputStreamReader(InputStream in)
例
: Writer writer = new OutputStreamWriter(out)
接收到的字节流对象通过向上转型变成字节流对象
字节流转字符流的继承结构
例 :
上例是最原始的拷贝实现, 而从JDK1.9开始InputStream和Reader类追加了数据转
存的处理方法
transferTo()
, 该方法性能更高
public long
transferTo
(Writer out) throws IOException
InputStream:
public long
transferTo
(OutputStream out) throws IOException
Reader:
TransferTo() 例 :
最终代码(包括目录拷贝)
该程序是IO的基础核心, 要理解
常用编码
GBK/GB2312
国标编码, 可以描述中文信息, GB2312只有简体, GBK有简,繁
ISO8859-1
国际通用编码, 可以描述所有字母信息, 如果是象形文字则需要进行编码处理
UNICODE编码
采用十六进制的方式存储, 可以描述所有文字信息
UTF编码
象形文字部分使用十六进制编码, 普通字母采用ISO8859-1编码, 适合快速传输, 节
约带宽, UTF-8是我们
开发中的首选编码
前面使用的都是文件操作流, 现在要进行IO操作, 又不希望产生文件(临时文件), 就以
内存为终端进行处理
字节内存操作流
字符内存操作流
public class
ByteArrayOutputStream
extends OutputStream
public class
ByteArrayInputStream
extends InputStream
public class
CharArrayWriter
extends Writer
public class
CharArrayReader
extends Reader
构造方法
构造方法
public
ByteArrayInputStream
(byte[] buf)
public
ByteArrayOutputStream
()
public byte[]
toByteArray
()
获取数据
例 :
实现两个线程之间的IO处理操作
OutputStream
Writer
连接()
InputStream
Reader
发送消息线程对象
(Runnable)
← 管道 →
接收消息线程对象
(Runnable)
字节管道流
字符管道流
public class
PipedInputStream
extends InputStream
public class
PipedOutputStream
extends OutputStream
public void
connect
(PipedInputStream snk) throws IOException
连接处理
public void
connect
(PipedWriter src) throws IOException
public class
PipedReader
extends Reader
public class
PipedWriter
extends Writer
public void
connect
(PipedReader snk) throws IOException
public void
connect
(PipedOutputStream src) throws IOException
例 :
public class
RandomAccessFile
extends Object
implements DataOutput, DataInput, Closeable
可以由用户定义读取的位置, 数据可以按照固定的长度进行保存
根据实例化对象反推出其类型
"正"
1.导入程序需要的包
2.通过类产生实例化对象
3.根据对象调用类中的方法
"反"
1.获取Class类信息(根据实例化信息)
public final Class<?>
getClass
()
public final class
Class<T>
extends Object
implements Serializable, GenericDeclaration, Type, AnnotatedElement,
TypeDescriptor.OfField<Class<?>>, Constable
构造方法
public
RandomAccessFile
(File file, String mode)
throws FileNotFoundException
mode: 读写状态, "r", "rw, "rws", "rwd"
public int
skipBytes
(int n) throws IOException
public void
write
(byte[] b, int off, int len) throws IOException
跳过第n个字节开始操作
public void
seek
(long pos) throws IOException
回到第n个字节开始读取(设置指针偏移量)
例 :
public int
read
(byte[] b, int off, int len) throws IOException
从第off个字节开始写入len字节(覆写原位置内容)
......
标准输出(显示器)
public static final
PrintStream
out
错误输出
标准输入(键盘)
public static final
InputStream
in
public static final
PrintStream
err
System.out和System.err都是统一种类型, 在Eclipse中System.err会输出红色字体
可以修改输出位置
public static void
setOut
(PrintStream out)
public static void
setErr
(PrintStream err)
可以输出到文件里, 但一般不这么做, 没什么用
例 :
缺陷: 如果长度不足, 只能接收部分内容, 一般情况不这样输入
提供的是一个缓存字符输入流的概念, 可以
利用这个类实现键盘输入数据的标准化
定义
public String
readLine
() throws IOException
读取一行数据
public class
BufferedReader
extends Reader
例 :
java.util.Scanner, JDK1.5之后追加的类, 目的为了解决输入流的访问问题, 比
BufferReader方便点
实际开发中输入的一般是字符串
public
Scanner
(InputStream source)
构造 :
public boolean
hasNext
()
判断是否有数据
public String
next()
取出数据
public Scanner
useDelimiter
(String pattern)
设置分隔符
例 :
Scanner最大特点是可以进行正则验证
public boolean
hasNext
(String pattern)
例 :
程序需要输出数据使用打印流, 输入数据使用Scanner(首选)或BufferReader
OutputStream输出功能有限: public void write(byte[] b) throws IOException,
开发中往往自定义一些功能类
打印流实现 例 :
设计思想 : 提高已有类的功能, 即"装饰设计模式"
在java.io包里提供有打印流: PrintStream(字节流), PrintWriter(字符流)
public class
PrintWriter
extends Writer
public class
PrintStream
extends
FilterOutputStream
implements Appendable, Closeable
构造方法
public
PrintStream
(OutputStream out)
......
构造方法
public
PrintWriter
(OutputStream out)
......
public
PrintWriter
(Writer out)
public PrintWriter
printf
(String format, Object... args)
格式化输出
例 :
只要是进行内容输出, 全部使用打印流
指将内存中保存的对象以二进制数据流的形式进行处理, 可以实现对象的保存或网
络传输
堆内存中对象经二进制转换保存位置
文件中
服务器
数据库里(SQL)
Java中强制性要求
要序列化的对象要实现java.io.
Serializable
父接口, 作为序列化的标记(这个接口没
有方法, 只是描述了这个类的能力)
public class
ObjectOutputStream
extends OutputStream
implements ObjectOutput, ObjectStreamConstants
序列化
public class
ObjectInputStream
extends InputStream
implements ObjectInput, ObjectStreamConstants
反序列化
public
ObjectInputStream
(InputStream in) throws IOException
构造方法
构造方法
public
ObjectOutputStream
(OutputStream out) throws IOException
public final void
writeObject
(Object obj) throws IOException
public final Object
readObject
() throws IOException,
ClassNotFoundException
Java中的对象序列化处理必须使用内部提供的对象操作流, 因为牵扯到对象的二进
制处理。实际开发中很少能见到
ObjectOutputStream, ObjectInputStream
的
直接使用, 会有其他容器帮助完成
例 :
类中有一些属性不需要序列化处理, 可以使用transient关键字
private transient String name ;
在进行序列化的时候那么属性的内容不会被保存下来
由于开发中大部分被序列化的类往往都是简单的java类, 所以这一关键字出现的频率
不高
Class类
Object类
public final Class<?>
getClass
()
例 :
JVM支持 "类.class" 形式实例化
第一种
第二种
例 :
public static Class<?>
forName
(String className)
throws ClassNotFoundException
通过类名称(字符串) 获得类对象, 并且不需要import语句
第三种
Class<? extends Person> cls = per.
getClass
() ;
Class<? extends Person> cls =
Person.class
;
例 :
Class<?> cls = Class.
forName
("cn.exercise.test.Person");
获取Class对象之后最大的意义不是在于对象的实例化操作形式, 更重要的是Class类
里提供有对象的反射实例化方法(代替了关键字new)
JDK1.9以前的实例化
@Deprecated(since="9") public T
newInstance
() throws
InstantiationException, IllegalAccessException
JDK1.9之后
public Constructor<?>[]
getDeclaredConstructors
() throws
SecurityException
例 :
实例化对象 关键字new 与 反射的选择
简单工厂设计模式
例 :
这种属于静态工厂设计模式, 每追加一个子类工厂就要追加判断
工厂设计模式要解决的是子类与客户端的耦合问题, 该例子中Factory要进行修改,
实际开发中要求Factory满足所有子类的修改
解决方案 : 不使用关键字 new, 因为new使用的时候要有一个明确的类存在,
newInstance()方法只需要一个表示类名称的字符串即可应用
例 :
小数高精度计算
public T
newInstance
(Object... initargs) throws InstantiationException,
IllegalAccessException, IllegalArgumentException,
InvocationTargetException
java.lang.reflect.Executable.
Construtor
<T>类
利用反射机制实现的工厂设计模式, 对于接口子类的扩充不会影响到工厂类
只有一个接口
例 :
有多个接口
先从简单的看起容易理解
上述例子中如果要定义其他接口, Factory还是要修改, 解决方案 : 用泛型 (客户端即
主方法要知道要使用的接口和方法名称)
例 :
这样的工厂设计模式才是真正实用的
单例设计模式本质在于 : 类内部的构造方法私有化, 在类的内部产生实例化对象后通
过static方法获取实例化对象进行类中的结构调用(本次只谈论懒汉式)
没考虑多线程的 例 :
单例设计最大特点是在运行过程中只允许产生一个实例化对象, 但是在使用多线程
时可以实例化多个, 此时就不是单例设计模式了
解决方案 : 进行同步处理, 在getInstance()方法加Synchronized可以解决, 但是这
样的效率太低, 实际上只有instance实例化对象部分需要同步处理
并发编程的3个基本概念
原子性
定义 : 即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打
断,要么就都不执行。
可见性
定义:指当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程
能够立即看得到修改的值。
有序性
定义:即程序执行的顺序按照代码的先后顺序执行。
锁的两种主要特性
(1)互斥即一次只允许一个线程持有某个特定的锁,一次就只有一个线程能够使
用该共享数据。
(2)可见性要更加复杂一些,
当一条线程修改了共享变量的值,新值对于其他线
程来说是可以立即得知的。
可见性(visibility)
互斥(mutual exclusion)
要使 volatile 变量提供理想的线程安全,必须同时满足下面两个条件:
a.对变量的写操作不依赖于当前值。
b.该变量没有包含在具有其他变量的不变式中。
???
例 :
面试题
编写一个饿汉式的单例设计模式, 并实现构造方法私有化
在Java中那里使用了单例设计模式 : Runntime类 ; Spring框架
懒汉式单例设计模式的问题
标准单例设计模式
获取类的基本信息(父类, 父接口)
类名.class, class.forName(), getClass()区别
其他
子主题
1.
类名.class
说明: JVM将使用类装载器, 将类装入内存(前提是:类还没有装
入内存),不做类的初始化工作.返回Class的对象
2.
Class.forName("类名字符串")
(注:类名字符串是包名+类名) 说明:装入
类,并做类的静态初始化,返回Class的对象
3.
实例对象.getClass()
说明:对类进行静态初始化、非静态初始化;返回引用运
行时真正所指的对象(因为:子对象的引用可能会赋给父对象的引用变量中)所属的类
的Class的对象
Class类
public Package
getPackage
()
获取指定类的包定义
public String
getName
()
获得包名称
public Class<? super T>
getSuperclass
()
获得父类信息
public Class<?>[]
getInterfaces
()
获取实现接口
.......
获取一个Class类后可以获取这个类的一切继承结构信息
例 :
Class类
public Constructor<?>[]
getDeclaredConstructors
()
throws SecurityException
public Constructor<T>
getDeclaredConstructor
(Class<?>...
parameterTypes throws NoSuchMethodException, SecurityException
获取所有构造方法
获取指定构造方法, 要用Class定义参数类型, (包括public和非public)
建议反射的类中最好有无参构造, 因为这样的实例化可以达到统一性
例 :
通过反射获取类中的全部方法, 前提条件是类中要提供实例化对象
Class类
public Method[]
getMethods
()
throws SecurityException
获取全部方法(包括父类的方法)
例 :
public Method
getDeclaredMethod
(
String name, Class<?>...
parameterTypes)
throws NoSuchMethodException, SecurityException
获取指定的方法(包括父类), 权限包括public和非public
public Method
getMethod
(
String name, Class<?>... parameterTypes
)
throws NoSuchMethodException, SecurityException
获取本类指定方法(权限是public的)
public Method[]
getDeclaredMethods
()
throws SecurityException
获取本类全部方法
public Object invoke(Object obj, Object... args) throws
IllegalAccessException, IllegalArgumentException,
InvocationTargetException
Method类
不导入指定类开发包的情况下实现属性配置
例 :
这里的输出是通过Method的toString方法完成的
public Class<?>
getReturnType
()
Executable类
public abstract int
getModifiers
()
返回修饰符的整形类型, 可通过Modifier.toString(int param)转字符串
自定义方法信息输出
例 :
了解可以根据反射获取方法结构即可, 与开发关联不大
例 :
没有明确的类对象产生, 都是通过反射机制处理的, 避免了与某一个类的耦合问题
Class类
public Field
getDeclaredField(String name)
throws NoSuchFieldException,
SecurityException
public Field[]
getDeclaredFields
() throws SecurityException
获取全部成员属性
获取指定成员属性
public Field
getField
(String name) throws NoSuchFieldException,
SecurityException
获取指定父类成员属性
public Field[]
getFields()
throws SecurityException
获取全部父类成员属性
例 :
但是Field类里最重要的操作形式不是获取全部成员, 而是以下几个
Field类
public void
set(Object obj, Object value)
throws IllegalArgumentException,
IllegalAccessException
设置属性内容
public Object
get(Object obj)
throws IllegalArgumentException,
IllegalAccessException
获取属性内容,
public void
setAccessible(boolean flag)
解除封装, 虽然允许, 但是不建议去解除
public Class<?> getType()
获取成员类型, 开发中最常用的方法
开发中进行反射处理的时候, 往往会利用Field, Method类实现setter方法的调用
public Constructor<T>
getConstructor
(Class<?>... parameterTypes)
throws NoSuchMethodException, SecurityException
获取指定构造方法, 只返回制定参数类型访问权限是public的构造器。
例 :
特点 : 可以用反射类获取对象, 并且直接使用底层的C++来代替JVM执行(即绕过
JVM的对象管理机制, 无法使用JVM的内存管理机制以及垃圾回收机制)
不建议使用
sun.msic.Unsafe, 找不到这个包.......
设置多种数据类型
级联对象实例化
级联属性赋值
简单java类有过多的setter, getter方法, 代码存在有大量的重复操作
解决方案 : 反射机制, 可以根据自身特点实现相同功能类(Object类的直接操作, 可直
接操作属性和方法)的重复操作的抽象处理
属性自动设置解决方案 :
采用字符串 : "属性: 内容|属性: 内容"
类的基本结构 : 由一个专门的ClassInstanceFactory类负责所有的反射处理, 接收反
射对象于要设置的属性内容, 同时可以获取指定类的实例化对象
设计的基本结构:
需要通过反射进行指定类对象的实例化处理 ; 进行内容的设置(Field属性类型、方
法名称, 要设置的内容)
例 :
应该使用"."作为级联关系的处理
例(难点) :
实现自动实例化类(包括它的级联对象) 和设置属性
JVM里面可以根据类加载器, 而后进行指定路径中的类加载(JVM提供的环境变量
CLASSPASH)
public ClassLoader
getClassLoader
()
获得类加载器
public final ClassLoader
getParent
()
Class类
ClassLoder类
获取其父类的ClassLoder
AppClassLoader
应用程序加载器
PlatformClassLoader
平台类加载器, JDK1.8及以前为扩展类加载器
ExtClassLoad(JDK1.8及以前)
开发包里有ext文件夹, 可以将"*.jar"文件拷贝到目录里面, 可以直接执行。
但是这样并不安全, 所以从JDK1.9开始将其废除了,同时为了保证系统类加载器和
应用类加载器的平衡, 提供平台类加载器
Bootstrap
系统类加载器
类加载器
获得了类加载器后可以利用类加载器来实现类的反射加载类处理
自定义的类加载器执行顺序是在所有系统类加载器最后
作用 :可以由开发者任意指派类加载位置,( 系统类加载器都是由CLASSPATH定
义的), 类文件从磁盘加载, 也可以通过网络进行加载(最终都是用字节数组来加载)
protected final Class<?>
defineClass
(String name, byte[] b, int off, int len)
throws ClassFormatError
将字节数据转换为要实例化的类对象
类集就是一套动态对象数组的实现方案
重要的两个结构
困难
数据结构的代码实现困难
对于链表或二叉树更新处理的时候维护麻烦
对于链表或二叉树要尽可能保证其操作性能
链表 与 树
因为以上原因, JDK1.2开始引入了类集, 对常见的数据结构进行完整的实现包装. 并
且提供了一系列接口与实现子类来减少困难
几个核心接口
Collection, List, Set, Map, Iterator, Enumeration, Queue
java.util.Collection是单值集合操作的最大父接口
方法
boolean add(E e)
增加单个数据
boolean
addAll(Collection<? extends E> c)
增加一组数据
void
clear()
清空集合, 让根节点为空 , 同时执行GC处理
boolean
contains(Object o)
查询数据是否存在, 需要equals()方法支持
boolean
remove(Object o)
数据删除, 需要wquals()方法支持
int
size()
获取数据长度
Object[] t
oArray()
将集合变成对象数组返回
Iterator<E> iterator()
将集合变为Iterator接口返回(数据输出)
子接口
List<E>
Set<E>
允许重复
不允许重复
public interface
List<E>
extends Collection<E>
方法
E
get(int index)
获取指定索引上的数据
E
set(int index, E element)
修改指定索引对象的数据
ListIterator<E>
listIterator()
返回ListIterator接口对象
List本身依然属于一个接口, 接口要想使用则一定要使用子类来完成定义
三个常用子类
ArrayList
LinkedList
Vector
大部分情况首选(90%)
......
JDK1.9开始List子接口里面追加有一些static方法, 以方便用户的处理
观察List中的静态方法
static <E> List<E>
of
(E... elements)
例 :
因为是JDK1.9后开始提供的, 不兼容以前的版本, 开发的时候一般都用传统方法
public class
ArrayList<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
例 :
保存的顺序就是其存储顺序
List集合里面允许存在重复数据
这个例子 集合的输出是利用每一个类提供的toString()方法实现的,
public void
forEach(Consumer<? super E> action)
为了方便进行输出处理, 在JDK1.8之后Iterable父接口定义有一个forEach()进行输
出(不是标准输出)
ArrayList操作封装的是一个数组
例 :
构造
public ArrayList()
public ArrayList(int initialCapacity)
public ArrayList(Collection<? extends E> c)
initial(初始), capacity(容量)
JDK1.9之后 ArrayList默认的构造指挥使用默认的空数组, 使用的时候才会开辟数组,
默认的开辟长度为10
JDK1.9之前 ArrayList默认的构造实际上就会默认开辟大小为10的数组
实例化ArrayList类对象的时候如果没有传递初始化的长度, 默认使用空数据, 如果增
加的时候容量不够了, 使用较大的数值(成倍的方式)进行新的数组开辟
所以如果数据量超过10个, 使用有参构造方法进行创建, 以避免垃圾数组的空间产生
保存自定义对象时如果需要用到contains(), remove()方法进行查询与删除的时候
一定要保证类已经成功覆写了equals()方法
例 :
双亲加载机制 : 如果自定义类加载器与系统类同名, 则为了保证系统的安全性不会加
载
代理设计模式是开发中使用最多的, 核心是有真实业务实现类与代理业务实现类, 代
理实现类要完成比真实业务实现类有更多的操作
传统代理设计模式弊端
例 :
标准代理设计(基础模式)
调用要知道接口, 代理类和业务类,
客户端的接口与子类产生了耦合问题, 实际开发时最好引入工厂设计模式进行代理
对象的获取
静态代理设计, 一个代理类只为一个接口服务
为所有功能一致的业务操作接口提供有统一的代理处理操作
InvocationHandler接口
public Object
invoke(Object proxy, Method method, Object[] args)
代理方法调用, 代理主题类里面执行的方法最终都是此方法
参数 :
Proxy类
public static Object
newProxyInstance(ClassLoader loader, Class<?>[]
interfaces, InvocationHandler h)
创建代理对象
参数 :
loader : 当前主体类ClassLoader ; interfaces : 真实主体类的接口信息 ;
h : 代理处理的方法
proxy 要代理的对象 ; method 要执行的接口方法名称 ; args 传递的参数
例 :
一些开发者认为不应该强迫性的基于接口实现代理设计模式, 所以开发者就开发出
了CGLIB开发包(第三方程序包)来实现类的代理设计
看教程使用并不比官方的代理设计方便......由空对比下优缺点
建议还是用接口设计比较合理
java.lang.reflect.
AccessibleObject类
public Annotation[]
getAnnotations()
获取全部Annotation信息
public <T extends Annotation> T
getAnnotation(Class<T>
annotationClass)
获取指定Annotation信息
例 :
不同的Annotation有它的不同存在范围
@FunctionalInterface
@SuppressWarnings
源码里有@Retention(RetentionPolicy.RUNTIME),
RetentionPolicy.RUNTIME
: 即运行时生效, 程序运行时可以获取此Annotation
@Retention(RetentionPolicy.SOURCE)
RetentionPolicy.SOURCE
: 源代码编写时有效
@Retention
RetentionPolicy.class : 类定义时有效
RetentionPolicy.RUNTIME : 即运行时生效,
RetentionPolicy.SOURCE : 源代码编写时有效
描述Annotation的运行策略, Retention policy(保留策略)
使用"@interface"来定义Annotation
例 :
自定义Annotation最大特点是可以结合放射机制实现程序的处理
public class
LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, Serializable
继承关系
LinkedList
AbstractSequentialList {abstract}
List<E> <<interface>>
Deque<E> <<interface>>
队列
Queue<E> <<interface>>
双端队列
AbstractList<E> {abstract}
AbstractCollection<E> {abstract}
Collection<E> <<interface>>
Iterable<E> <<interface>>
例 :
这块操作只看功能跟ArrayList是一样的, 但实现机制是完全不同的
跟ArrayList区别
LinkedList构造方法里面没有像ArrayList那样初始化大小的方法, 只提供无参构造
LinkedList是链表实现的集合操作, ArrayList是数组实现的集合操作
使用get()方法根据索引获取数据时, ArrayList的时间复杂度为O(1), LinkedList为
O(n), n是集合的长度
ArrayList如果长度不足会以2倍的长度增加, 保存大数据量的时候会产生垃圾数组及
性能的下降, 这时可以用LinkedList来保存
Vector [ˈvektər] 矢量, 向量
public class
Vector<E>
extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, Serializable
继承结构与ArrayList相同
Vector无参构造会开辟长度为10的数组, 其余操作与ArrayList是相同的
Vector类中的操作方法采用的都是synchronized的同步处理, 在多线程访问的时候
属于线程安全的, 但性能不如ArrayList高
与ArrayList区别
Set集合最大特点是不允许保存重复元素
JDK1.9以前Set集合与Collection集合的定义并无差别, Set继续使用了Collection
定义的方法
JDK1.9之后, Set集合也像List集合一样扩充了一写static方法
public interface
Set<E>
extends Collection<E>
没有像List集合扩充了许多的新方法, 无法使用List集合中的get()方法, 无法实现指
定索引数据的获取
两个常用子类
HashSet, TreeSet
Set接口里使用最多的子类, 最大的特点是保存的数据是无序的, 且不允许保存重复
的元素(Set接口定义的)
public class
HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, Serializable
与HashSet最大的区别是TreeSet集合的数据是有序的(升序)
例 :
public class
TreeSet<E>
extends AbstractSet<E>
implements NavigableSet<E>, Cloneable, Serializable
继承结构
TreeSet<E>
NavigableSet<E> <<interface>>
SortedSet<E> <<interface>>
Set<E> <<interface>>
......
允许使用自定义类进行排序, 但是这个类必须实现Comparable接口, 只有实现这个
接口才能确认对象的大小关系
TreeSet本质是利用TreeMap子类实现集合数据的存储, 而TreeMap需根据
Comparable确定大小关系
例 :
TreeSet需要将类中所有信息进行比对, 实现难度大, 开发中首选HashSet子类进行
存储
HashSet判断重复元素用的是Object类提供的方法hashCode()和equals(),
只有在需要排序的情况下(TreeSet)才会利用Comparable接口来实现
public int hashCode()
对象编码, 编码作用: 快速定位信息。
public boolean equals(Object obj)
对象比较
先进行编码匹配, 如果编码不存在, 则对象不存在, 如果编码存在, 则进一步进
行对象比较处理, 如果发现对象存在了,此数据不允许保存
开发工具可以生成hashCode()和equals()方法
例 :
JDK1.8开始在Iterable接口之中提供的forEach()方法并不是标准的集合输出形式,
并且也很难在实际的开发中出现
概述
用得最多的
非常少用
用得比较多
比较少用
Collection接口从JDK1.5开始多继承了一个Iterable父接口, 这个接口的iterator()方
法可以获取Iterator接口对象(JDK1.5前这个方法是定义在Collection中的)
Iterator<T>
iterator
()
boolean
hasNext
()
获取Iterator接口对象
判断是否有数据
E
next
()
取出当前数据
default void remove()
删除(不是必须不要使用, Iterator是输出类)
方法
在迭代过程中如果使用Collection中的remove()方法删除会出现并发更新的异常
此时就只能利用Iterator中的remove()方法删除
Collection.remove()与Iteration.remove()区别
Iterator迭代输出只能向后输出, 如果需要双向迭代输出则要使用Iterator的子类
ListIterator实现
public interface ListIterator<E> extends Iterator<E>
方法
boolean
hasPrevious
()
判断是否有前一个元素
E
previous
()
由后向前取出数据
例 :
public interface
Enumeration
<E>
方法
boolean
hasMoreElements
()
E
nextElement
()
判断是否由下一个元素
获取当前元素
例 :
对Vector进行输出
该方法时间比较久远, 有些方法只能用Enumeration, 现在大多数都能使用Iterator
输出了
例 :
在Collection保存的数据是单个对象, 实际上可以进行二元偶对象(key:value)的形
式存储, 其核心意义在于需要通过key获取对应的value
开发中Collection集合保存数据的目的是为了输出, Map集合保存数据的目的是为
了进行key的查找
概述
Map接口是二元偶对象保存的最大父接口
public interface
Map
<K,V>
方法
V
put
(K key, V value)
向集合中保存数据
V
get
(Object key)
根据key查询数据
Set<Map.Entry<K,V>>
entrySet
()
将Map转为Set集合
boolean
containsKey
(Object key)
查询指定key是否存在
Set<K>
keySet
()
将Map集合中的key转为Set集合
V
remove
(Object key)
根据key删除掉指定数据
key是不允许重复的
, 在Map中数据的保存按照key = value的形式存储的, 使用of()
操作的时候如果重复会出现"IllegalArgumentException"异常
key值
key值不能为null
, 否则会出现"NullPointerException"异常
例 :
Map接口中最为常见的一个子类, 该类的主要特点是无序存储
public class
HashMap
<K,V> extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
public V
put
(K key, V value)
向集合中保存数据, 返回值 : 重复key时返回旧的value
方法
public V
get
(Object key)
获取集合数据
HashMap的put()方法是如何实现容量扩充的
HashMap类里面提供有一个"DEFAULT_INITIAL_CAPACITY"常量, 默认值16
当保存的内容超过了阈值(DEFAULT_LOAD_FACTOR = 0.75f), 相当与"容量 * 阈
值" = 12, 保存12个元素的时候就会进行容量的扩充
进行扩充的时候HashMap采用的是成倍的扩增模式
HashMap的工作原理
JDK1.8后开始的, 在HashMap中进行数据存储的依然是利用了Node类完成的, 这
种情况下能使用的结构只有链表(时间复杂度"O(n)")和 二叉树("O(logn)")
JDK1.8开始, HashMap的实现发生了改变, 因为要适合大数据时代的大量数据存储
如果保存的数据没有超过阈值(TREEIFY_THRESHOLD = 8), 会按照链表的形式进行
存储, 如果超过了阈值则会将链表转为红黑数以实现树的平衡, 并且利用左旋与右旋
保证数据的查询性能
如果要Map集合中保存的数据为其添加顺序, 可以更换为子类LinkedHashMap(基
于链表实现的), 使用LinkedHashMap类时数据量不要特别大, 会造成时间复杂度攀
升
public class
LinkedHashMap
<K,V> extends HashMap<K,V> implements
Map<K,V>
例 :
操作方法与HashMap类似
public class
Hashtable
<K,V> extends Dictionary<K,V>
implements Map<K,V>, Cloneable, Serializable
例 :
Hashtable设置的key和value都不允许为null
HashMap与Hashtable的区别
HashMap中的方法都属于异步操作(非线程安全, HashMap允许保存null数据)
Hashtable中的方法都属于同步方法(线程安全), Hashtable不允许保存null, 否则会
出现NullPointerException
HashMap源码里 :
static class Node<K,V> implements
Map.Entry<K,V>
public static interface
Map.Entry<K,V>
方法
V getValue()
K getKey()
获取value
获取key
JDK1.9之后Map中追加了一个新的方法
static <K,V> Map.Entry<K,V> entry(K k, V v)
创建Map.Entry对象
作用 : 作为key和value的包装类型使用, 默认数据存储时会将key和value包装为一
个Map.Entry对象使用
例 :
Set<Map.Entry<K,V>>
entrySet
()
将Map集合转为Set集合, 返回一组Map.Entry接口对象(包装key和value)
Set<Map.Entry<K,V>> entrySet()
例 :
将Map集合转为Set集合, 返回一组Map.Entry接口对象(包装key和value)
过程
用Map接口中的entrySet()方法将Map集合转为Set集合
用Set集合中的Iterator()方法将Set集合转为Iterator集合
用Iterator迭代输出每一个Map.Entry对象, 可用getKey()和getValue()方法获取key
和value
要覆写hashCode()和equals()方法, 否则无法查找到key
注意
实际开发中key常用数据类型 String, Long, Integer
HashMap进行数据操作时出现Hash冲突(Hash码相同), HashMap是如何解决的
为了保证程序的正常执行, 会在冲突的位置上将所有Hash冲突的内容转为链表保存
因为根据key获取数据的时候要将传入的key通过hash()方法来获取对应的hash码,
即要先用hashCode()来进行数据查询
例 :
栈是一种先进后出的数据结构
方法
public class
Stack<E>
extends Vector<E>
虽然继承了Vector, 但用的不是Vector提供的方法
public boolean empty()
判断栈是否为空
public E push(E item)
推入元素
public E peek()
peek(窥视), 查看栈顶的元素
public E pop()
抛出栈顶元素(删除), 如果栈已经空了, 会抛出"EmptyStackException"异常
例 :
队列的特点是先进先出的操作形式
public interface
Queue
<E> extends Collection<E>
方法
boolean
add
(E e)
boolean offer(E e)
E poll()
E
element
()
E
peek
()
向队列中追加数据
弹出后(返回值)删除(先进的)数据
向队列中提供数据(添加)
返回首个元素
查看首个元素
子类 :
LinkedList
PriorityQueue
例 :
优先级队列(有排序)
例 :
根据功能要求选择使用
public class
Properties
extends Hashtable<Object,Object>
方法
public Object
setProperty
(String key, String value)
设置属性
public String
getProperty
(String key)
获取属性, 如果key不存在返回null
public String
getProperty
(String key, String defaultValue)
获取属性, 如果key不存在返回默认值
public void
store
(OutputStream out, String comments) throws IOException
输出属性内容
public void
load
(InputStream inStream) throws IOException
通过输入流读取属性内容
Properties可以像Map一样进行数据操作, 区别是Properties只能操作String类型
Properties类可以进行输入流和输出流输出读取属性,
例 :
Collections是一组集合数据操作工具类
方法
public static <T> boolean
addAll
(Collection<? super T> c, T... elements)
public static void
reverse
(List<?> list)
追加数据
实现数据反转
......
例:
public static <T> int
binarySearch
(List<? extends Comparable<? super
T>> list, T key)
二分查找
Collection与Collections区别
Collection是集合接口, 允许保存单值对象
Collecttions是集合操作工具类
default Stream<E>
stream
()
获取Stream接口对象
Collection接口
方法
Stream<T>
filter
(Predicate<? super T> predicate)
Stream<T>
limit
(long maxSize)
设置取出的最大的数据量
Stream<T>
skip
(long n)
跳过指定数据量
Predicate: 断言型的函数式接口
例 :
分两部分 : Map处理部分, Reduce分析部分
例 :
这些分析操作只是JDK本身提供的支持, 而实际中不会这样, 因为面对大数据的环境,
不能将所有数据都保存在内存里面
两种模型
C/S(Client/Server)
, 客户端与服务器端, 这种开发可以由开发者自定义传输协议,
并且使用一些比较私密的端口, 安全性比较高, 但是开发与维护成倍较高
B/S(Browse/Server
, 浏览器与服务器端) : 只开发一套服务器端程序, 浏览器作为
客户端, 这种开发维护成倍较低(只有一套程序), 但使用的是公共的HTTP协议和80端
口,安全性较差, 现在的开发基本上以"B/S"结构为主
C/S程序模型
TCP(可靠的数据连接)
UDP(不可靠的数据连接)
TCP程序基本实现
核心特点使用两个类实现数据的交互处理 : ServerSocket(服务器端), Socket(客户
端)
ServerSocket
主要目的是设置服务器的监听端口
Socket
要指明要连接的服务器地址与端口
telnet指令
open localhost 端口
进行服务器端的连接
检查是服务器端还是客户端出错
例 :
服务器端
客户端
服务器上启动多个线程, 每个线程单独为一个客户端实现Echo服务支持
服务器是单线程, , 占用着的端口其他程序不能用了, 只能提供一个Echo服务
例
服务器端
客户端
基于datagram(数据报)的网络编程实现, 数据报客户端是否接收与发送者无关
两个类
DatagramPacket
DatagramSocket
数据内容
网络的发送与接收
例 :
服务端
客户端
Java Database Connectivity(Java数据库连接)
java.sql模块
DriverManager类
一些接口 : Connection, Statement, PreparedStatement, ResultSet
对数据库访问几种形式
JDBC-ODBC桥连接
利用微软的ODBC技术进行数据库的连接, 而后再利用JDBC技术访问ODBC技术进
行数据库的开发, Java默认支持的技术, 不需要任何额外配置就可实现
处理流程: 程序 → JDBC → ODBC → 数据库
性能很差, 没有人用
JDBC连接
程序 → JDBC → 数据库
这种连接一般只连接本地数据库
JDBC网络连接
通过特点的网络协议连接指定的数据库服务
程序 → JDBC → 网络数据库(IP地址, 端口号)
JDBC的协议连接
自己编写指定的协议操作实现数据库的访问
Oracle驱动配置
使用记事本编写的话用Oracle文件路径配置到CLASSPATH中
用Eclipse开发, 要在JavaBuilderPath上配置驱动程序
步骤
通过反射机制加载数据库驱动程序类
oracle.jdbc.driver.OracleDriver
地址结构
jdbc:oracle:thin:@主机名称:端口号:SID
用户名 :
密码 :
java.sql.DriverManager类
获取Connection接口对象
public static Connection
getConnection(String url, String user, String
password)
throws SQLException
例 :
加载properties文件的5种方式
一类是先获得文件输入流, 再通过Properties的load(InputStream inStream)方法
加载到Properties对象中,最后通过Properties对象来操作文件内容
第二种是通过ResourceBundle类来加载Properties文件,然后ResourceBundle对
象来操做properties文件内容
注意 : 文件的路径需要按照方法的定义的格式来加载
注意
对于文本文件一般使用字符流, 对于非文本文件使用字节流
操作数据单位
数据的流向
输入流, 输出流
流的角色
节点流, 处理流
流的体系结构
抽象基类
Writer, Reader
OutputStream, InputStream
节点流(文件流)
FileInputStream, FileOutputStream
FileReader, FileWriter
处理流(缓冲流)
BufferedInputStream, BufferOutputStream
BufferedWriter, BufferedReader
其他
通信要素
IP和端口号
网络通信协议
TCP/IP参考模型(或协议)
应用层, 传输层, 网络层, 物理+数据链路层
IP和端口号
InetAddress的实例化
IP的理解
Java中用InetAddress表示IP
IP分类
IPv4, IPv6
Internet上的计算机的唯一标识(通信实体)
万维网, 局域网
public static InetAddress
getByName
(String host) throws
UnknownHostException
public String getHostName()
返回域名
public String getHostAddress()
返回ip地址
端口号
公认端口 : 0~1023
被预先定义的服务器通信占用, 如HTTP占用80
注册端口 : 1024~49151
分配给用户进程或应用程序, 如Mysql占用3306
动态/私有端口 : 49152~65535
端口号与IP地址组合得出一个网络套接字 : Socket
TCP/IP
发送文件
URL编程
构成 : 协议://主机名:端口号/资源地址
体现反射的动态性(运行时才做的事)
Created With
MindMaster