前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Java知识点——第六周总结

Java知识点——第六周总结

作者头像
用户7073689
发布2020-03-24 17:53:33
5690
发布2020-03-24 17:53:33
举报
文章被收录于专栏:青柠小鱼

第六周总结

TCP多人聊天室实现

分析

  • 客户端 功能: 1. 数据发送 2. 数据接收 技术: 1. socket 2. 输入流和输出流 3. 多线程,客户端功能模块有两个线程 聊天: 1. 群聊 2. 私聊 私聊前缀 @服务器用户ID号:msg
  • 服务器 功能: 1. 数据转发 2. 用户注册 技术: 1. ServerSocket 2. 每一个用户对应的Sokcet对象 3. 多线程同时在线 4. HashMap<Integer, 用户> 数据转发: 私聊前缀判断 群聊所有人发送

客户端实现

数据发送: 使用输出流发送数据给服务器 遵从Runnable接口 数据接收: 使用输入流从服务器端接收数据 遵从Runnable接口

客户端主方法: 用户名提交 数据发送 数据接收 多线程启动

资源关闭问题

-代码中操作了大量的输入流和输出流,这里都需要进行关闭操作。 DataInputStream, DataOutputStream, BufferedReader, Socket

以上这些资源都是Closeable接口的实现类,都有对应的Close方法 封装一个工具类: 提供一个closeAll方法,参数为符合Closeable接口的实现类对象。 这里可以考虑可变长参数 Closeable… closeable

代码语言:javascript
复制
可变长参数在方法中使用的过程里面是对应一个数组,这里完成可以使用增强for来使用

工具类名: CloseUtil public static void closeAll(Closeable… closeable)

功能拓展

  1. 用户退出 用户输入指定字段之后可以退出 客户端Socket服务 服务端Socket服务 涉及资源关闭,线程关闭
  2. 用户异常退出 在运行过程中发现问题,需要及时处理,关闭对应的资源,终止对应的线程
  3. 服务器保存所有的聊天记录

JSON

JSON格式概述

  • JSON JavaScript JavaScript Object Notation (JavaScript Object Notation,JavaScript对象表示法,读作/ˈdʒeɪsən/)是一种由道格拉斯·克罗克福特构想和设计、轻量级的数据交换语言,该语言以易于让人阅读的文字为基础,用来传输由属性值或者序列性的值组成的数据对象。尽管JSON是JavaScript的一个子集,但JSON是独立于语言的文本格式,并且采用了类似于C语言家族的一些习惯

数据格式

JSON对象

{ “ID”:001, “name”:“骚磊”, “age”:16 }

特征: 1. 数据形式键值对形式 “键”:值 2. 数据支持 字符串,数字,true false 3. {} 大括号以内的数据

  • JSON对象数组
    • [ { “ID”:1, “name”:“骚磊”, “age”:16 }, { “ID”:2, “name”:“骚杰”, “age”:66 }, { “ID”:3, “name”:“康康”, “age”:15 } ]

特征: 1. 数据使用[]包含 2. 在[]都是JSON格式对象 3. 每一个对象之间使用逗号隔开,同时最后一个元素不需要逗号

  • JSON数据验证
    • JSON格式验证

解析JSON格式工具

  • 常用的工具: Gson,fastjson, Jackson 以上都是第三方工具,需要导入对应的jar包按使用XML导包
  • FastJson内容
    • JSON核心类 JSON核心类提供解析和转化方法,用于解析JSON数据格式,同时用于转换类对象到JSON格式,该类对象需要符合JavaBean规范 –| JSONArray 存在按照键值对方式解析获取数据,同时存在一定的List方法 –| JSONObject 获取对应的类对象,指定键值对对应数据的方法
  • 解析演示

注解

注解概述

  • 注解解释
    • 注释: 解释代码,给程序员看

