前言
多年以前自学Java,在本地做了一些笔记。最近几年流行播客,一方面防止丢失,一方面可以帮助其他小伙伴学习。所以,一直也想写一些属于自己的东西,但总是在忙抽不出时间。最近难得的清闲,就把之前本地的笔记给总结到线上来。本Java基础笔记适合初学者来学习,刚入门者可以把此作为工具书来用。
接着上文来写接下来。
Java基础笔记汇总----略微进阶
-------------------------------------------集合-------------------------------------
26.集合的继承关系
Collection 接口
|
|
|
|----------List接口(有序的 可重复的)
| |
| |------ArrayList类 底层是数组
| |
| |------LinkedList类 底层是双向链表
|
|---------Set接口(无序的(存取顺序无序) 不可重复的)
|
|
|-----HashSet类 可以通过元素的hashCode和equals来完成保证元素唯一性
|
|
|------TreeSet类
27.Collection 和 Collections的区别:(面试题)
(1)Collection是集合的工具类,直接实现类有List和Set
主要方法:add(Object) remove(Object) removeAll(另一个集合)
clear() contains(Object) idEmpty() seze()
集合独有的代码方法:
<1>每个集合都可调用Collection的Iterator()方法获取迭代器(Interator接口的实例)
<2>Interator中的hasNext() 判断下一个元素是否有元素 可作为循环的条件
<3>Interator中的next() 返回光标的下一个位置的元素,并且光标向下移动一位
<4>remove()移除光标指向的元素(★)
(2)Collections是一个集合的工具类,可以对集合排序,查找等(参考API)
29.List的总结
(1)元素的存储是有序的,元素可以重复.因为该集合有索引
(2)List的孩子有ArrayList LinkedList Vector
(3)凡是可操作角标的方法都是该体系特有的方法
增:add(index) addAll(index) 删:remove(index) 改:set(index)
查:get(index) subList(from,to)//获取部分对象的元素
(4)ListIterator是List集合特有的迭代器,是Iterator的子接口
Interator迭代时只能用迭代器的方法操作集合,但其方法是有限的
因此有了ListInterator,此迭代器迭代式是用集合中的方法操作集合的
ListInterator特有的方法
add()
set()
hasPravious()//判断前面有没有元素
previous()//取前一个元素
28.ArrayList与LinkedList的区别:(面试)
(1)ArrayList 底层是数组,在指定位置增加,删除元素效率低
随机访问效率高(用下标访问)
(2)LinkedList 底层是双向链表,在指定位置增减或者删除效率高
随机访问效率低(用下标访问每次都是从头查找)
LinkedList中有一系列xxxFirst()方法,从而可以模拟堆栈,队列等
(3)二者都是List的孩子
29.ArrayList和Vector的区别:(面试)
(1)ArrayList 线程不安全 效率高
(2)Vector是旧版的ArrayList,线程安全,效率低不适用,一般
30.Set总结
(1)Set散列存储: 元素是无序的(存取顺序不一致) 元素不可重复
(2)Set有两个孩子HashSet和TreeSet
(3)Set的功能和其父类Collection是一致的
31.HastSet总结
(1)散列存储
(2)通过元素的hashCode和equals来完成保证元素唯一性
先判断hashCode(),如果hashCode相同,则进一步判断equals.如果hashCode不同,,直接存储(★)
(3)因此存入对象必须重写hashCode()和equals方法
32.TreeSet总结
(1)可以对Set集合中的元素进行排序,默认按照字母的自然顺序排序,底层是二叉树,保证元素的唯一性的依据是compareTo方法return 0;
(2)TreeSet类实现了Comparable接口,该接口强制让增加到集合中的对象进行了比较, 需要复写compareTo方法,才能让对象按指定需求(如人的年龄大小比较等) 进行排序,并加入集合。
(3)第一种方式:传入数据自带比较方法(★)
该对象需要实Compareable(T t)接口,并重写compareTo(T t);方法
public int compareTo(School school) {
if (this.school_id != school.school_id) {
return school.school_id - this.school_id;
}else if (!this.school_name.equals(school.school_name)) {
CollationKey key1 = Collator.getInstance().getCollationKey(this.school_name);
CollationKey key2 = Collator.getInstance().getCollationKey(school.school_name);
return key1.compareTo(key2);
}
return 0;
}
(4)第二种方法,实例化TreeSet时传入一个比较器 TreeSetset = new TreeSet(比较器);(★) 比较器有两种方式:第一是 单独自定义类实现Comparator接口 并实现compare(object o1,object o2)方法 第二是 以匿名内部类的方式传入TreeSet new Comparator() {
@Override
public int compare(School s1, School s2) {
if (s1.getSchool_id() != s2.getSchool_id()) {
return s2.getSchool_id() - s1.getSchool_id();
} else if (!s1.getSchool_name().equals(s2.getSchool_name())) {
CollationKey key1 = Collator.getInstance().getCollationKey(s1.getSchool_name());
CollationKey key2 = Collator.getInstance().getCollationKey(s2.getSchool_name());
return key1.compareTo(key2);
}
return 0;
}
});
33.集合与数组的互相转换
(1)集合转数组,用Collection接口中的toArray方法
<1>转为Object的数组 : object[] o = list.toArray();
<2>转为指定类型的数组 : T t = list .toArray(t);
(2)数组转为集合,用Arrays工具类中的asList()方法
String data[] = {"aa","bb"};
Listlist = Arrays.asList(data);
34.CollationKey与Collator的使用:
(1)功能比较汉字比较精确(比String.compareTo()方法精确)
(2)CollationKey key1 = Collator.getInstance().getCollationKey(string1);
CollationKey key2 = Collator.getInstance().getCollationKey(string2);
key1.compareTo(key2);
35.Map的特点:
(1)键值对,key不允许重复,value可以重复,运行时最多有一个null键,可以有无数个null值
(2)Map的Key底层是set, HashMap的key的底层是HashSet TreeMap的key的底层是TreeSet 由此延伸到 HashMap与TreeMap的比较和排序方法.
(3)的常用方法:
增:put(key,value);
删:clear() remove(key)
改,put(key,value);更新key相同的键值对
查:keySet()//返回key组成的set集合 常用于遍历map(★)
values()//返回所有值组成的Collection集合
get(key)//根据键拿值
entrySet()//返回此映射中包含的映射关系的 Set 视图。
判断:ContainsKey(key) ContainsValue(value) isEmpty()
(4)Map的三个子类对比
<1>HashMap:底层是哈希表数据结构。允许使用null键null值,该集合是不同步的。JDK1.2,效率高。
<2>HashTable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。JDK1.0,效率低。一般不用
<3>TreeMap:底层是二叉树数据结构。线程不同步。可以用于给Map集合中的键进行排序。 (5)Map.Entry
<1>Map.Entry是Map的静态内部类
<2>Map.Entry是Map中键值对的对象.
<3>用法:(用于Map的遍历)
MapMap=new HashMap();
Set> set=map.entrySet();
for(Map.Entry> entry:set){
sysout(entry.getkey()+" " +entry.getValue();
}
------------------------------------文件---------------------------------
36.File类的常用方法
(1)new File(String) new File(uri) //给定地址创建File对象
(2)createNewFile(); //创建文件,前提是目录存在
(3)mkdir() makdirs() //创建一层文件夹和创建多长文件夹
(4)exists //判断文件或文件夹是否存在
(5)isFile() //判断是否是文件
isDirectory() //判断是否是文件夹
(6)renameTo(File file) //重命名绝对路径(也可以说是移动/剪切文件)
(7)length() //返回文件的大小
(8)getAbsolutePath() //返回文件的绝对路径
(9)delete() //删除文件或者空文件夹(自动判断是否为空)
(10)String[] list() //返回当前目录下的文件及文件夹的绝对路径
(11)String[] list(FilenameFilter filter) //返回过滤器过滤后的文件或者文件夹
(12)File[] listfiles() //与上雷同
(13)File[] listFiles(FilenameFileter filter);
37.流的分类:
(1)按流的流向分: 输入流和输出流
(2)按处理的数据单位: 字节流和字符流
(3)按功能层次: 节点流和处理流
节点流:直接能处理数据源的流
处理流:不直接操作数据源,而是在已知的流的基础上进行功能扩展的流
----------------------------------流-----------------------------------------------
38.流的分类:
(1)按流的流向分: 输入流和输出流
(2)按处理的数据单位: 字节流和字符流
(3)按功能层次: 节点流和处理流
节点流:直接能处理数据源的流
处理流:不直接操作数据源,而是在已知的流的基础上进行功能扩展的流
39.InputStream 字节输入流 抽象类 不能实例化
(1)read() 每次读取一个字节,返回读到的真实数据
(2)read(byte []b) 每次读取最多b.length个字节,返回的是实际读取的字节数
FileInputStream in = newFileInputStream("路径");
byte[] b = new byte[1024];
int len= 0;
while((len=in.read(b))!=-1){
syso(new String(b,0,len));//每次从文件中最多读取1024字节存入b数组中,
//下次读取后存入b数组,覆盖之前的数据
//当最后一次读取的数据不够1024时,存入数组只能覆盖前面的一部分数据,后面的仍然存才
//此时参数Len就体现了价值.
}
(3)read(byte[] b,0,len);返回的是实际读取的字节数
(4)常用子类
ByteArrayInputStream 内存字节输入流
FileInputStream 文件字节输入流
ObjectInputStream 对象字节输入流
40.OutputStream 字节输出流 抽象类 不能实例化
(1)write(int a) 写入一个字节
(2)write(byte b[])每次写入b.length个字节
(3)write(byte b[],int off,int len) 每次写入Len个字节
(4)常用子类
ByteArrayOutputStream 内存字节输出流
FileOutputStream 文件字节输出流
ObjectOutPutStream 对象字节输出流
41.Reader 字符输入流 抽象类 不能实例化
(1)read() 类似于上面 不同的是 以字符为单位
(2)read(char []b)
(3)read(byte[] b,0.len);
(4)常用子类
BufferedReader 字符输入处理流
StringReader 字符串输入处理流
InputStreamRead 转换流
42.Writer 字符输出流 抽象类 不能实例化
(1)write(int data);
(2)write(char ch[]);
(3)write(char ch[],0,len);
(4)write(String str);//可以直接输出字符串
(5)write(String str,int off,int len);
(6)常用子类
BufferedWriter 字符输出处理流
StringWriter 字符串输出处理流
OutputStreamWriter转换流
43.内存流 ByteArrayOutputStream
ByteArrayInputStream
(1)比字节流和字符流直接操作数据源效率高
44.字节缓冲流 BufferedInputStream
BufferedOutputStream
(1)包裹在字节流外面使用 以提高效率
45.字符缓冲流 BufferedReader
BufferedWriter
(1)包裹在字符流外面使用 以提高效率
(2)readLine()和WriterLine()是这两个方法特有的 可以一次读写整行
46.转化流
(1)InputStreamReader 字节流--->字符流
以字节流从文件中读取数据,通过转化流转化为字符流输入程序
(2)OutputStreamWriter 字符流--->字节流
47.打印流 只能写,不能读
(1)PrintStream 能够自动刷新缓冲区数组
(2)常用方法:print() println() printf() format()
(3)PrintStream ps = new PrintStream(OutputStream out,booleam autoFlush);设置是否自动刷新
(4)PrintsWriter同上
48.重定向流
System.setOut(PrintStream ps);把控制台输出语句重定向到PrintStream指定的文件
注意:必须和ParintStream(打印流)一起用
49.对象流
(1)ObjectOutputStream 把一个基本数据类型或者对象保存到某个文件的过程叫做序列化
(2)ObjectInputStream 把某个文件中的二进制数据重新构造成对象或者基本数据类型的过程称为反序列化
50.随机访问文件流 RandomAccessFile 即能读又能写(★不熟)
(1)可以随机读取,或者写入
(2)直接继承Object类
(3)android应用 多线程下载,
(4)有文件指针,并且可以设置(seek())
(5)获得文件指针:getFilePointer()
---------------------------------------多线程-------------------------------
51.创建和启动多线程的方式(★)
(1)实现Runnable接口
<1>实现Runnable接口,实现run()方法
<2>创建线程对象 MyRunnable runnable = new MyRunnable()
<3>创建Thread对象,接收一个线程对象. Thread thread = new Thread(runnable)
<4>thread.start()启动线程
(2)继承Thread类
<1>继承Thread
<2>重写run()方法
<3>创建线程对象 MyThread myThread=new MyThread();
<4>启动新线程 myThread.start();
52.两种开启多线程的比较
(1)实现Runnable接口
<1>由于是实现接口,所以还可以继承和实现其他接口
<2>可以共享数据
(2)继承Thread类
<1>由于是继承,所以不能再继承其他的类
<2>不能共享数据
53.线程中常用的方法
(1)static Thread currentThread();//获取当前正在运行的线程对象
(2)getName()
(3)setName()
(4)isAlive() 判断线程是否处于活跃状态
(5)getPrority() 获取线程的优先级 ,取值范围是1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )
(6)setPrority() 设置线程的优先级
(7)interrupt() 阻断线程的sleep() join() wait()状态,使线程进入可执行状态
能够改变interrupted的状态, false-->true(擦出状态)--->false
54.线程调度
(1)static sleep(long millis) 使当前线程处于休眠状态
(2)join()合并两个线程A线程调用B线程的join() 则A线程阻塞,等待B线程执行完再执行
相当于方法调用.
(3)static yeild() 让出CPU,给同优先级或者更高优先级的线程先运行,如果CPU空闲则转为就绪状态(就让一下时间很短暂)
56.线程的状态转换(生命周期)
57.线程同步 (个人理解:数据同步)
(1)按照顺序访问某个共享资源
(2)优点:数据安全
(3)缺点:效率低
58.线程异步:
(1)多个线程可同时操作资源
(2)缺点:数据不安全
(3)优点:效率高
59实现线程同步的两种方法
(1)同步方法 用synchronized关键字修饰的方法叫同步方法
(2)同步代码块
<1>用synchronized(){}包裹的代码块叫同步代码块
<2>synchronized(){}的()内传入的数据被上锁,称为监听对象
<3>synchronized(){}的()内可传入this,对象,字符串
60.守护线程(★不熟)
(1)A线程中启动B线程(B为守护线程),则当A线程结束时,B线程也随之结束
(2)用setDaemon(true)设置守护线程
(3)设置守护线程必须在启动前
(4)守护线程的作业:程序收尾,关闭资源
61.线程间的通信
(1)Object提供了三个用于线程通信的方法
(2)wait()让线程处于等待状态
(3)notify()唤醒任意一个正在等待的线程
(4)notifyAll() 唤醒所有正在等待状态的线程
(5)用于生产者消费者模式
62.生产者消费者模式
(1)共享数据的不一致性/临界资源的保护
(2)描述:
<1>有一定大小的容器类用于存储产品,并提供生产方法和消费方法
生产方法:控制生产者在(库存<容量)时生产(notify()),否则休眠(wait())
消费方法:控制消费者在(库存>0)时消费(notify()),否则休眠(wait())
<2>生产者线程类,调用容器的生产方法
<3>消费者线程类,调用容器的消费方法
(3)容器类的关键代码:
int count=100;
public synchronized void sell() {
if (count > 0 && count <= 100) {
try {
notifyAll();
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "出售了第"
+ count + "张车票");
count--;
} else {
try {
System.out.println(Thread.currentThread().getName() + "票已卖完");
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public synchronized void returnT() {
if (count < 100) {
try {
notifyAll();
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
count++;
System.out.println(Thread.currentThread().getName() + "退回了第"
+ count + "张车票");
} else {
try {
System.out.println(Thread.currentThread().getName() + "票还没有卖出");
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
------------------------------------------------TCP和UDP--------------------------------------------
63.基于TCP协议的网络编程
(1)客户端:
<1>创建Socket对象并指定IP地址和端口号(0-65535)
Socket socket = new Socket("10.9.152.168","8080");
<2>打开Socket相关的输入输出流
intputStream = socket.getinput();
outputStream = socket.getoutput();
<3>读取操作
inputStream.read();
outputStream.write();
<4>关闭流 关闭Socket
inputStream.close();
outputStream.close();
socket.close();
(2)服务端:
<1>创建ServerSocket对象,并指定监听的端口
ServerSocket serverSocket = new ServerSocket(8080);
<2>使用accept()方法监听客户端的连接,此方法一直阻塞,当有客户端与其连接时返回Socket对象
Server socket = serverSocket.accept();
<3>打开Socket相关的输入输出流
inputStream = socket.getinput();
outputStream = socket.getoutput();
<4>读写操作
inputStream.read();
outputStream.write();
<5>关闭流 关闭Socket
inputStream.close();
outputStream.close();
socket.close();
64.常见错误:
(1)java.net BindException:Address already in use 端口占用
(2)java.net.ConnectException:Connection refused:connect 服务端没有启动
(3)socket isclosed;socket或者socket相关的流关闭,还调用Socket对象的方法
65.UDP传输的相关知识
(1)DatagramSocket 此类表示用发送和接收数据包的套接字
其中void send(DatagramPacket p)方法用于接收数据包
void receive(DatagramPacket p)方法用于接收数据包
(2)DataGramPacket 数据包 用来实现无连接包投递服务
根据数据包的信息从一台计算机到另一台计算机中
一次次包中需要封装一个地址(IntAddress)
(3)InetAddress IP地址类其中与一些静态方法用于f封装IP对象
getByAllName(String host) 给定主机名获取IP对象即(InetAddress实例)
getByAddress(byte[] addr) 给定原始IP获取InetAddress对象
getByName(String host)在给定主机名的情况下获取InetAddress对象
66.UDP传输的步骤:
发送端:
(1)用DatagramSocket创建UDP服务
DatagramSocket ds = new DatagramSocket();//可传入端口号,也可不传入
(2)封装InetAddress对象
InetAddress address = InetAddress.getByName("192.168.1.3");
(3)准备要发送的数据,并封装成数据包
byte[] buf = "字符串".getBytes();
DatagrmPacket dp = new DatagramPacket(buf,buf,length,address,8080);
(4)用DatagramSocket的send方法发送数据包
ds.send(dp);
ds.close();
服务端:
(1)用DatagramSocket创建UDP服务 并监听端口
DatagramSocket ds= new DatagramSocket();//必须指定端口
(2)定义数据包用于存储接收的数据包
byte[] buf=new byte[1024]//数组的大小是估计值
DatagramPacket dp = new DatagramPacket(buf,buf.length);
(3)通过DatagramSocket的receive的方法接收数据包并存入dp中
ds.receive(dp);
(4)通过DatagramPacket中的方法解析数据包
String data = new String(dp.getData(),0,dp.getLength);
(5)最后关闭资源
ds.close();
------------------------------------sqlite/sql-----------------------------------
67.sqlite3常用命令
(1)sqlite3 数据库名称(有则打开,无则创建)
.open 数据库名称(有则打开,无则创建);
(2).database 显示数据库的列表
(3).table 或者.tables显示当前数据库中所有的表
68.常用SQL语句
(1)create table 表名(字段名 数据类型,字段名 数据类型...);------创建表
(2)drop table 表名 -------删除该表
(2)insert into 表名 values(按字段顺序的所有字段信息);
insert into(要插入的字段) 表名 values(要查入的字段信息,跟前面的顺序对应)----插入一条记录
(3)select * from 表名;----查询该表的所有信息
(4)select * from 表名 where (控制条件) ----按条件查找
(5)select * from 表名 where like '%单词%' ----模糊查找
%代表0个或多个字符
_代表一个字符
(6)select * from 表名 where id=2 and name="jack" and表示与
select * from 表名 where id=1 or name="jack" or表示或
(7)聚合函数
select count(*) from 表名 ---查询所有记录的条数(即行数)
select max(字段) from 表名---查询某个字段的最大值
select min(字段) from 表名---查询某个字段的最小值
select avg(字段) from 表名---查询某个字段的平均值
(8)排序查询
select * form 表名 order by 字段 -----按照升序排序 (默认asc)
select * form 表名 order by 字段 desc------按照降序排序
(9)update 表名 set 字段=新值,字段=新值 where (条件) ----修改指定条件的记录的指定字段
(10)delete from 表名----删除所有数据
(11)delete from 表名 where (条件) ----删除指定数据
(12)住键:primary key
自增长:autoincrement 该字段必须是Integer类型
用法举例:crate table test(id integer primary key autoincrement,name string);
-----------------------------------反射-----------------------------------
69.反射
(1)类可以new出对象,但类本身也是一个对象
当类被加载后jvm会为这个类创建一个Class对象
(2)获得类的class对象的三种方法:
<1>使用Class类的forName("类的权限定名")静态方法(常用此方式降低耦合度)
例如:Class.forName("org.lang.String"); //加载类并返回该类的Class对象
<2>使用某个类的class属性来获得该类的Class对象
例如:Class clazz = Person.class
<3>调用对象的getClass()方法,该方法是Object中的一个方法
例如:Person person = new Person();
Class clazz = person.getClass();
(3)获得某个类的class对象后 可以获取该类中的各种信息,即使私有的也可以获得
<1>获取所有构造器
Class中有一系列获取类中构造器的方法 返回一个Connstructor 例如:ConstructorgetConstructor(Class... parameterTypes) 根据指定参数类型列表返回指定的构造器 Constructor[] getConstructors() 返回所有公共构造器的数组 ConstructorgetDeclaredConstructor(Class... parameterTypes)//对应上面的该方法返回的是所有的 包括私有的
Constructor[] getDeclaredConstructors()
Construction类有一系列获得该构造方法信息的方法
并且有newInstance()方法来new出指定类的实例(重点)
<2>获取指定类中的方法
Method getMethod(String name, Class... parameterTypes) //根据参数类型列表返回方法的对象
Method[] getMethods() //返回公共方法的数据
Method getDeclaredMethod(String name, Class... parameterTypes)
Method[] getDeclaredMethods()
Method类中有一系列方法来获取指定类中方法的信息
<3>获取指定类中的属性
Field getDeclaredField(String name) //根据属性名返回File对象
Field[] getDeclaredFields() //返回
Field getDeclaredField(String name)
Field[] getDeclaredFields()
Filed类有一系列方法 来获取该属性的信息
getName() //返回此 Field 对象表示的字段的名称。
get(Object object)
getXXX(Object object) //返回指定对象上的该Field属性的值
如果底层Field是静态属性,则忽略object参数
set(Object object)
setXxx(Object object, Xxx value) //给指定对象上的该Field属性赋值
如果底层Field是静态属性,则忽略object参数
setAccessible(boolean boolean) //Field从AccessibleObject中继承的方法,将此对象的 accessible 标志设置为指示的布尔值。
值为 true 则指示反射的对象在使用时应该取消 Java 语言访问检查。
值为 false 则指示反射的对象应该实施 Java 语言访问检查。
简单来说,set(Object object)之前必须将此方法设置为true
<4>获取Class对象中的成员类(内部类)和成员接口(内部接口)
Class[] getClasses() //返回一个包含某些 Class 对象的数组,
这些对象表示属于此 Class 对象所表示的类的成员的所有公共类和接口。
Class[] getDeclaredClasses() // 返回 Class 对象的一个数组,
这些对象反映声明为此 Class 对象所表示的类的成员的所有类和接口。
-----------------------------------JDBC-----------------------------------
70.JDBC总结 以sqlite为例(需要导第三方jar包)
通用步骤:
(1)加载数据库驱动
Class.forName("org.sqlite.JDBC"); //固定格式
(2)获得与指定数据库的连接 通过DriverManager类连接
Connection connection = DriverManager.getConnection("jdbc:sqlite://D://db//mydb.db");
(3)获取SQL基本语句对象Statement
Statement statement = connection.creatStatement();
(4)调用Statement中的一系列方法来操作数据库
ResultSet resultSet = statement.executeQuery("select * from Student");
(5)关闭连接
connection.close();
(6)Statement类的介绍:用于执行静态SQL语句并返回它所生成的对象
ResultSet executeQuery("") //通常执行查询语句 返回结果集
int executeUpdate("")//通常执行更新语句 插入语句 和 删除语句 或者不返回任何信息的SQL语句
返回行计数(即更新行数),什么都不返回的SQL语句返回0
(7)ResultSet类的介绍:表示数据库结果集的数据表(即表的对象)(★不熟)
光标初始位置在第一行的前面
next()将光标从当前位置向前移动一行
------------------------------------HTTP----------------------------------
71.HTTP协议总结
(1)HTTP协议的概述
HTTP协议用于定义客户端与web服务器通迅的格式。
HTTP是hypertext transfer protocol(超文本传输协议)的简写,它是TCP/IP协议的一个应用层协议
HTTP使用请求-响应的方式进行传输,一个请求对应一个响应,并
且请求只能是由客户端发起的。
HTTP协议的版本:HTTP/1.0、HTTP/1.1,其中1.0一次请求发起一次连接,响应过后连接自动断开。1.1里每次请求
(2)HTTP协议请求的格式:
请求行(Request-Line)例如:GET/imagees/logo.gifHTTP/1.1,表示从/images目录下请求logo,gif文件
请求头 例如:Accept_Language:e(很多请求头);
空行 必须的,服务通过这个空行来区别请求头和请求体
请求体 有时候也叫消息体,是可选的,GET请求时无请求体,Post请求有
实例:
REquest_Line:GET /books/java.html HTTP/1.1 //请求行 请求方式请求资源名 协议名
其中GET方式在请求资源的URL后跟“?参数名=参数值&参数名=。。。”方式传递参数,传输的数据内容最大为1K
其中POST方式在请求实体中传输数据
除了用Form表单明确用method指定用post方式提交数据以外,其他的方式都是GET提交方式
Accept:text/html,image/*告诉服务器客户端可以接受的数据类型 */*表示什么类型都可以
Accept-Encoding:gzip,deflate 支持的压缩格式.
Accept-Language:zh-cn 当前客户端支持的语言
Connection:Keep-Alive 客户端支持的链接方式,当请求完成后保持一段时间默认为3000ms
Cookie:JSESSIONID=AF6FB5136BCCfdkljfafj
Host:localhost:8080 请求的地址和端口号
User-Agent:mazilla/4.0(fsajfsalkfjdsafsk) 与浏览器和OS相关的信息。大家看到有些网站会显示用户的系统版本和浏览器版本信息,这都是通过获取User-Agent头信息而来的;
请求体:
(3)HTTP协议相应的格式:
HTTP/1.1 200 OK //状态行 HTTP版本号 状态吗 原因叙述
常见状态码:200:请求处理成功 302请求重定向 304 307服务器通知浏览器使用缓存
404 资源找不到
500 服务器端代码错误
若干响应头:
Location:http://www.it315.org/index.jsp 配合302实现请求重定向
Server:apache tomcat 服务器的基本信息
Conten-Encoding:gzip 服务器发送数据时使用的压缩格式
Content-length:80 发送数据的大小
Content-Language:zh-cn 发送的数据使用的语言环境
Content-Type:text/html;charset=GB2312 当前所发送的数据的基本信息
Last-Modified:Tue,11 jul 2000 缓存相关的头
Refresh: 1;url=http://www.it315.org 通知浏览器进行定时刷新,此值可以是一个数字指定多长时间以后刷新当前页面,这个数字之后也可以接一个分号后跟一个URL地址指定多长时间后刷新到哪个URL
Content-Disposition: attachment;filename=aaa.zip 与下载相关的头
Transfer-Encoding: chunked 传输类型,如果是此值是一个chunked说明当前的数据是一块一块传输的
Set-Cookie:SS=Q0=5Lb_nQ; path=/search 和cookie相关的头,后面课程单讲
ETag: W/"83794-1208174400000" 和缓存机制相关的头
Expires: -1 指定资源缓存的时间,如果取值为0或-1浏览就不缓存资源
Cache-Control: no-cache 缓存相关的头,如果为no-cache则通知浏览器不缓存
Pragma: no-cache 缓存相关的头,如果为no-cache则不缓存
以上三个头都是用来控制缓存的,是因为历史原因造成的,不同的浏览器认识不同的头,我们通常三个一起使用保证通用性。
Connection: close/Keep-Alive 是否保持连接
Date: Tue, 11 Jul 2000 18:23:51 GMT 当前时间
相应体
72.URL 统一资源定位符 是指向互联网"资源"的指针
由protocol(协议名称) host(主机名) Port(主机端口号) File(主机上的文件) 构成
(1)常用的构造方法: URL(String spec)
URL(String protocol,String host,int Port,String File)
(2)常用方法:一系列get方法 获得 协议名 主机名 端口号 文件名称等
getprotocol() getHost() getPort() ......
openConnection()返回一个URlConnection对象 它表示到Url所引用的远程对象的连接
HttpURLConnection方式请求网络的主要步骤
73.HTTP请求网络的两种方式(GET POST)
(1)GET:
<1>get主要是从服务器上获取数据
<2>get请求参数能在地址栏显示
<3>get传送的数据量较小,不能大于2kb
<4>get安全性非常低,但效率高
(2)POST:
<1>Post主要是向服务器传送数据
<2>POST是通过Http Post机制,将表单内各个字段与其内容放置在HTML内一起传送到ACTION属性所指的URL地址,地址栏不显示
<3>Post传送的数据较大
<4>Post安全性高,但效率低
74.HttpURLConnection请求网络通用步骤:
android6(API 23)大量使用此方式请求网络
API标准步骤:
(1)通过在 URL 上调用 openConnection 方法创建连接对象。
(2)处理设置参数和一般请求属性。
(3)使用 connect 方法建立到远程对象的实际连接。
(4)程对象变为可用。远程对象的头字段和内容变为可访问。
(1)创建URL对象
URL url = new ("地址");//当GET请求时需要带参数
(2)通过url上的openConnection方法创建HttpUrlConnection对象
HttpUrlConnection httpUrlConnection = (HttpURlConnection)url.openConnection();
(3)设置请求参数
httpurlConnection.setRequestMethod("GET/POST");//GET/POST必须大写
httpurlConnection.setDoinput(ture);//默认为true
(4)使用connect方法建立到远程对象的实际连接 底层TCP连接
httpUrlConnection.connect();
(5)获得响应码,并判断,响应吗为200时请求成功
int code httpurlconnection.getResponseCode();
(6)获取对象的输入/输出流,进行传递数据
InputStream inputstream = httpurlconnection.getInputStream();
//Post请求时需要用输出流 必须调用httpUrlConnection.setDoOutput(true);(默认是false)
OutputStream outputStream = httpurlconnection.getOutputStream();
75.HttpClient请求网络:android6之后需要导入jar包
(1)创建HttpClient对象 HttpClient httpClient=new DefaultHttpClient(); //HttpClient为抽象类 需要new其子类
(2)创建请求方式 并指定地址 HttpGET/HttpPost HttpGET httpget = new HttpGet("地址");//包含参数 HttpPost httpPost = new HttpPost("地址");//不包含参数
(3)通过httpget/HttpPost设置请求参数
(4)如果为HttpPost请求 需要封装请求数据 Listlist= new ArrayList();
list.add(new BasicNameValuePair("属性","值");
list.add(new BasicNameValuePair("属性","值");
....
HttpEntity requestEntity = new UrlEncodeFormEntity(list,"编码格式");//将请求数据封装到HttpEntity
httppost.setEntity(requestEntity);//将封装好的请求数据设置到httppost中
(5)执行请求,返回响应对象HttpResponse
HttpResponse response=httpClient.excute();
(6)获取响应码 并判断
int code=response.getStatusLine().getStatusCode();
(7)获得服务端和客户端传递的载体对象
HttpEntity entity = response.getEntity();
(8)通过entity获得输入流
InputStream inputStream = entity.getContent();
(9)EntityUtils提供了一系列获取数据的工具
<1>获取字符串信息
String string = EntityUtils.toString(entity);
<2>获取图片类型的
byte[] b = EntityUtils.toByteArray(entity);
-----------------------------------------XML解析--------------------------------------
76.SAX解析
(1)继承DefaultHandler类重写startElement(),endElement(),characters()等方法编写自己的解析逻辑
public MyHandler extends DefaultHandler{
String nowTag="";
public void startElement(String uri,String localName,String qName,Attributes attributes)
throws SAXException{
//解析到开始标签时触发次方法,
//qName--该标签的名字
//Attributes本标签的属性对象,相当于一个键值对组成的数组
可以根据下标获得键名和值 可以根据键名获得值 还以获取属性的总数
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
//解析到结束标签时触发该方法
}
public void characters(char[] ch, int start, int length)
throws SAXException {
//解析到文本内容时触发次方法
//注意空白内容和换行等垃圾字符
}
}
(2)用SAXParserFactory中的静态方法创建拿到解析工厂类(单例模式)
SAXParserFactory factory = SAXParserFactory.newInstance();
(3)通过解析工厂对象创建解析器对象
SAXParser parser = factory.new SAXParser();
(4)调用解析器的parser()为解析器关联要解析的对象和handler对象,同时进行解析
MyHandler handler = new MyHandler();
parser.parse("weather.xml"或inputStream,handler);
77.pull解析
(1)用XmlPullParserFactory中的静态方法创建解析工厂(单例模式)
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
(2)通过解析工厂对象创建解析器对象
XmlPullParser parser = factory.newPullParser();
(3)调用解析器的setinput方法为解析器关联目标流
parser.setInput(字符流);
(4)循环用parser.getEventType()获取节点标识码,判断节点标识码来解析
int code = parser.getEventType();
while(code!=XmlParser.END_DOCUMENT){
String string = parser.getName();//获取本节点的名字
switch(code){
case XmlPullParser.START_TAG:
.....
parser.nextText();//获取下一个节点的文本信息
.....
parser.getAttributeCount();//获取本节点的属性个数
parser.getAttributeName(index);//根据属性下标获取属性名
parser.getAttributeValue(index);//同上
break;
case XmlPullParser.END_TAG:
break;
case XmlPullParser.START_TAG:
break;
}
code = parser.next();//获取下一个节点的标识码(容易遗漏)
}
-------------------------------------json解析----------------------------------
78.json的数据格式:
{name:chx,age:22,sex:男}-----大括号对应一个对象,键值对中间用冒号隔开
[{name:chx,age:22,sex:男},{name:chx2,age:23,sex:男}]-------中括号对应数组,里面可包含若个对大括号
79.JSON解析
(1){}对应JSONObject类
[]对应JSONArray类
(2)JSONObject类的用法:
<1>new JSONObject("{JSON字符串}")---JSON字符串最外层必须是{}
<2>Object get(String key) //根据key得到value
<3>Object opt(String key) //同上
<4>xxx getXXX(String key) //根据key得到指定数据类型的value
<5>put(String key,Object o);//向json字符串中添加一个key-value对
<6>getJSONObject(String key)/optJSONObject(String key) //根据key得到JSONObject对象
<7>getJSONArray(String key)/optJSONObject(String key) //根据key得到JSONOArray对象
(3)JSONArray类的用法:
<1>---<7>同JSONObject雷同
<8>length();//获得JSONArray中的JSONObject的个数
<9>get/opt/put 增加了可以根据下标操作对象的方法
80.GSON解析
(1)GSON是谷歌公司封装的一套json解析的工作集,其中了反射机制
(2)toJSON(Object) //将具体的对象转为json字符串
(3)fromJson(字符串/流,json中对应的JavaBean)//第二个参数必须有并且要一一对应
(4)当包含集合时需要借助TypeToken类----抽象类
TypeToken> typeToken = new TypeToken() {};
typeToken.getType();
81.FastJSON解析
(1)阿里巴巴封装的一套json解析的工具集,使用了反射机制
(2)主要类是JSON类--相当于一个工具类 其中有一系列parsexxx方法和一系列toxxx方法
(3)JSON.toJSONString(javaBean);//将java对象转换为json字符串 即使传入的是对象的集合
(4)JSON.parseObject(jsonString/流,Class);//将字符串转换为具体的对象,也可直接转为对象的集合,但第二个参数必须传入类型
(5)JSON.parseArray//同JSON.parseObject雷同
82.json解析的一般规律
(1)一般服务端响应的json数据,第一层大部分为json对象,
包含的内容格式:{result:"success",totalPage:190,curPage:1,datas:[{},{},{}] }
(2)GSON/FastJSON 优点:速度快,代码少.可忽略JavaBean中没有的属性
缺点:JavaBean中的属性与json字符串的键必须一致
JavaBean必须有无参构造方法和get,set方
(3)JSON 优点:可继续无规律的数据
完全根据json字符串解析 不受javaBean的约束
缺点:代码繁琐