本帖最后由 小石姐姐 于 2018-4-24 17:31 编辑
JavaSE学习笔记(9-13天)
第9天 IO流第1章 File类1.1 File概述打开API,搜索File类。阅读其描述:File文件和目录路径名的抽象表示形式。即,Java中把文件或者目录(文件夹)都封装成File对象。也就是说如果我们要去操作硬盘上的文件,或者文件夹只要找到File这个类即可,那么我们就要研究研究File这个类中都有那些功能可以操作文件或者文件夹呢 1.2 File类的构造函数 File(Stringpathname) :将一个字符串路径封装成File对象 File(String parent,String child):传入一个父级路径和子级路径 File(File parent,String child):传入一个File类型的父级路径和子级路径 1.3 File类创建和删除功能boolean createNewFile():指定路径不存在该文件时时创建文件,返回true,否则返回false boolean mkdir():当指定的单级文件夹不存在时创建文件夹并返回true,否则返回false boolean mkdirs():当指定的多级文件夹某一级文件夹不存在时,创建多级文件夹并返回true,否则返回false boolean delete():删除文件或者删除单级文件夹 1.4 File类的判断功能boolean exists():判断指定路径的文件或文件夹是否存在 boolean isAbsolute():判断当前路路径是否是绝对路径 boolean isDirectory():判断当前的目录是否存在 boolean isFile():判断当前路径是否是一个文件 boolean isHidden():判断当前路径是否是隐藏文件 1.5 File类的获取功能和修改名字功能 File getAbsoluteFile():获取文件的绝对路径,返回File对象 String getAbsolutePath():获取文件的绝对路径,返回路径的字符串 StringgetParent():获取当前路径的父级路径,以字符串形式返回该父级路径 FilegetParentFile():获取当前路径的父级路径,以字File对象形式返回该父级路径 StringgetName():获取文件或文件夹的名称 StringgetPath():获取File对象中封装的路径 longlastModified():以毫秒值返回最后修改时间 longlength():返回文件的字节数 boolean renameTo(File dest): 将当前File对象所指向的路径修改为 指定File所指向的路径 1.6 File类的其它获取功能String[] list():以字符串数组的形式返回当前路径下所有的文件和文件夹的名称 File[]listFiles():以File对象的形式返回当前路径下所有的文件和文件夹的名称 static File[] listRoots():获取计算机中所有的盘符 第2章 字符流与字节流2.1 概述 IO流分类: 流向 输入流 读取数据 FileReader Reader 输出流 写出数据 FileWriter Writer 数据类型 字节流 字节输入流 读取数据 InputStream 字节输出流 写出数据 OutputStream 字符流 字符输入流 读取数据 Reader 字符输出流 写出数据 Writer 2.2 利用字符流复制文本文件 利用字符流将当前工程下的IODemo.java拷贝到d盘的a文件夹下
package com.itheima_02;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 使用字符流复制文本文件
*
* 数据源 IODemo.java
* 目的地 d:\\IODemo.java
*
*/
public class FileCopyDemo {
public static void main(String[] args) throws IOException {
//创建字符输入流对象
FileReader fr = new FileReader("IODemo.java");
//创建字符输出流对象
FileWriter fw = new FileWriter("d:\\IODemo.java");
//一次读写一个字符
/*int ch;
while((ch = fr.read()) != -1) {
fw.write(ch);
fw.flush();
}*/
//一次读写一个字符数组
int len;//用于存储读到的字符个数
char[] chs = new char[1024];
while((len = fr.read(chs)) != -1) {
fw.write(chs,0,len);
fw.flush();
}
//释放资源
fw.close();
fr.close();
}
}
2.3 利用字节流复制文本文件利用字节流将当前工程下的IODemo.java拷贝到d盘下
package com.itheima_03;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/*
* 使用字节流复制文本文件
*
* 数据源 IODemo.java
* 目的地 d:\\a\\IODemo.java
*
*/
public class FileCopyDemo {
public static void main(String[] args) throws IOException {
//创建字节输入流对象
FileInputStream fis = new FileInputStream("IODemo.java");
//创建字节输出流对象
FileOutputStream fos = new FileOutputStream("d:\\a\\IODemo.java");
//一次读写一个字节
/*int by;
while((by = fis.read()) != -1) {
fos.write(by);
}*/
//一次读写一个字节数组
int len;//存储读到的字节个数
byte[] bys = new byte[1024];
while((len = fis.read(bys)) != -1) {
fos.write(bys,0,len);
}
//释放资源
fos.close();
fis.close();
}
}
2.4 复制图片字节流可以操作所有类型的文件,因为所有的文件在计算机中都是以字节形式存储 而字符流只能用来操作纯文本类型的文件,不能操作字节类型的文件
package com.itheima_04;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
/*
* 分别使用字符流和字节流复制图片
*
* 二进制文件只能使用字节流进行复制(使用windows自带记事本打开读不懂的)
* 文本文件的复制即可使用字符流,也可以使用字节流
*
*/
public class CopyImage {
public static void main(String[] args) throws IOException {
//method();
//创建字节输入流对象
FileInputStream fis = new FileInputStream("传智学院.jpg");
//创建字节输出流对象
FileOutputStream fos = new FileOutputStream("d:\\传智学院.jpg");
//一次读写一个字节数组
int len;//用于存储读到的字节个数
byte[] bys = new byte[1024];
while((len = fis.read(bys)) != -1) {
fos.write(bys,0,len);
}
//释放资源
fos.close();
fis.close();
}
private static void method() throws FileNotFoundException, IOException {
//创建字符输入流对象
FileReader fr = new FileReader("传智学院.jpg");
//创建字符输出流对象
FileWriter fw = new FileWriter("d:\\传智学院.jpg");
//一次读写一个字符数组
int len;//用于存储读到的字符个数
char[] chs = new char[1024];
while((len = fr.read(chs)) != -1) {
fw.write(chs,0,len);
fw.flush();
}
//释放资源
fw.close();
fr.close();
}
}
第10天 IO流第1章 标准输入流 & 转换流& 打印流1.1 标准输入输出流 publicstatic final InputStream in:标准输入流 publicstatic final PrintStream out:标准输出流 1.2 转换流1.2.1 OutputStreamWriter:将字节输出流转换为字符输出流1.2.2 InputStreamReader:将字节输入流转换为字符输入流1.3 打印流打印流添加输出数据的功能,使它们能够方便地打印各种数据值表示形式. 字符打印流 PrintWriter void print(String str): 输出任意类型的数据, void println(String str): 输出任意类型的数据,自动写入换行操作 第2章 对象操作流2.1 概述用于从流中读取对象的 ObjectInputStream称为 反序列化流,利用输入流从文件中读取对象 ObjectOutputStream 称为 序列化流,利用输出流向文件中写入对象 特点:用于操作对象。可以将对象写入到文件中,也可以从文件中读取对象。 2.2 利用序列化流读写对象2.3 解决对象输入流读取对象出现异常的问题2.4 解决读写对象版本不一致问题第3章 Properties集合3.1 Properties介绍Properties 类表示了一个持久的属性集。Properties 可保存在流中或从流中加载。属性列表中每个键及其对应值都是一个字符串。 特点: 1、Hashtable的子类,map集合中的方法都可以用。 2、该集合没有泛型。键值都是字符串。 3、它是一个可以持久化的属性集。键值可以存储到集合中,也可以存储到持久化的设备(硬盘、U盘、光盘)上。键值的来源也可以是持久化的设备。 4、有和流技术相结合的方法。 3.2 利用Properties存储键值对3.3 Properties与流结合使用第4章 编码表4.1 编码表的概述编码表:把计算机底层的二进制数据转换成我们能看到的字符 * ASCII * * GB2312 --- GBK * Unicode 所有的字符都占2个字节 * UTF-8 长度可变的码表 * * ANSI:本地编码表 gbk * Java中的字符串默认使用的ANSI(gbk) * 乱码:编码保持前后一致即可解决 4.2 Java中字符串的编码4.2.1 常用方法构造方法(字节数组转字符串): String():初始化一个新创建的 String 对象,使其表示一个空字符序列 String(byte[]bytes) 使用平台的默认字符集解码指定的 byte 数组,构造一个新的 String String(byte[]bytes, Charset charset) 通过使用指定的 charset 解码指定的 byte 数组,构造一个新的 String 成员方法(字符串转字节数组) getBytes()使用平台的默认字符集将此 String 编码为 byte 序列,并将结果存储到一个新的 byte 数组中 getBytes(Charsetcharset) 使用给定的 charset 将此 String 编码到 byte 序列,并将结果存储到新的 byte 数组 4.3 字符流中的编码4.3.1 常见对象InputStreamReader(InputStreamin, CharsetDecoder dec) 创建使用给定字符集解码器的InputStreamReader OutputStreamWriter(OutputStreamout, CharsetEncoder enc) 创建使用给定字符集编码器的OutputStreamWriter 第11天第1章 多线程概述学习多线程之前,我们先要了解几个关于多线程有关的概念。 A:进程:进程指正在运行的程序。确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能。 B:线程:线程是进程中的一个执行单元,负责当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称之为多线程程序。 C:简而言之:一个程序运行后至少有一个进程,一个进程中可以包含多个线程 什么是多线程呢?即就是一个程序中有多个线程在同时执行。 第2章 线程实现2.1 实现线程一:继承Thread类A:创建线程的步骤: 1.定义一个类继承Thread。 2.重写run方法。 3.创建子类对象,就是创建线程对象。 4.调用start方法,开启线程并让线程执行,同时还会告诉jvm去调用run方法 2.2 实现线程二:实现Runnable接口创建线程的另一种方法是声明实现 Runnable 接口的类。该类然后实现 run 方法。然后创建Runnable的子类对象,传入到某个线程的构造方法中,开启线程。 为何要实现Runnable接口,Runable是啥玩意呢?继续API搜索。 查看Runnable接口说明文档:Runnable接口用来指定每个线程要执行的任务。包含了一个 run 的无参数抽象方法,需要由接口实现类重写该方法。 创建线程的步骤。 1、定义类实现Runnable接口。 2、覆盖接口中的run方法。。 3、创建Thread类的对象 4、将Runnable接口的子类对象作为参数传递给Thread类的构造函数。 5、调用Thread类的start方法开启线程。 第3章 多线程安全问题产生&解决方案3.1 多线程卖票案例 package com.itheima_03;
public class TicketThread implements Runnable {
int tickets = 100;//火车票数量
@Override
public void run() {
//出售火车票
while(true) {
//当火车票小于0张,则停止售票
if(tickets > 0) {
/*
* t1,t2,t3
* 假设只剩一张票
* t1过来了,他一看有票,他就进来了,但是他突然肚子不舒服,然后他就去上卫生间了
* t2也过来了,他一看也有票,他也进来了,但是他的肚子也不舒服,他也去上卫生间了
*
* t1上完了卫生间回来了,开始售票
* tickets = 0;
* t2也上完卫生间回来了,他也进行售票
* tickets = -1;
*
*
*/
try {
Thread.sleep(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" +tickets--);
}
}
}
}3.2 多线程安全问题解决3.2.1 使用同步代码块解决格式: synchronized(锁对象){ //需要同步的代码 } 3.2.2 使用同步方法解决 格式: 修饰符 synchronized 返回值 方法名(){ } 第12天 面向网络编程第1章 网络编程概述1.1 网络协议 通过计算机网络可以使多台计算机实现连接,位于同一个网络中的计算机在进行连接和通信时需要遵守一定的规则,这就好比在道路中行驶的汽车一定要遵守交通规则一样。在计算机网络中,这些连接和通信的规则被称为网络通信协议,它对数据的传输格式、传输速率、传输步骤等做了统一规定,通信双方必须同时遵守才能完成数据交换。 网络通信协议有很多种,目前应用最广泛的是TCP/IP协议(Transmission Control Protocal/Internet Protoal传输控制协议/英特网互联协议),它是一个包括TCP协议和IP协议,UDP(UserDatagram Protocol)协议和其它一些协议的协议组,在学习具体协议之前首先了解一下TCP/IP协议组的层次结构。 在进行数据传输时,要求发送的数据与收到的数据完全一样,这时,就需要在原有的数据上添加很多信息,以保证数据在传输过程中数据格式完全一致。TCP/IP协议的层次结构比较简单,共分为四层,如图所示。 上图中,TCP/IP协议中的四层分别是应用层、传输层、网络层和链路层,每层分别负责不同的通信功能,接下来针对这四层进行详细地讲解。 链路层:链路层是用于定义物理传输通道,通常是对某些网络连接设备的驱动协议,例如针对光纤、网线提供的驱动。 网络层:网络层是整个TCP/IP协议的核心,它主要用于将传输的数据进行分组,将分组数据发送到目标计算机或者网络。 传输层:主要使网络程序进行通信,在进行网络通信时,可以采用TCP协议,也可以采用UDP协议。 应用层:主要负责应用程序的协议,例如HTTP协议、FTP协议等。 1.2 IP地址和端口号要想使网络中的计算机能够进行通信,必须为每台计算机指定一个标识号,通过这个标识号来指定接受数据的计算机或者发送数据的计算机。 在TCP/IP协议中,这个标识号就是IP地址,它可以唯一标识一台计算机,目前,IP地址广泛使用的版本是IPv4,它是由4个字节大小的二进制数来表示,如:00001010000000000000000000000001。由于二进制形式表示的IP地址非常不便记忆和处理,因此通常会将IP地址写成十进制的形式,每个字节用一个十进制数字(0-255)表示,数字间用符号“.”分开,如 “192.168.1.100”。 随着计算机网络规模的不断扩大,对IP地址的需求也越来越多,IPV4这种用4个字节表示的IP地址面临枯竭,因此IPv6 便应运而生了,IPv6使用16个字节表示IP地址,它所拥有的地址容量约是IPv4的8×1028倍,达到2128个(算上全零的),这样就解决了网络地址资源数量不够的问题。 通过IP地址可以连接到指定计算机,但如果想访问目标计算机中的某个应用程序,还需要指定端口号。在计算机中,不同的应用程序是通过端口号区分的。端口号是用两个字节(16位的二进制数)表示的,它的取值范围是0~65535,其中,0~1023之间的端口号用于一些知名的网络服务和应用,用户的普通应用程序需要使用1024以上的端口号,从而避免端口号被另外一个应用或服务所占用。 1.3 InetAddress了解了IP地址的作用,我们看学习下JDK中提供了一个InetAdderss类,该类用于封装一个IP地址,并提供了一系列与IP地址相关的方法,下表中列出了InetAddress类的一些常用方法。 第2章 UDP协议 UDP是无连接通信协议,即在数据传输时,数据的发送端和接收端不建立逻辑连接。简单来说,当一台计算机向另外一台计算机发送数据时,发送端不会确认接收端是否存在,就会发出数据,同样接收端在收到数据时,也不会向发送端反馈是否收到数据。 由于使用UDP协议消耗资源小,通信效率高,所以通常都会用于音频、视频和普通数据的传输例如视频会议都使用UDP协议,因为这种情况即使偶尔丢失一两个数据包,也不会对接收结果产生太大影响。 但是在使用UDP协议传送数据时,由于UDP的面向无连接性,不能保证数据的完整性,因此在传输重要数据时不建议使用UDP协议。UDP的交换过程如下图所示。 2.1 DatagramPacket2.2 DatagramSocket2.3 UDP实现第3章 TCP协议TCP通信同UDP通信一样,都能实现两台计算机之间的通信,通信的两端都需要创建socket对象。 区别在于,UDP中只有发送端和接收端,不区分客户端与服务器端,计算机之间可以任意地发送数据。 而TCP通信是严格区分客户端与服务器端的,在通信时,必须先由客户端去连接服务器端才能实现通信,服务器端不可以主动连接客户端,并且服务器端程序需要事先启动,等待客户端的连接。 在JDK中提供了两个类用于实现TCP程序,一个是ServerSocket类,用于表示服务器端,一个是Socket类,用于表示客户端。 通信时,首先创建代表服务器端的ServerSocket对象,该对象相当于开启一个服务,并等待客户端的连接,然后创建代表客户端的Socket对象向服务器端发出连接请求,服务器端响应请求,两者建立连接开始通信。 3.1 ServerSocket通过前面的学习知道,在开发TCP程序时,首先需要创建服务器端程序。JDK的java.net包中提供了一个ServerSocket类,该类的实例对象可以实现一个服务器段的程序。通过查阅API文档可知,ServerSocket类提供了多种构造方法,接下来就对ServerSocket的构造方法进行逐一地讲解。 3.2 Socket讲解了ServerSocket对象可以实现服务端程序,但只实现服务器端程序还不能完成通信,此时还需要一个客户端程序与之交互,为此JDK提供了一个Socket类,用于实现TCP客户端程序 3.3 TCP协议实现第13天 java基础进阶第1章 反射机制概述、字节码对象的获取方式、反射操作构造方法、成员方法、成员属性1.1 反射机制的概述和字节码对象的获取方式1.1.1 反射介绍JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法 对于任意一个对象,都能够调用它的任意一个方法 这种动态获取的以及动态调用对象的方法的功能称为java语言的反射机制. 简单来说, 就可以把.class文件比做动物的尸体, 而反射技术就是对尸体的一种解剖. 通过反射技术, 我们可以拿到该字节码文件中所有的东西, 例如成员变量, 成员方法, 构造方法, 而且还包括私有 1.1.2 字节码文件获取的三种方式2. 类名.class // 类名.class这是一个静态的属性, 只要知道类名, 就可以获取 3. Class.forName(“com.itheima_01.Student”); // 通过Class类中的静态方法, 指定字符串, 该字符串是类的全类名(包名+类名) // 此处将会抛出异常都系 ClassNotFoundException防止传入错误的类名 1.1.3 问题: 字节码对象是用来描述什么的?用来描述.class文件的. 面向对象阶段的时候讲过java中描述事物都是通过类的形式 而字节码文件也可以看做为一种事物, 如何描述这种事物? 那就看看这个事物是由什么组成的了 1.2反射操作构造方法 1.2.1 通过获取的构造创建对象步骤: 1.获得Class对象 2获得构造 3.通过构造对象获得实例化对象 1.2.2 问题: 直接通过Class类中的newInstance()和获取getConstructor()有什么区别?newInstance()方法, 只能通过空参的构造方法创建对象 getConstructor(Class<T>…parameterTypes)方法, 方法接受一个可变参数, 可以根据传入的类型来匹配对应的构造方法 总结 Constructor<?>[]getConstructors() Constructor<T>getConstructor(Class<?>... parameterTypes) 方法1: 获取该类中所有的构造方法, 返回的是一个数组 方法2: 方法接受一个可变参数, 可以根据传入的类型, 来匹配对应的构造方法 1.3 反射操作公共成员变量1.3.1 反射public成员变量(字段)通过反射运行public变量流程 1. 通过反射获取该类的字节码对象 Class clazz = Class.forName("com.heima.Person"); 2. 创建该类对象 Object p = clazz.newInstance(); 3. 获取该类中需要操作的字段(**成员变量)** getField(String name) --> 方法传入字段的名称. 注意: 此方法只能获取公共的字段 Field f = clazz.getField("age"); 4. 通过字段对象中的方法修改属性值 void set(Object obj, Object value) --> 参数1): 要修改那个对象中的字段, 参数2): 将字段修改为什么值. f.set(p, 23); 1.3.3 方法总结 通过反射获取成员变量并使用 Field[]getFields() -->返回该类所有(公共)的字段 FieldgetField(String name) --> 返回指定名称字段 Field[]getDeclaredFields() --> 暴力反射获取所有字段(包括私有) FieldgetDeclaredField(String name) --> 暴力反射获取指定名称字段 ---------------马上讲----------------- Field: Objectget(Objectobj) --> Field对象调用, 返回传入对象的具体字段 voidset(Object obj, Object value) --> Field对象调用 参数1: 要修改的对象 参数2: 将此对象的字段修改为什么值. 第2章 JavaBean的概述、BeanUtils的使用2.1 JavaBean的概述和规范JavaBean**的概述:** 将需要操作的多个属性封装成JavaBean, 简单来说就是用于封装数据的 规范: 类使用公共进行修饰 提供私有修饰的成员变量 为成员变量提供公共getter和setter方法 提供公共无参的构造 2.2 BeanUtils的概述BeanUtils**的由来** 之前我们使用的类都是来自Java编写好的源代码 而这个BeanUtils却是一个叫做Apache的组织编写. 那么这个组织编写的代码当中, 有一个系列可以很方便的提高我们今后的开发效率. 这个系列为Commons, BeanUtils就是其中之一 2.3 BeanUtils的常用方法setProperty 用来给对象中的属性赋值(了解) 参数1: 需要设置属性的对象 参数2: 需要修改的属性名称 参数3: 需要修改的具体元素 getProperty 用来获取对象中的属性(了解) 参数1: 要获取的javaBean对象 参数2: 对象中的哪个属性 Populate 用来给对象中的属性赋值(掌握) 参数1: 要设置属性的对象 参数2: 将属性以Map集合的形式传入 Key : 属性的名称 Value: 属性具体的值 2.3.1 方法总结三个方法底层是通过反射实现, 而且反射操作的是setXxx方法和getXxx方法. 所以编写 JavaBean 的时候一定要注意格 2.4 自定义BeanUtils的赋值和获取方法实现.2.4.1 功能分析定义MyBeanUtils**工具类,** 实现与BeanUtils**相同的功能** public static void setProperty(Object bean,Stringname,Object value) // 设置任意对象的, 任意属性, 为任意的值 public static StringgetProperty(Object bean,String name) // 获取任意对象的任意属性 publicstatic void populate(Object bean,Map map) //修改任意对象中的属性, 为传入Map集合中的键和值 2.5 自定义BeanUtils的populate方法实现2.5.1 功能分析public static void populate(Object bean,Map map) //修改任意对象中的属性, 为传入Map集合中的键和值 思路: 1. 获取传入对象的字节码对象 2. 获取map集合中所有的键和值 3. 调用Class中的getDeclaredField()方法将每一个键传入, 得到Field对象 4. 通过Field对象中的set方法赋值 5. Try catch捕获getDeclaredField方法可能发生的异常.(为了方式传入错误的值)
|