JavaSE基础知识笔记(下)

一.java.io.File——该类的每一个实例用于表示一个文件或目录。实际表示的是一个抽象路径.
1.构造方法
public File(string pathname) 根据文件路径创建文件对象
public File(string parent,string child) 根据父路径名字符串和子路径名字符串创建文件对象
public File(File parent,string child) 根据父路径对应文件对象和子路径名字符串创建文件对象
2.常用方法
public boolean isDirectory() 判断此路径名表示的File是否为文件夹
public boolean isFile() 判断此路径名表示的File是否为文件
public boolean exists() 判断此路径名表示的File是否存在
public long length() 返回文件的大小(字节数量) 细节:这个方法只能获取文件的大小,单位是字节
public String getName() 返回文件的名称,带后缀
public boolean createNewFile() 创建一个新的空的文件 细节:如果要创建的文件所在的目录不存
在,该方法会抛出异常。
public boolean mkdir()/mkdirs() 创建单/多级文件夹
public boolean delete() 删除文件、空文件夹 细节:只有File表示的是一个空目录时才可以被删
除!!
public boolean isHidden() 是否为隐藏的
public boolean canRead() 是否可读
public boolean canWrite() 是否可写
public File[] listFiles(FilenameFilter filter) 返回抽象路径名数组,这些路径名表示此抽象路径名表示
的目录中满足指定过滤器的文件和目录。
当调用者File表示的路径不存在时,返回null,当调用者File表示的路径是文件时,返回null,当调用者
File表示的路径是一个空文件夹时,返回一个长度为0的数组,当调用者File表示的路径是一个有内容的
文件夹时,将里面所有文件和文件夹的路径放在File数组中返回,当调用者File表示的路径是一个有隐
藏文件的文件夹时,将里面所有文件和文件夹的路径放在File数组中返回包含隐藏文件,当调用者File
表示的路径是需要权限才能访问的文件夹时,返回null
public static File[] listRoots() 列出可用的文件系统根
public String[] list(FilenameFilter filter) 利用文件名过滤器获取当前该路径下所有内容
二.io:input和output 输入(读,获取信息,是对于计算机的)与输出(写,发送信息)
java将输入和输出用"流strean"表达,分为输入流与输出流,我们可以将它们想象为连接我们的程序与一
个设备之间的"管道",通过它们可以读写设备
JAVA IO将流按照读写单位划分为字节流与字符流
字节流的超类:java.io.InputStream和java.io.OutputStream 字节流是以字节为单位读写数据的流
字符流的超类:java.io.Reader和java.io.Writer 字符流是以字符为单位读写数据的流
注:这两组超类是平级关系,互相不存在继承

1.字节流——文件流(低级流)
java.io.FileInputStream和FileOutputStream,文件流继承自Inputstream和0utputstream.
功能:是用于连接文件的"管道",可以对文件进行读写的流。
①文件输出流四个构造器 close();//流用完了要关闭
FileOutputStream(String filename)
FileOutputStream(File file)
文件流创建时如果指定的文件不存在会自动创建出来,前提是该文件所在的目录必须存在,否会会抛出异
常地出的异常与FiLe创建文件时相同情况抛出的异常一致,以上两种构造器创建文件流时,如果指定
的文件已经存在了,会先将该文件内容 清除。之后通过当前流写出的所有内容会被重写写入到文件
中。小知识:File与FileOutputstream都一样,在指定相对路径时,如果"./“不写,默认就表示当前目录
即:”./fos.dat"等价于"fos.dat"
FileOutputStream(String filename,boolean append)
FileOutputStream(File file,boolean append)
如果创建文件流时append的值为true,则当前文件流为追加模式:
如果指定的文件已经存在,原数据全保留,新写入的内容都会陆续追加到文件末尾
②相关方法
void write(int d) 一次写一个字节数据,通过该输出流向目标位置写出1个字节,写出的是给定的int值
对应的2进制的"低八位"
当我们利用文件输出流写操作时: fos.write(1), 向文件fos.dat中写入1个字节. int值1的2进制样
子:00000000 00000000 00000000 00000001 写后面这些
void write(byte[] data) 一次性将给定的字节数组中所有字节写出
void write(byte[] data,int offset,int len) 一次性将给定的字节数组data从下标offset处开始的连续
Len个字节写出
③书写时换行
windows: \r\n linux:\n Mac:\r
细节:在windows操作系统当中,java对回车换行进行了优化虽然完整的是\r\n,但是我们写其中一个\r或
者\n,java也可以实现换行,因为java在底层会补全。
建议:不要省略,还是写全了。
④文件输入流两个构造方法
FileInputStream(String filename)
FileInputStream(File file)
上述两种构造器创建文件输入流时,如果参数表达的是一个文件则可以正常实例化若表达的文件不存
在,则会直接抛出异常:FileNotFoundException
例如: FileInputStream fis = new FileInputStream(“./fos.123”);//当fos.123不存在时
java.io.FileNotFoundException: .\fos.123 (系统找不到指定的文件。)
FileInputStream fis = new FileInputStream(“.”);//当表达的是一个目录时