注解: Java语言中的类、方法、变量、参数和包等都可以被标注。和Javadoc不同,Java标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java虚拟机可以保留标注内容,在运行时可以获取到标注内容。 当然它也支持自定义Java标注 JDK1.5之后的特征 用于说明程序 一般在框架中使用 格式: @AnnotationName

文档注释: @param @return @Exeception 从根本上是一个注释,不存在代码编译,不会生成对应的.class字节码问题,只是提供给JavaDoc API文件生成工具。作为标记生成对应的文档。

注解是有一部分参与编译 @Override并不是没编译就有效果了,是因为不管是Eclipse还是IDEA都可以预编译Java代码生成对应的.class文件的

  • 注解作用
    • 生成文档: 代码中生成对应的JavaDoc API文档 @param @return

    【IDEA JavaDoc工具使用参数】 Other Command Line Arguments : -encoding utf-8 -charset utf-8 解决中文乱码,因为IDEA默认编码集为UTF-8 Windows GKB

代码检查: 继承重写,或者说接口遵从之后的实现中,存在@Override

代码数据获取: [小框架] 通过反射获取指定注解中的一些内容,例如 配置,数据,操作,验证。。。

  • Java中预定义的一些注解
    • @Override: 重写/实现方法的情况下,检查方法声明是否和父类或者接口中的方法声明一致。强制格式检查。

@Deprecated 标注当前方法已过时,例如 Data日期类内的一些方法

@SuppressWarnings(“all”) 压制警告,可以用于一些代码中存在明确无异常的情况下,压制一些警告

Java中自定义注解

  • Java中自定义注解的方式
    • 格式: public @interface AnnotationName { 属性列表; }

Annotation注解是可以编译得到对应的.class字节码文件,验证了注解是可以参与编译过程的

通过反编译工具可以得到一下内容 【Annotation本质】 public interface MyAnnotation1 extends java.lang.annotation.Annotation { }

MyAnnotation1 本质是一个interface,同时java.lang.annotation.Annotation 子接口

  • Annotation注解属性【难点】
    • 属性: 开发书写代码使用注解的方式中,数据使用方式更加偏向于属性概念。 使用 1. 在书写代码中使用 @MyAnnotation(id=1, name=“骚磊”, age=16) 2. 利用反射时,会涉及到getXXX方法 通过属性名获取对应值的概念来完成的

    【但是实际上是利用abstract方法来完成属性概念的】

属性使用的格式[实际按照方法格式操作] 1. 属性的值数据类型和对应具体数据 ==> 返回值类型和返回的数据 属性类型支持: a. 基本数据类型 b. String类型 c. 其他的注解类型 d. 枚举类型 枚举就是一个带有名字的常量,为了更好的域阅读性和操作 e. 以上类型对相应的数组

代码语言:javascript
复制
	属性值要求
		a. 定义属性时可以使用default关键字,加上默认值,该属性在使用的过程中是
		没有强制要求属性值,如果没有赋予属性值,采用对应的默认值操作,如果赋
		值,使用对应值
		
		b. 如果注解中有且只有一个value属性,或者说注解中除value属性之外,都有
		默认值,不管是类,方法,成员变量,包使用当前注解是可以直接在括号内加入
		对应数据类型数值、
		
		c. 如果属性是数组类型, {}大括号保存,并且不同的内容,使用,隔开
2. 属性的键名字 ==> 方法的名字
  • 元注解
    • 给予注解的解释,用于约束注解的一些操作问题 @Retention - 标识这个注解怎么保存,是只在代码中,还是编入class文件中,或者是在运行时可以通过反射访问。 RetentionPolicy.RUNTIME:当前注解会编译生成对应的.class字节码文件,并且可以加 载到JVM中,参与代码执行 RetentionPolicy.CLASS:

别纠结,记下就好: RetentionPolicy.SOURCE:注解将被编译器丢弃(该类型的注解信息只会保留在源码里,源码经过编译后,注解信息会被丢弃,不会保留在编译好的class文件里) @Override 对应属性RetentionPolicy.SOURCE 在代码编译过程中,检查方法格式是否正确,不参与代码运行和解析。

