黑马程序员技术交流社区

标题: [石家庄校区]个人总结 java基础第二阶段day11-day14 [打印本页]

作者: 初音初音初    时间: 2018-12-2 16:26
标题: [石家庄校区]个人总结 java基础第二阶段day11-day14
本帖最后由 初音初音初 于 2018-12-2 16:28 编辑

day11 网络编程

UDP和TCP协议特点:
UDP: 用户数据报协议
        1. 无连接的不可靠的协议
        2. 数据以包的形式发送, 一个包64K
        3. 速度快效率高, 容易丢包
TCP: 传输控制协议
        1. 有连接的可靠协议
        2. 直接传输数据没有大小限制
        3. 速度慢, 安全性高

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

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

补充!!:
udp(User Datagram Protocol)用户数据报协议,类似于广播,数据在互联网中传播遇到对应端口会检测校验值,校验值符合即接收,
tcp(Transmission Control Protocol)传输控制协议,面向连接,可靠,基于字节流,建立管道来传送数据。
一般建立在项目下的serversocket,访问地址不需要有项目名和src
本地地址通常为127.0.0.1 或者使用通用形式localhost
端口不可任意设置,一般要高于1024
IP正确,端口不正确,会报链接被重置
IP不正确,会报链接超时

day12 函数式接口
@FunctionalInterface注解
@FunctionalInterface
作用: 检测接口是否符合函数式接口的要求, 不符合就编译报错
用在哪: 在接口声明的上面
@FunctionalInterface
public interface 接口名{}


lambda具有延迟执行的特点(传入方法)

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

Consumer:
    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(): 非, 取相反结果

Function:
    java.util.function.Function<T,R>: 根据一个T类型的数据得到另一个R类型的数据
            T称为前置条件, 也就是输入(input)的类型
            R称为后置条件, 也就是返回结果(result)的类型
            有进有出, 所以称为"函数Function"
            // 抽象方法
            R apply(T t): 将T转换为R
            // 默认方法
            default <V> Function<T, V> andThen(Function<? super R, ? extends V> after): 拼接多个Function转换


补充!!:
注意区分四大函数式接口

加了@FunctionalInterface并不代表就是函数式接口,注解只是用于判断
lambda实质上是将方法作为参数进行传递,可以提高程序运行效率


day13 Stream流 方法引用
常用的流操作

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

Stream方法:
    延迟方法:
            Stream filter(Predicate p): 过滤
         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): 合并流

方法引用(简化Lambda表达式)
对象的成员方法: 对象名::成员方法名
静态方法: 类名::静态方法名
父类的方法: super::成员方法名
本类的方法: this::成员方法名

类和数组的构造器引用
类: 类名::new  
数组: 数据类型[]::new


补充!!:
简化lambda表达式,适用的情况是:
如果Lambda表达式仅仅是调用一个已经存在的方法, 那就可以通过方法引用来替代Lambda表达式。
Lambda中, 重写方法的"参数", 必须是方法引用的方法"要接收的类型", 否则会抛出异常。
延迟方法可以链式调用。

day14 JUnit 反射 注解

JUnit单元测试
        
测试分类:
        1. 黑盒测试:不需要写代码, 给输入值, 看程序是否能够输出期望的值
                比如你下载一个APP, 随便点点点, APP闪退了
        2. 白盒测试:需要写代码的. 关注程序具体的执行流程
                比如今天学习的JUnit
JUnit使用步骤:
        1. 定义一个测试类(也叫测试用例)
            包名:xxx.xxx.xx.test
                被测试的类名:   Calculator   
                对应的测试类名: CalculatorTest
        2. 定义测试方法:可以独立运行
                被测试的方法名:       add()      
        对应的测试方法名: testAdd()  
                    建议测试方法的返回值是void, 参数列表是空参
        3. 在方法上加 @Test 注解
        4. 在 @Test 注解上按 Alt+Enter, 选择 "Add 'JUnit4' to Classpath" 导入JUnit依赖环境
        5. 在方法名上右键, 选择 "Run '方法名()'"
        
断言: Assert:
        使用断言操作来判断结果是否符合预期:
        Assert.assertEquals(期望的结果, 运算的结果);
        如果 期望的结果 和 运算的结果 相等, 则认为测试通过, 否则测试失败


JUnit: @Before, @After

        @Before: 修饰的方法会"在每个测试方法执行 之前"被执行
        @After:  修饰的方法会"在每个测试方法执行 之后"被执行

注意:
        @Before, @After 修饰的方法可以有多个, 但是谁先执行是由JUnit内部来决定的, 没有明显的规律
        所以不要写多个@Before, @After 修饰的方法

反射

框架:
        半成品软件. 可以在框架的基础上进行软件开发, 简化编码
        比如JUnit就是一个单元测试框架, 它不是一个独立的软件, 而是和我们开发的软件结合, 简化代码测试
        
反射: 将类的各个组成部分, 封装为其他对象, 这就是反射机制
        成员变量(字段): 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的方法概述

// 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(): 使用当前类的空参构造, 创建一个对象


反射: 获取成员变量Field


        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

反射: 获取构造方法Constructor


        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);

        T newInstance(Object... initargs): 使用当前构造方法传入参数, 创建对象
        void setAccessible(boolean flag): 注意: 构造方法不能利用此方法忽略权限, 会抛异常

反射: 获取成员方法Method

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)

JDK中预定义的一些注解:
        @Override: 检测被该注解标注的方法是否是"重写"父类(接口)的
        @Deprecated: 该注解标注的内容,表示已过时
        @SuppressWarnings: 压制警告. 一般传递参数all  @SuppressWarnings("all")

自定义注解: 格式和本质

public interface 接口名 {}

自定义注解格式:关键字 @interface

     元注解
    public @interface 注解名称 {
        属性; (接口中的抽象方法)
            属性;
            属性;
            ...

    }

@注解名称

注解的本质:
        注解本质上就是一个接口,该接口默认继承Annotation接口
        public interface MyAnno extends java.lang.annotation.Annotation {}

自定义注解: 属性定义

属性:
        接口中的"抽象方法"

属性的要求:
    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: 加上后, 当前注解会被子类继承

自定义注解: 解析注解

获取注解属性值的步骤:
        1. 获取注解定义位置的对象 (Class对象(类注解), Field对象(成员变量注解), Method对象(方法注解))
        2. 调用 ProAnno a = cls.getAnnotation(ProAnno.class) 方法获取注解对象
        3. 通过注解对象调用抽象方法获取属性值
        
        // 比如获取一个类上的注解
    注解类型 注解变量名 = 被注解的类.class.getAnnotation(注解名.class);
    数据类型 变量名 = 注解变量名.抽象方法();

    ProAnno proAnno = Test.class.getAnnotation(ProAnno.class);
    String className = proAnno.className();
    String methodName = proAnno.methodName();

补充!!:
注意getName和getSimpleName的区别,一个是全类名,一个是类名(不含包名)










欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2