java.io.FileNotFoundException: . (拒绝访问。)
⑤相关方法
int read() 读取1个字节,并以int形式返回。返回的int值对应的2进制中只有"低八位"是有效的(读取到
的字节) ,高24为全部补0。如果该方法返回的int值为整数-1(32位2进制都是1)时,则表达流读取到了
末尾。写不了-1(因为写入的是后八位11111111 然后读的时候补0,读出就是255)
int read(byte[] data):一次性读取给定的字节数组data总长度的字节量,并存入到该数组中。返回值
表达实际读取到了多少个字节。如果返回值为-1则表达流读取到了末尾。
⑥编码和解码
String类中的方法
public byte[] getBytes() 使用默认方式进行编码
public bytel] getBytes(string charsetName) 使用指定方式进行编码
string(byte[] bytes) 使用默认方式进行解码
String(bytel] bytes, string charsetName) 使用指定方式进行解码
JAVA.IO将流分为节点流与处理流
节点流:也称为低级流,是实际连接程序与另一端的"管道”,负责实际读写数据的流
处理流:也称为高级流,不能独立存在,必须连接在其他流上,目的是当数据经过它时对数据进行某种
加工,简化我们的同等操作
实际开发中,我们总是串联一组高级流到某个低级流上完成流水线式的读写操作,这个过程被称为"流
的连接"
注意:读写一定是建立在节点流上进行的,读写不一定需要处理流,使用处理流是为了简化我们操作。
2.字节流——缓冲流(高级流):java.io.BufferedInputStream和BufferedOutputStream它们也继承自
InputStream和OutputStream
功能:缓冲流可以保证读写效率
① void write(int i)和int read()
缓冲的read方法虽然也是读取一个字节。但是本质上当第一次调用时他会向其连接的流一次性块读一
组字节回来并存入到内部维护的字节数组中(buf上,默认8kb)然后将数组第一个字节返回。如果再次
调用read方法则直接将字节数组中第二个字节返回,依次类推。再次过程中并不会再次读取硬盘,直
到所有字节全部返回后,才会再次真实读取
②flush方法
注意:缓冲的wirte方法会将数据攒到充满之后,才会传递下去,所以要写一个flush()方法,缓冲输出
流的flush方法会强制将缓冲流中已经缓冲的数据一次性写出,close()中默认有一个flush方法
flush方法是在接口:FLushable中定义的,而字节输出流的超类0utputStream实现了该接口,这以为这
所有字节输出流都具有该方法。

但是只有缓冲流真正实现了flush应有的功能。其他的高级流flush方法的实现都是调用其连接的流的
fLush方法,将该动作传递下去
③底层运行图:
3.字节流—对象流(高级流):java.io.ObjectOutputStream和ObjectIntputStream
功能:是进行对象的序列化与反序列化
对象序列化:将一个java对象转换为一组字节的过程称为对象序列化
①void writeObjct():进行对象的序列化
②Object readObject():
对象输入流的readobject方法可以进行对象的反序列化注意:对象输入流通过下面连接的流读取的字节
必须是对象输出流序列化一个对象后的一组字节,否则会抛出异常:CTassNotFoundException
对象输出流在序列化对象时可能引发异常:java.io.NotSerializableException: io.Person
原因:当序列化的对象没有实现接口:java.io.Serializable时出现上述异常

