A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© yangxiaoqiang 初级黑马   /  2018-12-2 16:59  /  816 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

Day11 网络编程
c/s结构:Client/Server  指 客户端和服务端 结构
B/S结构:Browser/Server  指 浏览器和服务器 结构
UDP: User Datagram Protocol, 用户数据报协议
    特点:
        1. 无连接的不可靠协议
        2. 数据按包发送, 64K一个包
        3. 速度快效率高, 容易丢包
    用于视频直播, 网络电话


TCP: Transmission Control Protocol, 传输控制协议
    特点:
        1. 需要建立连接的可靠协议  电话
        2. 数据传输无大小限制
        3. 速度慢效率低   重发机制
    用于文件下载, 浏览网页


TCP通信的三次握手: TCP协议中, 在发送数据的准备阶段, 客户端与服务器之间的三次交互, 以保证连接的可

    1. 客户端向服务端发送验证信息, 等待服务器确认
    2. 服务端收到验证信息后, 回复客户端验证信息, 同时发送自己的一条验证信息
    3. 客户端收到服务端回复的信息, 确认自己之前发的信息无误, 并再次向服务器发回服务端的验证信息
网络编程三要素:1.通信地址 2.Ip地址 3.端口号
常用DOS命令:
    // 查看自己电脑的IP地址
    ipconfig
    // 查看是否能连接到指定IP地址
    ping IP地址
    ping 192.168.31.2
端口号的取值范围:0~65535的整数,其中0~1024不建议使用
java.net.ServerSocket类: TCP服务端
    // 构造方法
    ServerSocket(int port): 创建一个TCP服务端, 并监听指定端口
    // 成员方法
    Socket accept(): 监听数据, 会阻塞. 收到数据后返回Socket对象
    void close(): 关闭服务端ServerSocket

java.net.Socket类: TCP客户端
    // 构造方法
    Socket(String ip, int port): 创建TCP客户端对象
    // 成员方法
    OutputStream getOutputStream(): 获取输出流对象, 用于发送数据
    InputStream getInputStream(): 获取输入流, 用于接收数据
    void shutdownOutput(): 关闭输出流, 发送结束标记
    void close(): 关闭客户端Socket

TCP严格区分为 客户端(Client) 与 服务端(Server)

两端通信时步骤:
    1. 服务端程序需要先启动, 等待客户端的连接
    2. 客户端主动连接服务器端, 连接成功才能通信. 服务端不可以主动连接客户端

两端之间以 "IO字节流" 进行通信
一个服务端可以和多个客户端同时通信

[size=1.25em]ServerSocketjava.net.ServerSocket类: TCP服务端
// 构造方法
    ServerSocket(int port): 创建一个TCP服务端, 并监听指定端口
// 成员方法
    Socket accept(): 监听数据, 会阻塞. 收到数据后返回Socket对象
    void close(): 关闭服务端ServerSocket

服务器的实现步骤:
    1.创建服务器ServerSocket对象并指定服务器占用的端口号
    2.使用ServerSocket对象中的方法 accept(), 获取到请求的客户端对象Socket
    3.使用Socket对象中的方法 getInputStream() 获取网络字节输入流InputStream对象
    4.使用网络字节输入流InputStream对象中的方法 read(), 读取客户端发送的数据
    5.使用Socket对象中的方法 getOutputStream() 获取网络字节输出流OutputStream对象
    6.使用网络字节输出流OutputStream对象中的方法 write(), 给客户端回写数据
    7.释放资源(Socket,ServerSocket)
[size=1.25em]Socketjava.net.Socket类: TCP客户端
// 构造方法
    Socket(String ip, int port): 创建TCP客户端对象
// 成员方法
    OutputStream getOutputStream(): 获取输出流对象, 用于发送数据
    InputStream getInputStream(): 获取输入流, 用于接收数据
    void shutdownOutput(): 关闭输出流, 告知服务端数据发送完毕
    void close(): 关闭客户端Socket

// 构造方法
    Socket(String ip, int port): 创建TCP客户端对象
// 成员方法
    OutputStream getOutputStream(): 获取输出流对象, 用于发送数据
    InputStream getInputStream(): 获取输入流, 用于接收数据
    void shutdownOutput(): 关闭输出流, 告知服务端数据发送完毕
    void close(): 关闭客户端Socket
Day12 函数式接口
函数式接口: JDK 8 新特性
    有且仅有一个抽象方法的接口, 适用于函数式编程场景的接口
    (默认方法, 静态方法, 私有方法, 与 java.lang.Object 类中定义相同的抽象方法, 都不算作抽象方法)


自定义函数式接口:
    接口中有且只有一个抽象方法


@FunctionalInterface的作用:
    在接口上使用, 检测当前的接口是否为函数式接口


