一、枚举类型
(一)概念
1、就是描述对象个数是有限个的类型
2、声明一个枚举类型,使用关键字enum。枚举类型声明出来也是一个类型,编译过后也是一个.class文件
(二)自己实现枚举的第一种格式和使用枚举格式完成
1、自己实现:使用老汉式,在一个类中多定义几个对象就是枚举
2、枚举实现:
(1)使用enum关键字声明一个枚举类型
(2)在枚举类型中,声明罗列各个对象的名称
(3)在声明罗列各个对象时,对象之间使用逗号隔开,结束用分号结尾
(4)在枚举类型中的各个对象,叫做【枚举项】
//第一种自己实现枚举
public class meiju01 {
public static void main(String[] args) {
System.out.println(Week.MON);
}
}
/*class Week{
private Week() {}
public static final Week MON = new Week();
public static final Week TUE = new Week();
public static final Week WED = new Week();
}*/
enum Week{
MON,TUE,WED;
}
自己实现枚举的第二种格式和使用枚举格式完成
1、自己实现:加入一个成员变量
2、枚举实现:
(1)使用enum声明一个枚举类型
(2)在枚举类型中声明一个成员变量
(3)可以为成员变量提供get、set方法
(4)构造方法也可以提供,但必须是私有的
(5)在枚举类型的第一行,提供枚举项
public class meiju02 {
public static void main(String[] args) {
Week02 w = Week02.MON;
System.out.println(w.getWeek());
}
}
/*class Week02{
private String week;
private Week02() {}
public Week02(String week) {
super();
this.week = week;
}
public String getWeek() {
return week;
}
public void setWeek(String week) {
this.week = week;
}
public static final Week02 MON = new Week02("星期一");
public static final Week02 THU = new Week02("星期二");
public static final Week02 WED = new Week02("星期三");
}*/
enum Week02{
MON("星期一"),THU("星期二"),WED("星期三");
private String week;
private Week02() {}
public String getWeek() {
return week;
}
public void setWeek(String week) {
this.week = week;
}
private Week02(String week) {
this.week = week;
}
}
自己实现枚举的第三种格式和使用枚举格式完成
1、自己实现:在类中,再添加一个抽象方法
2、枚举实现:
(1)使用enum声明一个枚举类型
(2)在枚举类型中,声明一个成员变量
(3)提供成员变量的get、set方法
(4)枚举类型中定义一个抽象方法
(5)枚举项必须写在第一行,并且,枚举项使用匿名内部类的格式实现枚举类型中的抽象方法
package com.huzheng.demo;
public class meiju03 {
public static void main(String[] args) {
Week03 w = Week03.MON;
w.show();
}
}
/*abstract class Week03{
private String week;
private Week03() {}
public Week03(String week) {
super();
this.week = week;
}
public String getWeek() {
return week;
}
public void setWeek(String week) {
this.week = week;
}
public static final Week03 MON = new Week03("星期一") {
@Override
public void show() {
// TODO Auto-generated method stub
System.out.println(getWeek());
}
};
public static final Week03 TUE = new Week03("星期二") {
@Override
public void show() {
// TODO Auto-generated method stub
System.out.println(getWeek());
}
};
public static final Week03 WED = new Week03("星期三") {
@Override
public void show() {
// TODO Auto-generated method stub
System.out.println(getWeek());
}
};
public abstract void show();
}*/
enum Week03{
MON("星期一"){
@Override
public void show() {
// TODO Auto-generated method stub
System.out.println(getWeek());
}
},TUE("星期二"){
@Override
public void show() {
// TODO Auto-generated method stub
System.out.println(getWeek());
}
},WED("星期三"){
@Override
public void show() {
// TODO Auto-generated method stub
System.out.println(getWeek());
}
};
private String week;
private Week03() {}
private Week03(String week) {
this.week = week;
}
public String getWeek() {
return week;
}
public void setWeek(String week) {
this.week = week;
}
public abstract void show();
}
(五)枚举类型的常用方法
1、所有使用enum关键字声明的枚举类型,全都是Enum类型的子类
2、常用方法:
(1)compareTo(E o) 比较两个枚举类型的顺序
(2)ordinal() 返回枚举常量的序数
(3)toString() 返回枚举项的名称,该方法在Enum类中已经重写过了,自定义的enum无法重写
(4)values() 返回一个数组,数组中的元素是枚举类型的所有枚举项(API中没有,在编译的时候由系统提供,是一个静态方法)
public class meiju04 {
public static void main(String[] args) {
Week04 mon = Week04.MON;
Week04 tue = Week04.TUE;
Week04 wed = Week04.WED;
System.out.println(mon.getName());
System.out.println(mon.compareTo(tue));//-1
System.out.println(mon.compareTo(wed));//-2
System.out.println(mon.ordinal());//0
System.out.println(tue.ordinal());//1
System.out.println(wed.ordinal());//2
System.out.println(mon.toString());//MON
Week[] values = Week.values();
for (Week week : values) {
System.out.println(week);//MON TUE WED
}
}
}
enum Week04{
MON("星期一"),TUE("星期二"),WED("星期三");
private Week04() {}
private String name;
private Week04(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
二、网络编程
网络编程:在已经拥有的完备成熟的网络系统中,在整个系统之上,使用网络进行编程,是针对应用层的设计活动。
(二)IP地址
1、IP地址是计算机在网络中的唯一标志
2、分类:
(1)IPV4:
1)构成:点分十进制的构成,由4个0~255的数组组成,来表示一个IP地址,4个字节即32位,能够表示约40亿个IP地址
2)四个字节中,有2个字节或者3个字节表示所在的子网
3)一个字节能表示0~255一共256个数字,但是不能全用
4)0表示子网网号:192.168.1.0就表示当前子网
5)255表示广播地址:广播地址发送的内容所在子网内的所有设备都能接收
6)特殊IP:127.0.0.1,表示本地回环地址,可以访问本机
7)相关命令:ipconfig查看当前网卡信息
8)ping:可以产看网络是否联通
(2)IPV6:
1)构成:由8组数字组成,每组数字都是4个16进制数字,每个数字有16中状态,32个数字,最多能表示16^32个IP地址
2)号称能给地球上每一粒沙子都给一个IP地址
(三)端口号
1、也是一个数字,用于标记一台电脑中的某个进程
2、端口号的取值范围:0~65535
3、意味着计算机中至多能够运行65536个进程,当程序运行的时候,计算机会分配一个独一无二的端口号给进程,我们通过端口号,就可以找到指定的进程,当进程结束时,端口号会被回收
4、分配:可以计算机随机分配,也可以用户指定
5、常用的端口号:
(1)操作系统:0~1024之间
(2)MySQL:3306
(3)Tomcat:8080
(4)QQ:4000
(5)Oracle:1521
(四)通信协议
1、用于定义通信双方在交互时,对信息的封装和解析的规则,就是协议
2、网络分层:分工,每一层都可以做独立的事情
(1)应用层:http、https协议等(规定数据如何封装以及解析)
(2)传输层:UDP协议、TCP协议(更多关注的是端对端的传输)
(3)网络层:IP地址(如何完成两台设备之间的传输)
(4)物理层:底层的硬件设备、数据完整性的校验
四、InetAddress类
1、InetAddress类的对象表示IP地址
2、对象获取方式:
(1)getByName(String host) 根据主机名称返回对象包含IP地址
(2)getByAddress(byte[] addr) 给定装有ip地址的数组,返回InetAddress类对象
(3)getAllByName(String host) 根据主机明后才能获取所有当前类型对象的数组
(4)getLocalHost() 获取本机的主机名和IP地址的对象
3、常用方法:
(1)getHostName() 获取主机名称
(2)getAddress() 获取IP地址的字节数组
(3)toString() 获取主机名称和IP地址的字符串表示形式
public class Demo08_InetAddress {
public static void main(String[] args) throws UnknownHostException {
InetAddress host = InetAddress.getLocalHost();
System.out.println(host.getHostName());
byte[] arr = host.getAddress();
for (byte b : arr) {
System.out.println(b);
}
System.out.println(host.toString());
}
public static void test1() throws UnknownHostException {
InetAddress name = InetAddress.getByName("Zihuatanejo-PC");
System.out.println(name);
byte[] arr = {10, 10, 60, (byte) 177};
InetAddress address = InetAddress.getByAddress(arr);
System.out.println(address);
InetAddress[] arr1 = InetAddress.getAllByName("Zihuatanejo-PC");
for (InetAddress ele : arr1) {
System.out.println(ele);
}
InetAddress host = InetAddress.getLocalHost();
System.out.println(host);
}
}
五、UDP协议和TCP协议
(一)概述
1、UDP协议和TCP协议都是传输层协议,都是端到端的协议
2、区别:
(1)UDP协议:面向无连接。像发短信、送信、寄快递等都是面向无连接。效率高,不安全,先发送的消息未必先收到。只区分发送端和接收端,而不像TCP协议区分客户端和服务器端。
(2)TCP协议:面向连接。打电话,先发送的消息一定先到达,安全,效率低,区分客户端和服务器端。在连接的时候,要经理三次握手。
(二)Socket编程
1、Socket:是两台计算机之间的通信端,类似生活中的快递站、邮局、码头
2、Socket也叫作套接字,套接字编程:网络编程、通信点编程
(1)UDP中要是用到的套接字是:DatagramSocket
(2)在TCP协议中,客户端要使用的是Socket,服务器端要是用的是ServerSocket和Socket
(三)UDP编程
1、要用到的通信点:DatagramSocket
2、构造方法:
(1)DatagramSocket() 不指定端口号,直接创建通信点对象,端口号随机分配,一般用于发送端
(2)DatagramSocket(int port) 指定端口号,创建通信点对象,一般用于接收端
3、成员方法:
(1)send(DatagramPacket p) 将一个数据报包进行发送
(2)receive(DatagramPacket p) 从通信点接收数据报包
4、数据报包:DatagramPacket
(1)构造方法:
1)DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port) 发送端
buf:要发送的数据的字节数组
offset:从数组的哪个位置开始发送数据
length:发送多少数据
address:IP地址
port:端口号
2)DatagramPacket(byte[] buf, int length) 接收端
(2)成员方法:
1)getData() 将接收到的byte[]数组从数据报包中解析出来
2)getLength() 返回发送了或者接收到的数据的长度
public class UDP_Send {
public static void main(String[] args) throws IOException {
//1.创建发送端的通信点对象
DatagramSocket ds = new DatagramSocket();
//2.准备数据报包
byte[] buf = "闪电鞭".getBytes();
int offset = 0;
int length = buf.length;
InetAddress address = InetAddress.getLocalHost();
int port = 8848;
DatagramPacket dp = new DatagramPacket(buf, offset, length, address, port);
//3.通过通信点对象将数据报包发送出去
ds.send(dp);
}
}
public class UDP_Receive {
public static void main(String[] args) throws IOException {
//1.创建接收端的通信点对象
DatagramSocket ds = new DatagramSocket(8848);
//2.使用通信点对象接受网络中的数据
byte[] buf = new byte[1024];
int length = buf.length;
DatagramPacket dp = new DatagramPacket(buf, length);
ds.receive(dp);
//3.从数据报包中将数据解析出来
byte[] data = dp.getData();
int len = dp.getLength();
//4.打印数据
System.out.println(new String(data, 0, len));
}
}
(四)TCP编程
1、客户端要使用的是Socket,服务器端要是用的是ServerSocket和Socket
2、客户端和服务器端Socket对象的区别:
(1)客户端使用Socket的构造方法直接创建Socket对象
(2)服务器端不能直接使用Socket创建通信点对象,而是通过ServerSocket对象,从端口捕获客户端的响应,专门为这个客户端生成一个Socket对象
3、构造方法:
(1)Socket(InetAddress address, int port) 创建一个通信点对象,专门用于和制定IP的主机中指定的进程进行通信
(2)只要这个对象创建成功,就说明这个连接已经建立好了,也就说明客户端已经连接上了服务器端了,也就已经获取到了服务器返回的响应了
(3)创建对象的过程,就是在请求和服务器连接的过程
(4)ServerSocket(int port) 创建一个服务器通信点对象
(5)ServerSocket要配合accept()方法使用
(6)accept()方法是专门用于接收客户端请求,并且返回一个对应Socket对象的方法
4、传输操作:
(1)getOutputStream() 返回此套接字的输出流
(2)getInputStream() 返回此套接字的输入流
(3)一旦获取到IO流对象,就变成了以IO的方式传输
5、关系:
(1)客户端发送请求给服务器:客户端将请求从本机内存输出到网络,要用输出流
(2)服务器接收客户端传来的响应:服务器将网络中的请求读取到服务器的内存,要用输入流
public static void main(String[] args) throws UnknownHostException, IOException {
//1.创建Socket对象,即客户端通信点对象
Socket s = new Socket("127.0.0.1", 9999);
//2.获取输出流对象,用于将请求从客户端内存传入网络
OutputStream os = s.getOutputStream();
//3.使用输出流将要传输的内容进行输出
byte[] b = "松活弹抖闪电鞭".getBytes();
os.write(b);
s.close();
}
}
public class TCP_Server {
public static void main(String[] args) throws IOException {
//1.创建服务器套接字对象,绑定到指定端口
ServerSocket ss = new ServerSocket(9999);
//2.调用accept方法捕获并且针对当前客户端创建Socket对象
Socket s = ss.accept();
//3.获取套接字的输入流对象,用于将网络中的请求,输入进服务器的内存中
InputStream is = s.getInputStream();
byte[] b = new byte[1024];
int len = is.read(b);
//4.将请求解析为文字并打印
String request = new String(b, 0, len);
System.out.println(request);
s.close();
}
}
(五)TCP加强
public class TCP_ClientPlus {
public static void main(String[] args) throws UnknownHostException, IOException {
//1.创建Socket对象
Socket s = new Socket(InetAddress.getLocalHost(), 9898);
//2.获取输入流和输出流对象
//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));
PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
//3.键盘录入要发送的请求,通过高效缓冲字符输出流发送出去
Scanner sc = new Scanner(System.in);
String request = sc.nextLine();
pw.println(request);
//4.通过高效缓冲字符输入流用于读取请求
String response = br.readLine();
System.out.println(response);
s.close();
}
}
public class TCP_ServerPlus {
public static void main(String[] args) throws IOException {
//1.创建ServerSocket对象用于监听端口号
ServerSocket ss = new ServerSocket(9898);
while (true) {
//2.调用accept方法获取请求并建立连接
Socket s = ss.accept();
new Thread() {
@Override
public void run() {
try {
//3.获取流对象
BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter pw = new PrintWriter(s.getOutputStream(), true);
//4.输入流读取请求
String request = br.readLine();
System.out.println(request);
//5.键盘录入响应并通过流进行返回
Scanner sc = new Scanner(System.in);
String response = sc.nextLine();
pw.println(response);
s.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}.start();
}
}
}
print 和 println 底层都使用write方法,只是 println 多加了个‘ \n ’ ,在PrintWrite类中【PrintWriter(OutputStream out, boolean autoFlush) 通过现有的 OutputStream 创建新的 PrintWriter】 在Java中只有println才可以刷新输出缓冲区