③transient关键字
当一个属性被关键字transient修饰后,那么当这个对象进行序列化时,这个属性的值会被忽略。忽略
不必要的属性值可以达到对象序列化瘦身的目的。这有助于减少磁盘开销或提高网络传输效率。
④底层运行图:
字符流=字节流+字符集
字符流的底层其实就是字节流 ,字符流都是高级流,作用是方便我们读与文本数据,使用场景:对于
纯文本文件进行读写操作
特点:输入流:一次读一个字节,遇到中文时,一次读多个字节;输出流:底层会把数据按照指定的编码
方式进行编码,变成字节再写到文件中
由于其他的字符流在流连接中要求只能连接在其他字符流上,而不能直接连接在字节流上
原因:字符流都是以字符为单位读写的,字节流是以字节为单位读写的,因为读写数据单位不同,因此
不能直接串联在一起工作。
4.字符流—转换流(高级流):java.io.InputStreamReader和OutputStreamWriter
它们是非常常用的字符流实现类,实际开发中我们不会直接操作这两个流,但是它们在流连接中是非
常重要的一环。(它的意义更重要,操作了解就行)
①在流连接中的意义
转换流本身是一对字符流,而它们是唯一可以连接在字节流上的字符流,因此其他的字符流可以连接
在转换流上,而转换流连接在字节流上,从而就可以实现串联在一起进行读写操作了。
②转换流的作用:负责字符与字节的转换工作;串联其他字符流与下面的字节流工作(起到了转换器的作
用)
5.字符流—缓冲流(高级流):java.io.BufferedWriter和BufferedReader
内部维护一个默认8192长度的char数组,还是以块读写形式读写字符数据提高读写效率
①BufferedWrite
java.io.PrintWriter——具有自动行刷新功能的缓冲字符输出流。内部总是连接BufferedWriter作为缓
冲。
PrintWriter提供了直接对文件进行写操作的构造器:
PrintWriter(String filename)
PrintWriter(File file,boolean autoFlush) 构造器第一个参数为流,那么就可以传入boolean类型
的第二个参数,打开自动行刷新功能
方法:void println() 写入一行字符串,自带换行符
1 PrintWriter pw=new PrintWriter(“.\note.txt”);
2 pw.println(“哪怕只有一成不到的胜算”);

3 pw.println(“甚至没有胜算,也必须要有赢的心态”);
4 pw.close();
5 System.out.println(“完毕”);
底层运行图:
//文件流(字节流,低级流):将字节写入到文件中
FileOutputStream fos=new FileOutputStream(“.\note.txt”);
//转换流(字符流,高级流):1.负责衔接字符流与字节流 2.将写出的字符转换为字节再写出
OutputStreamWriter osw=new OutputStreamWriter(fos, StandardCharsets.UTF_8);
//缓冲字符流(字符流,高级流):块写文本数据加速(内部缓冲区默认8192) BufferedWriter bw=new BufferedWriter(osw);
//PrintWriter(字符流,高级流):1.按行写出字符串2.具有自动行刷新功能
PrintWriter pw=new PrintWriter(bw,true);
Scanner scanner=new Scanner(System.in);
while(true){

String line=scanner.nextLine();
if (line.equals(“exit”)) {break;}
//当开启自动行刷新后,每当调用println方法写出一行后自动flush。注意:print方法不会flush
pw.println(line);}
15 pw.close();
②BufferedReader
方法:String readLine()读取一行字符串,返回的字符串中不含有最后的换行符,如果单独读取到了换
行符(一个空行)则返回值为空字符串,如果返回值为null,则表示流读取到了末尾
注意:第一次调用readLine就一次性读取8192个字符存入缓冲区(char数组),然后将其中第一行内容
返回当再次调用readLine时,再将第二行内容直接返回直到数组所有内容均返回后会再次读取8192个
字符如此往复以块读取保证效率。缓存流的机制都是一样的,读都是一口气读满内部的块,再一一传

FileInputStream fis=new FileInputStream(“.\note.txt”);
InputStreamReader isr=new InputStreamReader(fis);
BufferedReader br=new BufferedReader(isr);
for (String line=br.readLine();line!=null;line=br.readLine()){

System.out.println(line);}
br.close();