@Documented 标记这些注解是否包含在用户文档中。 是否可以通过JavaDoc工具,生成对应的API文档

@Target 标记这个注解应该是哪种 Java 成员。 属性: ElementType TYPE: 当前注解可以用于类声明 METHOD: 当前注解可以用于方法声明位置 FIELD:当前注解可以用于成员变量声明位置 @Inherited 标记这个注解是继承于哪个注解类(默认 注解并没有继承于任何子类)

【重点】 @Target目标 可以作用范围 类,方法,成员变量… @Retention RetentionPolicy.RUNTIME 常用

  • 使用反射获取注解中的内容【用途】
  • 使用注解测试代码运行【用途】

注解使用总结

    1. 注解以后大多数情况下,都是使用过程,而不是自定义,会使用到框架中预处理好的注解。
  1. 注解是给谁用的? a. 编译器 b. 解析代码使用 c. JVM运行代码使用
  2. 注解是一个标签,有时候是做标记的,有时候标签是有属性的。

函数式接口

函数式接口

  • 概述
    • 如果说一个接口内有且只有一个方法,而且该方法是一个缺省属性为public abstract方法,该接口可以称之为是一个函数式接口。 自定义函数式接口,还有系统中提供的函数式接口 Comparator Runnable

    可以直接理解JDK1.8的新特征,Lambda表达式来使用。 Lambda表达式对比匿名内部类使用 1. 简化了代码结构 2. 节约了内存资源 3. 让程序员更加关注,我要做什么,而不是为了做什么需要完成什么

  • @FunctionalInterface 使用
    • /**
  • 使用@FunctionalInterface检查函数式接口格式问题
  • 要求当前接口中有且只有一个缺省属性为public abstract的方法
  • @author Anonymous 2020/3/11 9:55 */ @FunctionalInterface public interface FunctionalType { void test(); }
  • 使用自定义的函数式接口作为方法的参数使用

函数式编程思想

  • Lambda延迟执行
    • 日志记录
      • 日志是否保存会存在等级限制 演示一个根据不同的等级来记录log日志 要求: 等级 == 1 记录log日志,其他情况不记录
    • 使用函数式接口提供日志信息功能
  • Lambda作为方法参数和返回值

Java中提供的常用函数式接口

  • JDK常用函数式接口概述
    • java.util.function包名 。提供了很多函数式接口 规范了一些操作,提升了开发效率,更加专注于目的性!!!

    Supplier 生产者, 返回一个指定类型的数据 Consumer 消费者, 消耗一个指定类型的数据 Predicate 判断调节,过滤使用 Function<T,R> 类型转换,根据你指定的类型T, 转换成对应类型R

  • Supplier 生产者,返回一个指定的数据类型
    • java.util.function.Supplier 有且只有一个方法 T get(); 不需要参数,返回指定T类型数据 什么都不吃,挤的都是输出。。。
    • 找出数组中最大值所在下标位置
    • 引出满足更多普适性代码的函数式接口使用方式
  • Consumer消费者,处理数据
    • Consumer 操作使用的方式是 void accept(T t); 根据接口指定的数据类型接收对应数据,进行处理和消费,对外没有任何的返回 至于处理的过程,展示,处理,计算。。。
    • andThen
  • Predicate 判断数据是否合适,返回true/false
    • Predicate一般用于条件判断,过滤数据的方法 函数式接口中指定的方法 boolean test(T t); 处理T类型数据,返回boolean true / false
    • and 与
    • or 或
    • negate 非
    • ArrayList中使用Predicate删除指定数据
  • Function<T,R> 类型转换
    • 使用R apply(T t) 转换指定类型T到R
    • andThen

Stream流