Lambda具有"延迟执行"的特点:
    传递Lambda对象, 只有当符合执行条件时, 才会执行代码


常用的函数式接口
Java中提供的常用 函数式接口:
    Supplier<T>: 生产型函数式接口         获取值  a和b的和, 获取数组最大值, 获取一个Person对象
    Consumer<T>: 消费型函数式接口         使用值  给它一个String让他打印, 给它一个对象
    Predicate<T>: 条件判断型函数式接口     判断值  判断字符串长度是否大于5
    Function<T, R>: 转换型函数式接口      转换值  给它一个String转换为Integer "123"->123

Supplier生产型函数式接口java.util.function.Supplier<T>函数式接口: 生产型函数式接口
    // 抽象方法
     T get(): 用于获取一个对象或值. 至于获取什么值, 怎么获取, 需要我们根据应用场景编写Lambda来实现

Consumer消费型函数式接口java.lang.StringBuilder类: 可变字符序列, 类似于String, 线程不安全效率高   
    StringBuilder reverse(): 将StringBuilder内部保存的内容反转
    String toString(): 转换为String
        new StringBuilder("abc").reverse().toString(); -> "cba" "abc" -> "cba"
java.lang.StringBuffer类: 可变字符序列, 类似于String, 线程安全效率低
    StringBuffer reverse(): 将StringBuffer内部保存的内容反转
    String toString(): 转换为String




java.util.function.Consumer<T>函数式接口: 消费型函数式接口
    // 抽象方法
    void accept(T t): 用于消费(使用)一个对象或值. 至于怎么消费, 要我们根据应用场景编写Lambda实现
    // 默认方法
    default Consumer<T> andThen(Consumer<? super T> after): 拼接两个Consumer接口的Lambda对象实现连续操作. 谁写前面, 谁先消费

Predicate条件判断函数式接口java.util.function.Predicate<T>函数式接口: 条件接口, 用于判断
    // 抽象方法
    boolean test(T t): 判断参数传递的对象. 至于怎么判断, 判断什么, 需要我们编写Lambda表达式实现
    // 默认方法 (用于连接多个判断条件)
    default Predicate<T> and(Predicate<? super T> other): 与 &&
    default Predicate<T> or(Predicate<? super T> other): 或  ||
    default Predicate<T> negate(): 非, 取相反结果   !
   
   
    boolean b = 判断方式1.or(判断方式2).and(判断方式3).negate().test("abc")

Function转换型函数式接口函数 y = f(x)
java.util.function.Function<T,R>: 根据一个 T类型的数据 转换为 另一个R类型的数据
    T是 输入(input)的类型
    R是 返回结果(result)的类型
    有进有出, 所以称为"函数Function"
    // 抽象方法
    R apply(T t): 将T转换为R. 至于T和R是什么类型, 以及如何转换, 需要传递Lambda表达式实现
    // 默认方法
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after): 拼接多个Function转换

day13 Stream 方法引用Stream流式思想:
    JDK 8 出现, 是函数式编程中的一大特性
    关注做什么, 而不是怎么做
Stream流式思想处理数据的方式:
    让代码的执行像流水线一样, 先设计好处理方案, 然后一按开关开始执行

流相比于集合的2个优点:
    1. Pipelining(管道特性): "可以链式调用"
        Stream流对象的 延迟方法 调用后, 会返回新的Stream流对象, 可以链式调用
        每个方法类似于一条一条的管道, 衔接了不同的处理方案
    2. 内部迭代特性: "不用写for循环"
        集合遍历通过 Iterator 或者 增强for, 显式的在集合外部进行迭代, 这叫做外部迭代
        Stream提供了内部迭代的方法 forEach(Consumer c), 可以直接调用遍历方法

使用Stream流的3个步骤:
    1. 获取数据源 (从"集合"或"数组"转换为"Stream"对象)
    2. 数据处理 (调用延迟方法, 编写处理方案)
    3. 获得结果 (调用终结方法, 启动开关)


获取流对象
集合->流: 集合对象.stream()
数组->流: Stream.of(数组)

Stream 方法
延迟方法:
    Stream filter(Predicate p): 过滤
java.lang.String类:
    boolean startsWith(String prefix): 判断当前字符串是否以参数字符串开头


     Stream map(Function f): 转换映射
     Stream limit(long n): 只要前n个
     Stream skip(long n): 不要前n个
终结方法
    long count(): 返回流中元素的个数
    void forEach(Consumer c): 遍历消费每个元素
静态方法
    Stream concat(Stream s1, Stream s2): 合并流


每次调用延迟方法返回的Stream流对象, 都是经过处理后返回的"新的Stream流对象"
之前的Stream流在调用方法后, 已经使用过并关闭了, 不能再次使用, 否则会抛出异常:
    java.lang.IllegalStateException: stream has already been operated upon or closed