底层运行图:使用BufferedReader完成流连接目的是可以按行读取字符串并且还可以保证读取效率
三.异常
java.lang.ThrowabLe是所有异常的顶级超类
下面派生了两个子类型 :
Error:这类错误表示系统级别错误,是不可恢复的错误,程序出现后就会停止。Java异常处理机制不处
理Error,Error是给sun公司用的
Exception:程序级别的异常(“意外,例外”),是可以通过异常处理机制恢复的错误。
RuntimeException异常定义的都属于BUG级别的问题,都是可以通过逻辑避免掉的异常.
1.异常的作用:处理明知会发生,但不可避免的问题 例如:硬件上的问题
2.异常的处理方式
①JVM默认的处理方式:把异常的名称,异常原因及异常出现的位置等信息输出在了控制台,程序停
止执行,异常下面的代码不会再执行了
②自己处理
try{可能出现异常的代码;}catch(异常类名 变量名){异常的处理代码;}finally{必须执行的代码;} 目的:
当代码出现异常时,可以让程序继续往下执行
try(){}catch(){} 在try()中定义的内容最终都会被编译器改为在finally中调用close()关闭,只有实现了
Autocloseabe接口的类才可以在这里定义
try (
FileOutputStream fos=new FileOutputStream(“.\note.txt”);
OutputStreamWriter osw=new OutputStreamWriter(fos, StandardCharsets.UTF_8);
BufferedWriter bw=new BufferedWriter(osw);
PrintWriter pw=new PrintWriter(bw,true);
){
pw.println(“万物相争,优胜劣汰”);
} catch (IOException e) {
e.printStackTrace();
}
细节:在JDK7之后,我们可以在catch中同时捕获多个异常,中间用 | 进行隔开表示如果出现了A异常
或者B异常的话,采取同一种处理方案
异常中的常见方法(Throwable 的成员方法)
public string getMessage() 返回此 throwable 的详细消息字符串,常用于给用户提示或记录日
志使用
public string tostring() 返回此可抛出的简短描述

public void printStackTrace() 在底层是利用system.err.println进行输出,把异常的错误信息以红
色字体输出在控制台 细节:仅仅是打印信息,不会停止程序运行
③抛出异常
应用场景:当程序出现了一个异常,但是该异常不应当有当前代码片段处理时可以将其抛出给上层调
用;程序可以运行,但是不满足业务场景。
throws:写在方法定义处,表示声明一个异常告诉调用者,使用本方法可能会有哪些异常。
public void 方法()throws 异常类名1,异常类名2…{} 编译时异常: 必须要写 运行时异常: 可以不写。
throw:写在方法内,结束方法手动抛出异常对象,交给调用者方法中下面的代码不再执行了。
public void 方法(){throw new RuntimeException();}
注意:当使用throw抛出一个非RuntimeException的其他异常时,必须在当前方法上使用throws声明
该异常的抛出,可以自己写一个try来处理,但是没必要;永远都不要到main方法上写throw。
1 public void setAge(int age) throws Exception {//抛什么异常,就写什么类型的异常
2
3
4
5
if(age<0||age>100){
//throw new RuntimeException(“年龄不合法”);
throw new Exception(“年纪不合法”);
}this.age = age;}
注意:当调用一个含有throws声明异常抛出的方法时,编译器要求必须处理该异常,处理手段有两
种:使用try-catch捕获并处理这个异常;在当前方法上继续使用throws声明该异常的抛出给上层调用
者。
3.自定义异常
通常用于定义哪些因为不满足业务场景导致的异常
定义自定异常的几个要素:①类名要做到见名知义;②要继承自Exception(直接或间接继承都可以);③
提供所有类型的构造器(Alt+insert 构造器全选)
四.网络编程
在网络通信协议下,不同计算机上运行的程序,进行的数据传输,Java中可以使用java.net包下的技术
轻松开发出常见的网络应用程序
1.常用的软件架构:
C/S(Client/Server):在用户本地需要下载并安装客户端程序在远程有一个服务器端程序。
优缺点:画面可以做的非常精美,用户体验好;需要开发客户端,也需要开发服务端;用户需要下载
和更新的时候太麻烦
B/S(Browser/Server):只需要一个浏览器,用户通过不同的网址客户访问不同的服务器
优缺点:不需要开发客户端,只需要页面 + 服务端;用户不需要下载,打开浏览器就能使用;如果应
用过大,用户体验受到影响