Stream流引入

  • Stream流完全不是I/O流,按照流水线处理方式来考虑代码中的思想。 JDK1.8 之后,我们拥有了Lambda表达式,让代码的中心偏向解决实际问题,直到重点,可以提高效率。 Stream流中使用了大量Lambda表达式,利用Lambda操作方式,提供开发效率

传统遍历方式和Stream类处理方式对比

Stream流对应的思想

  • Stream流有一些特征:
    1. 带有很多Stream流操作的方法, filter,limit,map,sorted,skip…这些方法大多是都会使用到函数式接口,那就意味着有lambda表达式
    2. 整个Stream流模型操作过程中,只有执行到count,foreach这些方法,操作真正的执行中的模型,如果不存在结果导向,中间的所有操作是无效的,这里得益于Lambda表达式的延后性
    3. Stream流是存在一定的管道性 Pipelining 流水线

获取Stream流

  • java.util.stream.Stream JDK1.8的新特征
    1. 所有的Collection集合都有对应的Stream();
    2. 可以通过Stream类中的static Stream of()获取 static Stream of(T… t); static Stream of(T t);

Stream常用方法

  • 延迟方法: 返回值类型依然是Stream接口本身,并没有影响我们操作真正的资源 允许链式操作, 例如 filter(XXX).limit(XXX).sorted(XXX). 终结方法: 返回值类型不是Stream接口本身,要么处理数据,要么返回其他类型数据,并且不再支持Stream流对象链式操作,count,foreach
    • foreach方法【终结方法】
      • void foreach(Consumer<? super T> action); /* 终结方法: 需要一个Consumer接口进行操作处理,消耗一个数据 Consumer接口是一个【函数式接口】那就可以使用Lambda表达式 Consumer接口中方法是 void accept(T t); */
    • filter方法
      • Stream filter(Predicate<? super T> condition); /* filter是过滤方式,需要的参数是Predicate接口,Predicate是一个函数式接口,可以直接使用Lambda表达运行。 这里返回值类型是Stream类对象,是经过过滤之后的Stream类型,可以进行链式操作 Predicate接口中需要实现的方法 boolean test(T t); */
        • stream has already been operated upon or closed

为何会出现这个错误?

因为调用终结方法后,Stream流已经被销毁,所以不能再对Stream流进行操作。

代码语言:javascript
复制
- map方法

	- <R> Stream<R> map(Function<? super T, ? super R> fun);

/* 类型转换操作,得到的一个转换之后数据类型的Stream流对象 这里需要的参数是Function函数式接口, R apply(T t); T类型的数据转换成R类型数据 */

代码语言:javascript
复制
- count方法【终结方法】

	- long count();

/* 返回当前Stream流对象中有多少个元素 类似有Collection接口下的size(). String的length(); 【终结方法】 一旦执行Stream流对象被关闭 */

代码语言:javascript
复制
-  limit方法

	- Stream<T> limit(long maxSize);

/* 对于当前Stream流对象操作的数据进行限制操作,限制个数到maxSize 例如: Stream流中保存的有10个元素,limit 5 ==> 前五个元素 */

代码语言:javascript
复制
- skip方法

	- Stream<T> skip(long n);

/* 返回值依然是一个Stream流对象,这里跳过当前Stream流对象前n个元素 */

代码语言:javascript
复制
- concat方法

	- static Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) 

/* 拼接两个Stream流对象,是一个静态方法,得到新的Stream流对象 */

代码语言:javascript
复制
- 原始操作方式和Stream流方式对比

	- 1. 一个String类型的字符串集合,"1,骚磊,16"
  1. 过滤没有5的数据
  2. 跳过前三个数据
  3. 限制得到前5个数据
  4. 两个String类型集合字符串合并
  5. 转换成Person类型
  6. 展示数据

方法引用

Lambda冗余问题以及方法引用初识

方法引用小要求

  • testPrint(“郑州加油!!!”, str -> System.out.println(str));

