网络编程
1、网络编程概述
什么是网络编程?
- 可以让设备中的程序与网络上其他设备中的程序进行数据交互(实现网络通信的);
基本的通信架构
- 基本的通信架构有2种形式:CS架构(Client客户端/Server服务端)、BS架构(Browser浏览器/Server服务器)。


注意:无论是CS架构,还是BS架构的软件都必须依赖网络编程。
2、网络通信三要素
网络通信的关键三要素

IP地址
- IP:全称"互联网协议地址",是分配给上网设备的唯一标志;
- IP地址有两种形式:IPv4,IPv6

IPv6地址
- IPv6:共128位,号称可以为地球每一粒沙子编号。
- IPv6分为8段表示,每段每四位编码成一个十六进制位表示,数之间用冒号(:)分开。

IP域名

公网IP,内网IP
- 公网IP:是可以连接互联网的IP地址;内网IP:也叫局域网IP,只能组织机构内部使用。
- 192.168.开头的就是常见的局域网地址,范围即为192.168.0.0--192.168.255.255,专门为组织机构内部使用。
特殊IP地址:
- 127.0.0.1、localhost:代表本机IP,只会寻找当前所在的主机。
IP常用命令:
- ipconfig:查看本机IP地址;
- ping IP地址:检查网络是否连通。
3、IP地址
InetAddress
- 代表IP地址
InetAddress的常用方法如下

代码演示:
java
public class InetAddressDemo1 {
public static void main(String[] args) throws Exception {
// 目标:InetAddress类代表IP地址对象,用来操作IP地址
//1、获取本机IP地址对象
InetAddress ip = InetAddress.getLocalHost();
System.out.println(ip.getHostAddress());
System.out.println(ip.getHostName());
//2、指定获取对方主机的IP地址对象
InetAddress ip2 = InetAddress.getByName("www.baidu.com");
System.out.println(ip2.getHostAddress());
System.out.println(ip2.getHostName());
//3、判断主机与该主机是否能够连通: ping
System.out.println(ip2.isReachable(5000));
}
}
4、端口
- 标记正在计算机设备上运行的应用程序的,被规定为一个16位的二进制,范围是0~65535。
分类

注意:我们自己开发的程序一般选择使用注册端口,且一个设备中不能出现两个程序的端口号一样,否则出错。
5、协议
通信协议:
- 网络上通信的设备,事先规定的连接规则,以及传输数据的规则被称为网络通信协议。
开放式网络互联标准:OSI网络参考模板
- OSI网络参考模型:全球网络互联标准。
- TCP/IP网络模型:事实上的国际标准。

传输层的2个通信协议
- UDP:用户数据报协议;TCP:传输控制协议。
UDP协议
- 特点:无连接、不可靠通信。

注意:通信效率高,语音通话,视频直播。
TCP协议
- 特点:面向连接、可靠通信。
- TCP的最终目的:要保证在不可靠的信道上实现可靠的传输。

TCP协议:三次握手建立可靠连接
可靠连接:确定通信双方,收发消息都是正常无问题的!(全双工)

传输数据会进行确认,以保证数据传输的可靠性。
TCP协议:四次握手断开连接
目的:确保双方数据的收发都已经完成!

注意:通信效率相对不高。网页、文件下载、支付。
6、UDP通信
7、UDP多发多收
Java高级技术
1、junit单元测试框架
单元测试
- 就是针对最小的功能单元(方法),编写测试代码对其进行正确性测试。
咱们之前是如何进行单元测试的?有啥问题?

Junit单元测试框架
- 可以用来对方法进行测试,它是第三方公司开源出来的
优点


步骤:Junit单元测试-快速入门
需求:
- 某个系统,有多个业务方法,请使用Junit单元测试框架,编写测试代码,完成对这些方法的正确性测试。
具体步骤

代码演示:
java
public class StringUtilTest {
@Test
public void testPrintNumber(){
StringUtil.printNumber(null);
StringUtil.printNumber("");
StringUtil.printNumber("admin");
}
@Test
public void testGetMaxIndex(){
/*System.out.println(StringUtil.getMaxIndex(null));
System.out.println(StringUtil.getMaxIndex(""));
System.out.println(StringUtil.getMaxIndex("admin"));*/
//断言:预言
int i1 = StringUtil.getMaxIndex(null);
Assert.assertEquals("测试失败",-1,i1);
int i2 = StringUtil.getMaxIndex("");
Assert.assertEquals("空字符串测试失败",-1,i2);
int i3 = StringUtil.getMaxIndex("admin");
Assert.assertEquals("admin测试失败",4,i3);
System.out.println("测试通过!");
}
}
2、Junit注解
Junit单元测试框架的常用注解(Junit4.XXXX版本)

- 在测试方法执行前执行的方法,常用于:初始化资源;
- 在测试方法执行完后再执行的方法,常用于:释放资源。
代码演示:
java
@Before //修饰实例方法,每个测试方法前都执行一次
public void before(){
System.out.println("======before=====");
}
@After //修饰实例方法,每个测试方法后都执行一次
public void after(){
System.out.println("======after=====");
}
@BeforeClass //修饰静态方法,全部测试方法前只执行一次
public static void beforeClass(){
System.out.println("======beforeClass=====");
}
@AfterClass //修饰静态方法,全部测试方法后只执行一次
public static void afterClass(){
System.out.println("======afterClass=====");
}
Junit单元测试框架的常用注解(Junit 5.xxxx)版本