2.网络编程三要素
①IP:上网设备在网络中的地址,是唯一的标识。
IPv4:全称:Internet Protocol version 4,互联网通信协议第四版采用32位地址长度,分成4组,采
用点分十进制表示法(192.168.1.66)
IPV6:全称:Internet Protocol version 6,互联网通信协议第六版由于互联网的发展,IP地址的需
求量愈来愈大,而IPV4的模式下IP的总数是有限的,采用128位地址长度,分成8组,采用冒分十六进
制法
现在如何解决IPv4不够的问题?利用局域网IP解决;特殊的IP:127.0.0.1(永远表示本机)
②端口号:应用程序在设备中唯一的标识。
由两个字节表示的整数,取值范围:065535其中01023之间的端口号用于一些知名的网络服务
或者应用。我们自己使用1024以上的端口号就可以了
③协议:数据在网络中传输的规则,常见的协议有UDP、TCP、http、https、ftp。
3.TCP协议
TCP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket对象通信之前要保证连接已
经建立,通过Socket产生IO流来进行网络通信
客户端(Socket)输出流 通信之前保证连接已经建立 服务器(ServerSocket)输入流
创建客户端的Socket对象(Socket)与指定服务端连接 创建服务器端的Socket对象(ServerSocket)
Socket(string host, int port) ServerSocket(int port)
获取输出流,写数据 监听客户端连接,返回一个Socket对象
Outputstream getoutputstream() Socket accept()
释放资源 获取输入流,读数据,并把数据显示在控制台
void close() InputStream getInputstream()
三次握手四次挥手
五.多线程
线程:程序中一个单一的顺序执行流程
多线程:软件或硬件上实现多个线程并发“同时”执行的技术
1.并发原理:
CPU一次只能执行一条指令,微观上是走走停停的,宏观上都在运行。这种现象叫并发,因此不是绝
对意义上的“同时运行”。
操作系统将时间划分为很多时间片段(时间片),尽可能均匀分配给每一个线程,得到时间片段的线程被
CPU运行,而其他线程全部等待,CPU在用高性能模拟“同时”。
2.线程使用场景
互不干扰:多线程通常用于在一个程序中需要同时处理多个互不干扰的任务;多线程更快:单线程中
可以完成,但是多线程可以更快。
3.创建并启动线程

①方法一:
创建:定义一个类继承Thread,重写run()方法来定义线程要执行的任务代码
启动:创建类的对象,调用线程的start()方法启动线程 注意: 启动线程要调用start而不是直接调用
run方法!
优点:在于结构简单
缺点:存在继承冲突问题,java是单继承的,实际开发中如果我们继承了某个类为了复用方法,而于
此同时又希望当前类是一个线程,则出现了继承冲突问题;当我们继承Thread并重写run方法来定义
该线程要执行的任务,这会导致线程与其执行的任务存在了必然的耦合关系,不利于线程的重用。
②方法二:
创建:定义一个类实现Runnable接口,重写run()方法来定义线程要执行的任务代码
启动:实例化线程要执行的任务(创建Runnable关于实现类的多态),创建线程执行任务(将多态对
象传给Thread对象),调用start()方法启动线程
4.获取线程
JAVA中所有的代码都是靠线程执行的,main方法也不例外,执行main方法的线程是由JVM创建的,
并为该线程取名"main"。因此我们称它为"主线程"
Thread提供了一个静态方法:
static Thread currentThread()该方法可以获取运行这个方法的线程。 那个对象执行这句话 返回的就
是那个线程。
public String getName() 获取线程的名字 public long getId() 获取唯一表示 (非空且唯一 ) public
int getPriority() 获取线程优先级
public boolean isAlive() / .isDaemon() / isInterrupted() 是否活着 / 是否为守护线程 / 是否被中断
5.线程的优先级(setPriority()方法 设置线程优先级)
线程一旦调用start方法后就纳入到线程调度器中被统一管理,线程只能被动的被分配时间片并发运
行。
调整线程的优先级可以最大程度的改善获取时间片的概率。优先级越高的线程获取时间片的次数越
多。
线程有10个优先级,分别用整数1-10表示。其中1最低,10最高,5为默认值
1 Thread t1=new Thread(){
2
@Override
3
public void run() { for (int i = 0; i < 10000; i++) { System.out.println(“max”);
}}};
4 Thread t2=new Thread(){
5
6
@Override
public void run() { for (int i = 0; i < 10000; i++) {
System.out.println(“min”);}}};
7
8
t1.setPriority(Thread.MAX_PRIORITY);
t2.setPriority(Thread.MIN_PRIORITY);