方法引用
方法引用能简化以下场景: (方法名后不要写小括号)
        场景                                            格式               简化之前的Lambda         方法引用简化后
    1. 通过对象名引用成员方法     对象名::成员方法名   ()->person.eat()            person::eat
    2. 通过类名引用静态方法       类名::静态方法名        i -> Math.abs(i)            Math::abs
    3. 通过super引用父类成员方法  super::父类方法名   ()->super.eat();           super::eat
    4. 通过this引用本类成员方法   this::本类方法名         ()->this.eat();              this::eat
    5. 引用某个类的构造方法       类名::new        name->new Person(name)    Person::new
    6. 引用创建数组的方法         数据类型[]::new   length->new int[length];    int[]::new
day14 JUnit 反射 注解


测试分类:
    1. 黑盒测试:不需要写代码, 给输入值, 看程序是否能够输出期望的值
        比如你下载一个APP, 随便点点点, APP闪退了
    2. 白盒测试:需要写代码的. 关注程序具体的执行流程
  JUnit:使用步骤
    注意:不要写main方法
    1.在方法上加 @Test 注解
    2. 在 @Test 注解上按 Alt+Enter, 选择 "Add 'JUnit4' to Classpath" 导入JUnit依赖环境
断言: Assert
    使用断言操作来判断结果是否符合预期:
        Assert.assertEquals(期望的结果, 运算的结果);
        如果 期望的结果 和 运算的结果 相等, 则认为测试通过, 否则测试失败
@Before: 修饰的方法会"在每个测试方法执行 之前"被执行
@After:  修饰的方法会"在每个测试方法执行 之后"被执行
注意:
    @Before, @After 修饰的方法可以有多个, 但是谁先执行是由JUnit内部来决定的, 没有明显的规律
    所以不要写多个@Before, @After 修饰的方法
  
反射   
框架:
    半成品软件. 可以在框架的基础上进行软件开发, 简化编码
   
反射: 将类的各个组成部分, 封装为其他对象, 这就是反射机制
    成员变量(字段): Field类的对象
    构造方法: Constructor类的对象
    成员方法: Method类的对象
    好处:
        1. 可以在程序运行过程中, 操作这些对象
        2. 可以解耦, 提高程序的可扩展性
        
Java代码在计算机中的3个阶段:
    SOURCE: 源代码阶段
    CLASS: 类对象阶段
    RUNTIME: 运行时阶段


获取一个类的字节码对象的3种方式:
    1. Class.forName("全类名")
        将字节码文件加载进内存,返回Class对象
        适用场景: 多用于配置文件,将类名定义在配置文件中. 读取文件, 加载类
    2. 类名.class                         .
        通过类名的属性class获取
        适用场景: 多用于参数的传递  getConstructor(String.class, int.class)
    3. 对象.getClass()
        getClass()方法在Object类中定义
        适用场景: 多用于对象的获取字节码的方式 p.getClass()
        
同一个类的字节码对象, 只有"唯一的一个"   
Class的方法概述java.lang.Class<T>类: 表示一个类的字节码对象, 其中包含该类中定义的内容
// 成员方法
// 1. 获取成员变量们
    Field[] getFields(): 获取所有 public 的成员变量
    Field getField(String name): 获取指定名称的 public 的成员变量
    Field[] getDeclaredFields(): 获取所有的成员变量, 不考虑权限修饰符
    Field getDeclaredField(String name): 获取指定名称的成员变量, 不考虑权限修饰符
// 2. 获取构造方法们
    Constructor<?>[] getConstructors(): 获取所有 public 的构造方法
    Constructor<T> getConstructor(Class<?>... parameterTypes): 获取指定的 public 构造方法
    Constructor<?>[] getDeclaredConstructors(): 获取所有的构造方法, 不考虑权限修饰符
    Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes): 获取指定的构造方法, 不考虑权限修饰符
// 3. 获取成员方法们:
    Method[] getMethods(): 获取所有 public 的成员方法
    Method getMethod(String name, Class<?>... parameterTypes) : 获取指定的 public 成员方法
    Method[] getDeclaredMethods(): 获取所有的成员方法, 不考虑权限修饰符
    Method getDeclaredMethod(String name, Class<?>... parameterTypes): 获取指定的成员方法, 不考虑权限修饰符
// 4. 获取Class对象代表的类的全类名
    String getName(): 获取当前Class对象代表的类的全类名
// 5. 创建对象
    T newInstance(): 使用当前类的空参构造, 创建一个对象