- 开始执行的方法:初始化资源;
- 执行完之后的方法:释放资源。
3、反射第一步:Class对象
反射(Reflection)
- 反射就是:加载类,并允许以编程的方式解剖类中的各种成分(成员变量、方法、构造器等)。

反射学什么?
学习获取类的信息、操作他们

获取Class对象的三种方式

代码演示:
java
public class Test1Class {
public static void main(String[] args) throws Exception {
//目标:反射第一步,获取Class对象
//1、方式一 类名.class
Class c1 = Student.class;
System.out.println(c1);
//2、方式二 Class.forName(全类名)
Class c2 = Class.forName("com.itheima.d2_reflect.Student");
System.out.println(c2);
//3、对象.getClass();
Student s1 = new Student();
Class c3 = s1.getClass();
System.out.println(c3);
System.out.println(c1 == c2);
System.out.println(c1 == c3);
}
}
4、反射获取构造器对象
获取类的构造器、并对其进行操作
- Class提供了从类中获取构造器的方法。

获取类构造器的作用:依然是初始化对象返回。

代码演示:
java
public class Test2Constructor {
@Test
public void testGetConstructors(){
Class c = Cat.class;
//Constructor[] constructors = c.getConstructors(); //只能获取public的构造器
Constructor[] constructors = c.getDeclaredConstructors(); //存在即可拿
//3、遍历构造器
for(Constructor con : constructors){
System.out.println(con.getName() + "===>" + con.getParameterCount());
}
}
@Test
public void testGetConstructor() throws Exception{
//1、获取class对象
Class c = Cat.class;
//2、获取类的某一个构造器,无参数构造器
Constructor con1 = c.getDeclaredConstructor();
Constructor con2 = c.getDeclaredConstructor(String.class,int.class);
//3、得到构造器的目的依然是初始化对象返回
Cat c1 = (Cat)con1.newInstance();
System.out.println(c1);
con2.setAccessible(true); //禁止检查访问权限(暴力反射)
Cat c2 = (Cat)con2.newInstance("叮当猫", 30);
System.out.println(c2);
}
}
5、反射获取成员变量对象
获取类的成员变量
- Class提供了从类中获取成员变量的方法。

获取到成员变量的作用:依然是赋值、取值。

代码演示:
java
public class Test3Field {
@Test
public void testGetFields() throws Exception {
//反射第一步,获取Class
Class c = Cat.class;
//2、获取类的全部成员变量
Field[] fields = c.getDeclaredFields();
//3、遍历这个成员变量全部数组
for (Field field : fields) {
System.out.println(field.getType() +"==>" + field.getName());
}
//4、获取制定的成员变量
Field fname = c.getDeclaredField("name");
fname.setAccessible(true);
//5、成员变量的作用价值是:取值和赋值
Cat cat = new Cat();
fname.set(cat,"哆啦A梦");
String name = (String)fname.get(cat);
System.out.println(name);
}
}
6、反射获取方法对象
代码演示:
java
public class Test4Method {
@Test
public void testGetMethods() throws Exception {
//1、反射第一步,去得到Class对象
Class c = Cat.class;
//2、获取类的全部成员方法
Method[] methods = c.getDeclaredMethods();
//3、遍历这个数组中的每个方法对象
for(Method method : methods){
System.out.println(method.getName() + "==>" + method.getParameterCount());
}
//4、定位单个方法
Method eat1 = c.getDeclaredMethod("eat");
Method eat2 = c.getDeclaredMethod("eat",String.class);
//5、定位方法的目的是,依然是执行它
Cat cat = new Cat();
Object result = eat1.invoke(cat);
System.out.println(result);
eat2.setAccessible(true);
Object result2 = eat2.invoke(cat, "鱼儿");
System.out.println(result2);
}
}
7、反射做通用框架
反射的作用?
- 基本作用:可以得到一个类的全部成分然后操作;
- 可以破坏封装性。
- 最重要的用途是:适合做Java的框架,基本上,主流的框架都会基于反射设计出一些通用的功能。
案例:使用反射做一个简易版的框架
需求:
- 对于任意一个对象,该框架都可以把对象的字段名和对应的值,保存到文件中去。

代码演示:
java
public class ObjectFrame {
public static void saveObject(Object obj) throws Exception {
//但是这个对象中国有多少个字段,我们不清楚的,谁清楚呢?只有反射可以解决
PrintWriter pw = new PrintWriter(new FileWriter("day14-junit-reflect-annotation-proxy/src/obj.txt"),true);
Class c = obj.getClass();
//要知道此class是什么对象
//String className = c.getName(); 太长,有文件名
String className = c.getSimpleName(); //简名
pw.println("========"+className+"==========");
Field[] fields = c.getDeclaredFields();
for (Field field : fields) {
field.setAccessible(true);
String name = field.getName();
String value = field.get(obj) + "";
pw.println(name + "=" + value);
}
pw.close();
}
}