testPrint(“郑州加油!!!”, System.out::println);

  1. 明确对象 对象 ==> 调用者 类对象,类名,super,this,构造方法,数组构造方法
  2. 明确的执行方法 该方法只有名字不需要显式出现参数
  3. 需要处理的数据 【联想,推导,省略】
  4. :: 方法引用格式

通过类对象来执行方法引用

    1. 明确对象 类对象
  1. 明确执行的方法 自定义
  2. 处理的数据 简单要求为String类型

通过类名来执行方法引用

通过super关键字执行方法引用

通过this关键字执行方法引用

类构造方法引用

数组创建方式引用

单例模式

要求

  • 当前类有且只有一个对象,一旦当前类存在一个对象之后,无法在重新创建当前类的对象。就算是你要创建,代码返回的对象依然是上一次创建的对象。 懒汉模式,饿汉模式

单例模式推导【懒汉】

另一种单例模式【饿汉】

NIO

BIO概述

  • BIO BIO ==> Basic IO (基本IO), Block IO(阻塞IO) Scanner操作,文件读写操作,Socket数据传输操作… 都是BIO 比如TCP群聊,私聊聊天室 Socket涉及到的IO,也是BIO 资源浪费: 1. 多线程,每一个Socket会对应一个线程,如果用户量巨大,会导致线程过 多,资源处理过多 2. 采用阻塞状态,一旦进入阻塞,代码无法执行其他操作。 3. 承载量一般,吞吐量比较小,同时可靠性不佳

NIO概述

  • NIO NIO ==> New IO(新IO), Non-Block IO(非阻塞IO) NIO非阻塞IO,允许当前程序在处理IO事务时,不会影响其他程序的运行,可以在不使用多线程的情况下,满足IO操作要求。 三大核心部分: 通道 Channel 文件操作,网络数据传递操作使用的通道 缓冲 Buffer 缓冲使用可以提高操作效率,减少不必要的读写次数 选择器 Selector 真·核心 老大 boss

Buffer Channel完成文件操作

  • 常用API
    • java.nio.Buffer Buffer缓冲区 ByteBuffer 字节缓冲 常用 ShortBuffer IntBuffer LongBuffer CharBuffer 字符缓冲 常用 FloatBuffer DoubleBuffer

常用方法: public static ByteBuffer allocate(int capacity); 按照指定的字节数分配对应的缓冲区空间,保存字节数据 public byte get(); 从字节缓冲区对象中读取一个byte类型数组 public final Buffer flip(); 翻转缓冲区,回到缓冲区的开始位置。 public static ByteBuffer wrap(byte[] arr); 存入一个byte类型数组到缓冲区,会得到一个新的ByteBuffer public static ByteBuffer put(byte[] b); 将字节数组存入缓冲区

Channel接口,通道接口 FileChannel 文件操作通道 DatagramChannel UDP协议数据包操作的Channel ServerSocketChannel TCP服务端ServerSocket对应Channel SocketChannel TCP客户端Socket对应Channel

首先操作文件,以FileChannel为例 public long read(ByteBuffer buffer); 从通道中读取数据到ByteBuffer中 public long write(ByteBuffer buffer); 从Buffer中写数据到通道中 public long transferFrom(ReadableByteChannel src, long position, long count) 从指定srcChannel中,指定位置position开始,读取count个元素,到当前通道中 文件复制操作。

代码语言:javascript
复制
public long	transferTo(long position, long count, WritableByteChannel target) 
将当前通道中的数据写入到target中,从当前通道的position位置开始,计数count
  • 操作文件数据

网络编程使用NIO【重点】

  • Selector选择器老大
    • Selector 选择器,网络编程使用NIO的大哥!!! 服务器可以执行一个线程,运行Selector程序,进行监听操作。 新连接, 已经连接, 读取数据,写入数据

