(25)网络编程
- ipconfig //查看本机IP
- ping //测试连接
-
每个网络程序都要绑定一个端口号,范围(0-65535)
编写网络应用就需要绑定一个端口号,尽量使用1024以上的,1024以下的基本上都被系统占用了
常用端口:
mysql:2206 oracle:1521 web:80 tomcat:8080 QQ:4000 feiQ:2425
-
网络编程三要素协议:为计算机网络中进行数据交换而建立的规则、标准或约定的集合
UDP: 面向无连接,数据不安全,速度快;不区分客户端与服务端
TCP: 面向连接(三次握手),数据安全,速度略低,分为客户端和服务端
三次握手:客户端先向服务端发起请求,服务端响应请求,传输数据
-
Socket 套接字
网络上具有唯一标识的IP地址和端口号组合在一起才能构成唯一能识别的标识符套接字
通信的两端都有Socket;网络通信其实就是Socket间的通信;数据在两个Socket间通过IO流传输
Socket在应用程序中创建,通过一种绑定机制与驱动程序建立关系,告诉自己所对应的IP和port
-
UDP:
6.1 发送send
创建DatagramSocket 随机端口号
DatagramSocket socket = new DatagramSocket();
创建DatagramPacket 指定数据,长度,地址,端口
new DatagramPacket(str.getBytes(), str.getBytes().length, InetAddress.getByName("127.0.0.1"), 6666);
使用DatagramSocket发送DatagramPacket
socket.send(packet);
关闭DatagramSocket socket.close();
6.2 接收receive
创建DatagramSocket 指定端口号
DatagramSocket socket = new DatagramSocket(6666);
创建DatagramPacket 指定数组,长度
使用DatagramSocket 接收 DatagramPacket
关闭DatagramSocket
-
TCP协议:
7.1客户端
Socket socket = new Socket(指定ip,端口);
InputStream is = new socket.getInputStream(); //获取客户端输入流 优化后:用BufferedReader包装
OutputStream os = new socket.getOutputStream(); //获取客户端输出流 优化后:用PrintStream包装
byte[] arr = new byte[1024];
int len = is.read(arr); //读取服务器发来的数据
syso(new String(arr,0,len)); //将数据转换成字符串打印
os.write("****".getBytes()); //客户端向服务器写数据
socket.close(); //流也会一起关闭
7.2服务端
ServerSocket server = new ServerSocket(7.1中的端口);
Socket socket = sever.accept(); //接受客户端的请求
InputStream is = new socket.getInputStream(); //获取服务端输入流 优化后:用BufferedReader包装
OutputStream os = new socket.getOutputStream(); //获取服务端输出流 优化后:用PrintStream包装
os.write("***".getBytes()); //服务器向客户端写出数据
byte[] arr = new byte[1024];
int len = is.read(arr); //读取客户端发过来的数据
syso(new String(arr,0,len)); //将数据转换成字符串并打印
socket.close(); //流也会一起关闭
服务端 可以用while(true){} 循环接收客户端的请求,然后用匿名内部类创建线程,在run方法中,获取输入输出流
(26)反射&JDK新特性
一.反射
-
源文件阶段 *.java文件
Class clazz = Class.forName("类名"); //作用:读取配置文件
-
字节码阶段 *.class文件
Class clazz = 类名.class //作用:当作静态方法的锁对象
-
创建对象阶段 new *();
Class clazz = 引用.getClass(); //该引用指向的就是上边的类 作用:判断是否是同一个字节码对象
- Person p = (Person)clazz.newInstance(); //通过无参构造创建对象
-
Class clazz =Class.forName("完整类名"); //假设完整类名是com.my.Person Person类中有name,age属性值
Constructor c = clazz.getConstructor(String.class,int.class); //Person类中有一个有参构造(String name,int age)
Person p = (Person)c.newInstance("李四",24); //通过有参构造创建对象
-
Field f = clazz.getField("name"); //获取姓名字段
f.set(p,"张三"); //修改姓名的值
-
//若Person中的name,age属性被私有,就用暴力反射获取
Field f = clazz.getDeclaredField("name"); //暴力获取字段
f.setAccessible(true); //去除私有权限
f.set(p,"张三"); //修改姓名的值
-
-
Class clazz =Class.forName("完整类名"); //假设完整类名是com.my.Person Person类中有eat()方法
Constructor c = clazz.getConstructor(String.class,int.class);
Person p = (Person)c.newInstance("李四",24); //通过有参构造创建对象
Method m = clazz.getMethod("eat"); //获取eat()方法
m.invoke(p);
Method m2 = clazz.getMethod("eat",int.class) //获取有参 eat(int num)方法
m2.invoke(p,2);
-
泛型擦除/泛型反射
ArrayList<Integer> list = new ArrayList<>(); //创建一个只能放整数类型的集合
Class clazz = Class.forName("java.util.ArrayList"); //获取到字节码对象
Method m = clazz.getMethod("add"); //获取到add方法
m.invoke(list , "abc"); //向集合直接添加字符串
二.JDK新特性
-
JDK5 通过enum实现枚举类
int ordinal(); //枚举项都是有编号的,返回枚举的编号,从0开始
int compareTo(E o); //比较的是编号,返回的是this的编号减去o的编号
String name(); //获取实例的名称
<T>T valueOf(Class<T> type,String name) //通过传字节码对象,名称。 获取枚举项
values(); //获得所有枚举,可用来遍历,返回值是数组
-
JDK7
A:二进制字面量
syso(0b110); //输出6
B:数字字面量可以出现下划线
syso(100_000); //输出100000
C:switch 语句可以用字符串
D:泛型简化,菱形泛型
E:异常的多个catch合并,每个异常用或|
F:try-with-resources 语句, 1.7版标准的异常处理代码
-
JDK8
A.接口中可以定义有方法体的方法,static修饰的可以有方法体,如果是非静态的,必须用default修饰
B.局部内部类访问所在方法中的局部变量必须用final修饰,JDK8之后,可以省略
必须用final修饰原因:因为当调用这个方法时,局部变量如果没有用final修饰,他的生命周期和方法的生命周期是一样的
当方法弹栈,这个局部变量也会消失,那么如果局部内部类对象还没有马上消失想用这个局部变量,就没有了,如果
用final修饰会在类加载的时候进入常量池,即使方法弹栈,常量池中的常量还在,也可以继续使用