9
t1.start();
t2.start();
10
6.Sleep阻塞(是有误差的,不能做到精确的卡多少时间,因为还要等待时间片分配)
线程提供了一个静态方法:static void sleep(long ms),该方法可以让执行这个方法的线程处于阻塞状
态指定毫秒,超时后线程会自动回到RUNNABLE状态再次并发执行。当一个线程调用sleep方法处于
睡眠阻塞的过程中,此时该线程的void interrupt()方法被调用则会强行中断其睡眠阻塞,这时sleep方
法会抛出中断异常
7.守护线程
守护线程是通过用户线程(我们创建的线程默认都是用户线程)调用方法setDaemon(boolean on)并传
入true设置而转变来的,规定要定义在start方法前面。守护线程与用户线程的主要区别在于进程结
束:当JAVA进程中的所有用户线程都结束时,进程就会结束,在进程结束前会强制杀死所有还在运行
的守护线程。主线程是用户线程,只有两类线程,没有什么专门的守护那一个用户线程,只要还有一
个用户线程活着,守护线程就不会被强制杀死。
8.多线程并发安全问题
①原因:当多个线程并发操作同一临界资源,由于线程切换实际不确定,导致执行顺序出现混乱从而
产生不良后果。
临界资源:操作该资源的完整过程同一时刻只能被单个线程进行。
static void yield()方法用于让执行该方法的线程主动放弃本次剩余时间片
②解决办法
将多线程并发执行临界资源改为同步执行可有效解决并发安全问题。使用同步块可以更准确的锁定需
要同步执行的代码片段,当有效的缩小同步范围可以在保证并发安全的前提下尽可能提高并发效率
同步与异步执行都是指线程之间的执行方式:同步执行:线程之间执行存在先后顺序;异步执行:线程之
间各干各的,互补干扰
同步块语法:synchronized(同步监视器对象){ 需要同步执行的代码片段 }
注意:在成员方法上如果使用synchronized,那么该方法称为同步方法。 此时同步监视器对象不可
选,只能是this。静态方法上使用synchronized则该方法一定具有同步效果,静态方法上使用
synchronized时,同步监视器对象是当前类的类对象 ,即:Class的实例 (在JVM内部,每个被加载的
类都有且只有一个Class的实例与之对应,这个实例 就称为被加载的类的类对象) 若在静态方法中使
用同步块,指定的同步监视器对象通常还是类对象 ,指定方式:类名.class
同步监视器对象的选取原则
Ⅰ:必须是一个引用类型对象
Ⅱ:同个线程看到的必须是同一个对象
Ⅲ:该同步时能限制多个线程同步(同一个同步监视器对象), 不该同步时可以并发执行(不是同一个同步
见其对象)。
通常指定的同步监视器对象为临界资源对象(抢谁就锁谁)

互斥性:同一个类中,当使用多个synchronized锁定多个代码片段(方法),指定的同步监视器都是
同一个对象时,这些代码片段之间就是互斥的,多个线程不能同时访问它们。
六.集合进阶(Map)
Map是双列集合的顶层接口,它的功能是全部双列集合都可以继承使用的
Map是JAVA集合框架的一员。但是Map不是集合! ! ! 并没有实现Collection接口。
1.双列集合的特点
①Map体现的结构是一个多行两列的表格,其中左列称为key,右列称为value;②Map总是根据key
提取对应的vaLue;③键不能重复,值可以重复;④键+值这个整体我们称之为“键值对”或者“键值
对对象”,在Java中叫做“Entry对象
2.常见API
V put(K key,V value) 添加元素
V get(K key) 根据给定的key获取对应的value。如果给定的Key在Map 中不存在则返回值为null
V remove(Object key) 根据键删除键值对元素
void clear() 移除所有的键值对元素
boolean containsKey(object key) 判断集合是否包含指定的键
boolean containsValue(object value) 判断集合是否包含指定的值
boolean isEmpty() 判断集合是否为空
int size() 集合的长度,也就是集合中键值对的个数
put方法的细节:在添加数据的时候,如果键不存在,那么直接把键值对对象添加到map集合当中,方
法返回null,在添加数据的时候,如果键是存在的,那么会把原有的键值对对象覆盖,会把被覆盖的值
进行返回。
3.遍历方式
①遍历所有的key
Set keySet() 将当前Map中所有的key以一个Set集合形式返回,再遍历Set集合(迭代器,增强
for,lambda)
1 Map<String,Integer> map=new HashMap<>();
2 map.put(“语文”,99);map.put(“数学”,98);map.put(“英语”,97);map.put(“化学”,99);
3 Set keyset=map.keySet();
4 for (String s:keyset){ System.out.println(s); }
②遍历每一组键值对
Set entrySet() 将当前Map中每一组键值对以一个Entry实例表示,并最终以Set集合形式返回所有的
键值对。