Selector常用方法: public static Selector Open(); 得到一个选择器对象 public int select(long timeout); 监听所有注册通道,存在IO流操作是,会将对应的信息SelectionKey存入到内部的集 合中,参数是一个超时时间 public Set selectionKeys(); 返回当前Selector内部集合中保存的所有SelectionKey

  • SelectionKey
    • SelectionKey 表示Selector和网络通道之间的关系 int OP_ACCEPT; 16 需要连接 int OP_CONNECT; 8 已经连接 int OP_READ; 1 读取操作 int OP_WRITE; 4 写入操作 SelectionKey public abstract Selector selector(); 得到与之关联的 Selector 对象 public abstract SelectableChannel channel(); 得到与之关联的通道 public final Object attachment(); 得到与之关联的共享数据 public abstract SelectionKey interestOps(int ops); 设置或改变监听事件 public final boolean isAcceptable(); 是否可以 accept public final boolean isReadable(); 是否可以读 public final boolean isWritable(); 是否可以写
  • ServerSocketChannel
    • ServerSocketChannel 服务端Socket程序对应的Channel通道 常用方法: public static ServerSocketChannel open(); 开启服务器ServerSocketChannel通道,等于开始服务器程序 public final ServerSocketChannel bind(SocketAddress local); 设置服务器端端口号 public final SelectableChannel configureBlocking(boolean block); 设置阻塞或非阻塞模式, 取值 false 表示采用非阻塞模式 public SocketChannel accept(); [非阻塞] 获取一个客户端连接,并且得到对应的操作通道 public final SelectionKey register(Selector sel, int ops); [重点方法] 注册当前选择器,并且选择监听什么事件
  • SocketChannel
    • SocketChannel 客户端Socket对应的Channel对象

常用方法: public static SocketChannel open(); 打卡一个Socket客户端Channel对象 public final SelectableChannel configureBlocking(boolean block) 这里可以设置是阻塞状态,还是非阻塞状态 false,表示非阻塞 public boolean connect(SocketAddress remote); 连接服务器 public boolean finishConnect(); 如果connect连接失败,可以通过finishConnect继续连接 public int write(ByteBuffer buf); 写入数据到缓冲流中 public int read(ByteBuffer buf); 、 从缓冲流中读取数据 public final SelectionKey register(Selector sel, int ops, Object attechment); 注册当前SocketChannel,选择对应的监听操作,并且可以带有Object attachment参数 public final void close(); 关闭SocketChannel

XMind: ZEN - Trial Version

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 第六周总结
    • TCP多人聊天室实现
      • 分析
      • 客户端实现
      • 资源关闭问题
      • 功能拓展
    • JSON
      • JSON格式概述
      • 数据格式
      • 解析JSON格式工具
    • 注解
      • 注解概述
      • Java中自定义注解
      • 注解使用总结
    • 函数式接口
      • 函数式接口
      • 函数式编程思想
      • Java中提供的常用函数式接口
    • Stream流
      • Stream流引入
      • 传统遍历方式和Stream类处理方式对比
      • Stream流对应的思想
      • 获取Stream流
      • Stream常用方法
    • 方法引用
      • Lambda冗余问题以及方法引用初识
      • 方法引用小要求
      • 通过类对象来执行方法引用
      • 通过类名来执行方法引用
      • 通过super关键字执行方法引用
      • 通过this关键字执行方法引用
      • 类构造方法引用
      • 数组创建方式引用
    • 单例模式
      • 要求
      • 单例模式推导【懒汉】
      • 另一种单例模式【饿汉】
    • NIO
      • BIO概述
      • NIO概述
      • Buffer Channel完成文件操作
      • 网络编程使用NIO【重点】
相关产品与服务
云服务器
云服务器(Cloud Virtual Machine,CVM)提供安全可靠的弹性计算服务。 您可以实时扩展或缩减计算资源,适应变化的业务需求,并只需按实际使用的资源计费。使用 CVM 可以极大降低您的软硬件采购成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档