获取成员变量Fieldjava.lang.Class<T>类: 表示一个类的字节码对象, 其中包含该类中定义的内容
    // 获取功能
    1. 获取成员变量们
        Field[] getFields(): 获取所有 public 的成员变量
        Field getField(String name): 获取指定名称的 public 的成员变量
        Field[] getDeclaredFields(): 获取所有的成员变量, 不考虑权限修饰符
        Field getDeclaredField(String name): 获取指定名称的成员变量, 不考虑权限修饰符


java.lang.reflect.Field: 表示一个成员变量
    // 成员方法 String name;   Person p = new Person(); p2.name = "abc";
    void set(Object obj, Object value): 设置指定对象的成员变量的值 field.set(p1, "abc")
    Object get(Object obj): 获取指定对象的成员变量的值 field.get(p1)
    void setAccessible(boolean flag): 传true时忽略访问权限修饰符的安全检查. 暴力反射 field.set

获取构造方法Constructorjava.lang.Class<T>类: 表示一个类的字节码对象, 其中包含该类中定义的内容
    // 获取构造方法们
    Constructor<?>[] getConstructors(): 获取所有 public 的构造方法
    Constructor<T> getConstructor(Class<?>... parameterTypes): 获取指定的 public 构造方法
    Constructor<?>[] getDeclaredConstructors(): 获取所有的构造方法, 不考虑权限修饰符
    Constructor<T> getDeclaredConstructor(Class... parameterTypes): 获取指定的构造方法, 不考虑权限修饰符
    T newInstance(): 使用当前类的空参构造创建一个对象
   
   
    Constructor con = c.getConstructor(String.class, int.class);
    con.newInstance("zhangsan", 18);
    new Person("zhangsan", 18);
        
java.lang.reflect.Constructor<T>: 表示一个构造方法
    // 成员方法
    T newInstance(Object... initargs): 使用当前构造方法传入参数, 创建对象
    void setAccessible(boolean flag): 注意: 构造方法不能利用此方法忽略权限, 会抛异常

获取成员方法Methodjava.lang.Class<T>类: 表示一个类的字节码对象, 其中包含该类中定义的内容
    // 获取成员方法们:
    Method[] getMethods(): 获取所有 public 的成员方法
    Method getMethod(String name, Class<?>... parameterTypes) : 获取指定的 public 成员方法
    Method[] getDeclaredMethods(): 获取所有的成员方法, 不考虑权限修饰符
    Method getDeclaredMethod(String name, Class<?>... parameterTypes): 获取指定的成员方法, 不考虑权限修饰符
   
java.lang.reflect.Method类: 表示一个成员方法
    // 成员方法 Person p = new Person();   p.eat("adf", 123);  
    Object invoke(Object obj, Object... args): 使用指定对象和指定参数值调用此方法
    String getName(): 获取方法名
    void setAccessible(boolean flag): 传true时忽略访问权限修饰符的安全检查. 暴力反射



注解
注解: Annotation
    JDK 1.5 引入. 也叫元数据, 是一种代码级别的说明
    它可以声明在包, 类, 字段(成员变量), 方法, 局部变量, 方法参数等的前面, 用来对这些元素进行说明

注解: 说明程序的。给计算机看的
注释: 用文字描述程序的。给程序员看的

使用注解: @注解名称

作用分类:
    1. 编写文档: 通过代码里标识的注解生成文档
        (生成API文档 @author @version @since @param @return)
    2. 代码分析: 通过代码里标识的注解对代码进行分析 (使用反射)
        (JUnit提供的 @Test @Before @After)
    3. 编译检查: 通过代码里标识的注解让编译器能够实现基本的编译检查
        (@Override @FunctionalInterface)

自定义注解:属性定义
属性:
    接口中的"抽象方法"

属性的要求:
    1. 属性的"返回值类型"可以是以下类型:
        基本数据类型(8种)
        String
        枚举
        注解
        以上类型的数组
    2. 定义了属性,在使用注解时, 需要"给属性赋值" (其实是抽象方法的返回值)
        1. 属性使用 default 关键字指定默认值, 则可以不赋值
        2. 如果只有一个名为"value"的属性需要赋值, 则 value 可以省略, 直接写值即可
        3. 给数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略

常用元注解
@Target: 描述注解能够作用的位置
        ElementType枚举的常用取值:
            TYPE:可以作用于类上
            METHOD:可以作用于方法上
            FIELD:可以作用于成员变量上
        示例: @Target(value = {ElementType.TYPE, ElementType.METHOD})
    @Retention: 描述注解被保留的阶段
        RetentionPolicy枚举的取值:
            SOURCE: 保留到源代码阶段
            CLASS: 保留到类对象阶段
            RUNTIME: 保留到运行时阶段
        示例: @Retention(RetentionPolicy.RUNTIME):保留注解到class字节码文件中并被JVM读取到
    @Documented: 加上后, 当前注解会被抽取到api文档中
    @Inherited: 加上后, 当前注解会被子类继承


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马