Map.Entry的每一个实例用于表示Map 中的一组键值对,有两个常用方法:K getKey():获取 key V
getValue():获取value
1 Map<String,Integer> map=new HashMap<>();
2 map.put(“语文”,99);map.put(“数学”,98);map.put(“英语”,97);map.put(“化学”,99);
3 Set<Map.Entry<String,Integer>> entrySet= map.entrySet();
4 for (Map.Entry<String,Integer> e:entrySet){
5
6
7
String key=e.getKey();
Integer value=e.getValue();
System.out.println(key+“:”+value);}
③遍历所有的vaLue(相对不常用)
Collection values() 将当前Map中所有的value以一个Collection集合形式返回
1 Map<String,Integer> map=new HashMap<>();
2 map.put(“语文”,99);map.put(“数学”,98);map.put(“英语”,97);map.put(“化学”,99);
3 Collection collection=map.values();
4 for (Integer i:collection){ System.out.println(i); }
④lambda表达式
1 Map<String,Integer> map=new HashMap<>();
2 map.put(“语文”,99);map.put(“数学”,98);map.put(“英语”,97);map.put(“化学”,99);
3 map.forEach((s,i)->System.out.println(s+“,”+i));
七.反射
反射是java中的动态机制,是Java的底层机制。 常用框架,都是基于反射技术实现的!
它允许我们在程序运行期间再确定类的实例化,方法的调用,属性的调用等,而不是传统意义上的在
编码期间确定。 因此,反射可以大大的提高代码的灵活度,但是随之而来的是更多的系统开销和较慢
的运行速度,因此不能过度的依赖反射。
1.获取class对象的三种方法
①class.forName(“全类名”); 全类名 : 包名+类名(源代码阶段用,最为常用的)

1 Classs cls = Class.forName(“java.lang.String”);
2 System.out.println(cls);//class java.lang.String
3 System.out.println(cls.getName());//获取类型的全名:包名.类名 //java.lang.String
②类名.class(加载阶段用—class文件进入内存,一般更多的是当做参数进行传递)
1 Class cls = String.class;//返回 String 类型的Class对象,代表 String 类型的信息(属性、方
法、构造器 等)
2 System.out.println(cls.getName());
③使用ClassLoader加载获得 Class 对象
1 //先获得ClassLoader:当前类名.class.getClassLoader()
2 ClassLoader classLoader = ReflectDemo01.class.getClassLoader();
3 //使用loadClass方法,获取 String 类型的Class对象,如果类名错误,就会出现异常
4 Class cls = classLoader.loadClass(“java.lang.String”);
③对象.getClass()(运行阶段用,当我们已经有了这个类的对象时,才可以使用)
1 Person p=new Person();
2 Class cls=p.getClass();
2.利用反射获取构造方法
①Class类中用于获取构造方法的方法
Constructor<?>[] getConstructors(): 返回所有公共构造方法对象的数组 Constructor getConstructor(Class<?>… parameterTypes): 返回单个公共构造方法对象
Constructor<?>[] getDeclaredConstructors(): 返回所有构造方法对象的数组 Constructor getDeclaredConstructor(Class<?>… parameterTypes): 返回单个构造方法对象
②Constructor类中用于创建对象的方法
T newInstance(Object…initargs): 根据指定的构造方法创建对象
setAccessible(boolean flag):设置为true,表示取消访问检查,用于访问private修饰的信息
3.利用反射获取成员变量
①Class类中用于获取成员变量的方法

Field[] getFields():返回所有公共成员变量对象的数组
Field getField(String name): 返回单个公共成员变量对象
Field[] getDeclaredFields(): 返回所有成员变量对象的数组
Field getDeclaredField(String name): 返回单个成员变量对象
②Field类中用于创建对象的方法
void set(Object obj, Object value): 赋值
Object getObject obj) 获取值。
4.利用反射获取成员方法
①Class类中用于获取成员方法的方法
Method[] getMethods(): 返回所有公共成员方法对象的数组,包括继承的
Method getMethod(String name,Class<?>.. parameterTypes): 返回单个公共成员方法对象 Method[] getDeclaredMethods(): 返回所有成员方法对象的数组,不包括继承的 Method getDeclaredMethod(String name, Class<?>… parameterTypes): 返回单个成员方法对象
②Method类中用于创建对象的方法
Object invoke(Object obj, Object… args): 运行方法
参数一:用obj对象调用该方法
参数二:调用方法的传递的参数(如果没有就不写)
返回值:方法的返回值 (如果没有就不写)
八.注解
Java 5 开始提供了注解语法,利用注解可以为类扩展功能。注解功能都是利用反射API实现。
注解用于标注类、方法、属性、方法参数等。 注解用于扩展类的功能 。注解的功能是利用反射实现的
1.定义注解:public @interface 注解类型 { }
2.元注解——作为注解的注解, 说明注解的功能
常用的两种:
①@Target 目标注解:
@Target(ElementType.METHOD) 表示当前注解,只能标注在方法
@Target(ElementType.TYPE)表示当前注解,只能标注在类型(接口、类、抽象类)上
②@Retention保留规则:
@Retention(RetentionPolicy.CLASS)保留到源代码阶段
@Retention(RetentionPolicy.SOURCE)保留到
@Retention(RetentionPolicy.RUNTIME)保留到运行时(最常用)
1 @Target(ElementType.METHOD)
2 @Retention(RetentionPolicy.RUNTIME)
3 public @interface DemoAnnotation {}

3.注解和反射的用途
看jsd2210-se-teacher day08
4.注解的参数
①定义参数:类型 参数名() [default 默认值];
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Test {

//order 排序依据属性,-1 表示没有顺序
int order() default -1;
//属性 name
String name() default “”;
//value 是默认属性, 只有一个属性,建议使用value 属性
int value() default -1;}
②使用
1 @Test(order=6)
2 @Test(order=6, name=“Jerry”)
3 @Test(6) // 不写任何参数,就是对默认属性进行复制
4 //如果属性不设置值的化, 将采用默认值
九.线程池
1.主要核心原理
创建一个池子,池子中是空的,提交任务时,池子会创建新的线程对象,任务执行完毕,线程归还给
池子,下回再次提交任务时,不需要创建新的线程,直接复用已有的线程即可,但是如果提交任务
时,池子中没有空闲线程,也无法创建新的线程,任务就会排队等待
2.创建线程池
Executors:线程池的工具类通过调用方法返回不同类型的线程池对象
public static ExecutorService newCachedThreadPool() 创建一个没有上限的线程池(最高创建21
个亿的线程)
public static ExecutorService newFixedThreadPool(int nThreads) 创建有上限的线程池
3.创建并指派任务
①创建:实现Runnable接口重写run()方法

②指派任务:调用线程池方法pool.execute(任务)
4.线程池的关闭
①shutdown() 不再接收新的任务了 、将现有任务执行完毕、结束池中所有的线程
②shutdownNow() 不再接收新的任务了、中断线程池所有线程
1 ExecutorService threadPool= Executors.newFixedThreadPool(2);
2 for (int i = 0; i < 5; i++) {
3
4
Runnable r=new Runnable() {
@Override
5
public void run() {
try {
6
7
Thread t=Thread.currentThread();
8
System.out.println(t.getName()+“:正在执行一个任务”);
Thread.sleep(5000);
9
10
11
12
13
14
15
16
17
18 }
System.out.println(t.getName()+“:执行任务完毕”);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
threadPool.execute®;
System.out.println(“将一个任务交给线程”);
19 threadPool.shutdown();
20 System.out.println(“哇哈哈哈”);
5.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值