Java javase15

news/2024/11/15 7:31:34/

一、网络编程
(一)软件结构

  • C/S结构:全称为Client/Server结构,是指客户端和服务器结构。常见的有QQ、迅雷等。
  • B/S结构:全称为Browser/Server结构,是指浏览器和服务器结构。常见的有谷歌、火狐等等。
  • 网络编程:就是在一定的协议下实现两台计算机的通信的程序。
    (二)网络通信协议
  • 网络通信协议:通过计算机网络使多台计算机实现连接位于同一个网络中的计算机在进行连接和通信时需要遵守的一定规则。在计算机网络中,这些连接和通信的规则被称为网络通信协议,它对数据传输的格式、传输的速率和步骤做了统一规定,通信双方必须同时遵守才能完成数据交换。
  • TCP/IP协议:传输控制协议/因特网互联协议,是Internet最基本最广泛的协议。分为应用层、传输层、网络层(核心层)、链路层。
    (三)协议分类
  • java.net包中提供两种常见的网路协议的支持。
    UDP:用户数据报协议。UDP是无线通信协议,在数据传输时,数据的发送端和接收端不建立逻辑连接。
    特点:数据被限制在64KB内,超出该范围不能发送。
    TCP:传输控制协议。TCP协议是面向连接的通信协议,在传输数据之前,在发送端和接收端建立逻辑连接,然后在传输数据,它提供了两台计算机之间可靠无差错的数据传输。
    在TCP协议中,在发送数据的准备阶段,客户端与服务器之间三次交互以保证连接的可靠性。
    三次握手
  1. 第一次:客户端向服务器端发出连接请求,等待服务器确认。
  2. 第二次:服务器端向客户端回送一个响应,通知客户端收到了连接请求。
  3. 第三次:客户端再次向服务器端发送确认信息,确认连接。
    (四)网络编程三要素
    协议:计算机网络通信遵守的规则。
    IP地址
  • IP地址:互联网协议地址,俗称IP。IP地址用来给一个网路中的计算机设备做唯一的编号。
  • IP地址分类
  • IPv4:一个32位的二进制数,通常被分为4个字节。表示为a.b.c.d形式,例如192.168.65.100
  • IPv6:采用128位地址长度,每16个字节分成一组,分成8组16进制数,表示为ABCD:EF01:2345:6789:ABCD:EF01:2345:6789
  • 常用命令
  • 查看本机IP地址,在控制台输入`ipconfig
  • 检查网络是否连通在控制台输入ping 空格 IP地址
  • 本机IP地址:localhost
    端口号
  • IP地址可以唯一标识网络中的设备,端口号可以唯一标识设备中的进程(应用程序)了。
  • 端口号:用两个字节表示的整数,取值范围是065535。其中,01023之间的端口号用于一些知名网络服务应用,普通的应程序需要使用1024以上的端口号。网络软件的端口号不能重复。
  • 常用的端口号
    1. 80端口 网络端口
    2. 数据库 MySQL:3306 Oracle:1521
    3. Tomca服务器:8080
      二、TCP通信程序
      (一)概述
      TCP通信能否实现两台计算机之间的数据交互,通信的两端,要严格区分客户端(Client)和服务端(Server)
      两端通信时步骤
  1. 服务端程序,需要事先启动,等待客户端连接

  2. 客户端主动连接服务器端,连接成功才能通信。服务端不可以主动连接客户端。
    Java中提供两个类用于实现TCP通信程序

  3. 客户端:java.io.Socket类表示。创建Socket对象,向服务端发出连接请求,服务端响应请求,两者建立连接开始通信。

  4. 服务端:java.io.SeverSocket类表示。创建SeverSocket对象,相当于开启一个服务,并等待客户端的连接。
    (二)代码实现
    表示客户端的类

    • java.net.Socket:此类实现客户端套接字。套接字是两台机器间通信的端点。
    • 套接字:包含了IP地址和端口的网络单位。
      构造方法
      -Socke(String host, int port):创建一个流套接字并将其连接到指定主机上的指定端口号。
      参数:
      • Sting host:服务器主机的名称/IP地址
      • int port:服务器的端口号
        成员方法
      • OutputStream getOutputStream( ):返回此套接字的输出流。
      • InputStream getInputStream( ):返回此套接字的输入流。
      • void close( ):关闭此套接字。
        实现步骤
      1. 创建一个客户端对象Socket,构造方法绑定服务器的IP地址和端口号
      2. 使用Socket对象中的方法getOutputStream( )获取网络字节输出流OutputStream对象。
      3. 使用网络字节输出流OutputStream对象中的方法write,给服务器发送数据
      4. 使用Socket对象中的方法getInputStream( )获取网络字节输入流InputStream对象
      5. 使用网络字节输入流InputStream对象中的方法read,读取服务器回写的数据,
      6. 释放资源(Socket)
        注意
    1. 客户端和服务器端进行交互,必须使用Socket中提供的网络流,不能使用自己创建的流对象
    2. 当我们创建客户端对象Socket时,就会请求服务器和服务器经过3次握手建立连接通路。这时如果服务器没有启动,就会抛出异常。如果启动,就可以进行交互。

    表示服务器的类

    • java.net.ServerSocket:此类实现服务器端套接字
      构造方法
    • ServerSocket( int port):创建绑定到特定端口的服务器套接字
      成员方法
    • Socket accep( ):倾听并接受到此套接字的连接。
      服务器的实现步骤
    1. 创建服务器ServerSocket对象和系统要指定的端口号
    2. 使用ServerSocket对象中的方法accept,获取到请求的客户端对象Socket
    3. 使用Socket对象中的方法getInputStream( )获取网络字节输入流InputStream对象
    4. 使用网络字节输入流InputStream( )对象中方法read,读取客户端发送的数据
    5. 使用Socket对象中的方法getOutputStream( )获取网络字节输出流OutputStream对象
    6. 使用网络字节输出流OutputStream对象中方法write,给客户端回写数据
    7. 释放资源
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;public class TCPL {public static void main(String[] args) throws IOException {Socket soc = new Socket("127.0.0.1",8888);OutputStream os = soc.getOutputStream();os.write("你好服务器".getBytes());InputStream is = soc.getInputStream();byte [] bytes = new byte[1024];int len=is.read(bytes);System.out.println(new String(bytes,0,len));soc.close();}
}
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;public class TCPS {public static void main(String[] args) throws IOException {ServerSocket sso = new ServerSocket(8888);Socket soc = sso.accept();InputStream is = soc.getInputStream();byte [] bytes = new byte[1024];int len =is.read(bytes);System.out.println(new String(bytes,0,len));OutputStream os =soc.getOutputStream();os.write("收到谢谢".getBytes());soc.close();sso.close();}
}

综合案例:文件上传
实现步骤
客户端

  1. 创建一个本地字节输入流FileInputStream对象,构造方法中绑定要读取的数据源
  2. 创建一个客户端Socke对象,构造方法中绑定服务器的IP地址和端口号
  3. 使用Socket中方法getOutputStream,获取网络字节输出流OutputStream对象
  4. 使用本地字节输入流FileInputStream对象中方法read,读取本地文件
  5. 使用网络字节输出流OutputStream对象中方法write,把读取到的文件上传到服务器
  6. 使用Socket方法getInputStream,获取网络字节输入流InputStream对象
  7. 使用网络字节输入流InputStream对象中方法read读取服务回写的shuju
  8. 释放资源(FileInputStream, Socket)
    服务端
  9. 创建一个服务器ServerSocket对象,和系统指定的端口号
  10. 使用ServerSocket对象中方法accept,获取到请求客户端Socket对象
  11. 使用Socket对象中的方法getInputStream,获取到网络字节输入流InputStream对象
  12. 判断文件是否存在,不存在则创建
  13. 创建一个本地字节输出流FileOutputStream对象,构造方法中绑定要输出的目的地
  14. 使用网络字节输入流InputStream对象中方法read,读取客户端上传的文件
  15. 使用本地字节输出流FileOutputStream对象中的方法write,把读取到的文件保存到服务器的硬盘上
  16. 使用Socket对象中的方法getOutputStream,获取到网路输出流OutputStream对象
  17. 使用网络字节输出流OutputStream对象中的方法write,给客户端回写上传成功
  18. 释放资源
 import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;public class TCPS1 {public static void main(String[] args) throws IOException {ServerSocket sst = new ServerSocket(8888);Socket soc = sst.accept();InputStream is = soc.getInputStream();File file = new File("C:\\Users\\阚开豪\\Desktop\\javaFile\\a");if(!file.exists()){file.mkdirs();}FileOutputStream fos = new FileOutputStream(file+"\\a.txt");int len =0;byte [] bytes = new byte[1024];while ((len=is.read(bytes))!=-1){fos.write(bytes,0,len);}soc.getOutputStream().write("上传成功".getBytes());fos.close();soc.close();sst.close();}
}

import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;public class TCPL1 {public static void main(String[] args) throws IOException {FileInputStream fis  = new FileInputStream("C:\\Users\\阚开豪\\Desktop\\javaFile\\e.txt");Socket soc = new Socket("127.0.0.1",8888);OutputStream os = soc.getOutputStream();int len = 0;byte [] bytes = new byte[1024];while((len=fis.read(bytes))!=-1){os.write(bytes,0,len);}while((len = fis.read(bytes))!=-1){System.out.println(new String(bytes,0,len));}fis.close();soc.close();}
}

文件上传案例的阻塞问题
解决方案
上传完文件给服务器一个结束标记

  • void shutdowOutput( ):禁用此套接字的输出流。对于TCP套接字,任何以前写入的数据都将发送,并且后跟TCP的正常连接序列。
while ((len=is.read(bytes))!=-1){fos.write(bytes,0,len);}soc.shutdowOutput( );

文件上传优化分析

  1. 自定义一个文件的命名规则:防止同名文件被覆盖。
    规则:域名+毫秒值+随机数
  2. 让服务器一直处于监听状态(死循环accept方法)
    有一个客户端上传就保存一个文件,服务器不用被关闭
  3. 提高效率;使用多线程技术
    有一个客户端上传文件,就开启一个线程,完成文件的上传
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;public class TCPL1 {public static void main(String[] args) throws IOException {FileInputStream fis  = new FileInputStream("C:\\Users\\阚开豪\\Desktop\\javaFile\\e.txt");Socket soc = new Socket("127.0.0.1",8888);OutputStream os = soc.getOutputStream();int len = 0;byte [] bytes = new byte[1024];while((len=fis.read(bytes))!=-1){os.write(bytes,0,len);}soc.shutdownOutput();while((len = fis.read(bytes))!=-1){System.out.println(new String(bytes,0,len));}fis.close();soc.close();}
}
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;public class TCPS1 {public static void main(String[] args) throws IOException {ServerSocket sst = new ServerSocket(8888);while(true){Socket soc = sst.accept();new Thread(new Runnable() {@Overridepublic void run() {try{ InputStream is = soc.getInputStream();File file = new File("C:\\Users\\阚开豪\\Desktop\\javaFile\\a");if(!file.exists()){file.mkdirs();}String fileName ="itcast"+System.currentTimeMillis()+new Random().nextInt(300000)+".txt";FileOutputStream fos = new FileOutputStream(file+"\\"+fileName);int len =0;byte [] bytes = new byte[1024];while ((len=is.read(bytes))!=-1){fos.write(bytes,0,len);}soc.getOutputStream().write("上传成功".getBytes());fos.close();soc.close();}catch (IOException e){System.out.println(e);}}}).start();}}
}

三、函数式接口
(一)概念

  • 函数式接口:有且仅有一个抽象方法的接口。
  • Java的函数式接口就是可以使用Lambda使用的接口。
  • 语法糖:使用更加方便,但是原理不变的代码语法。
    二(格式)
@FuncationInterface
修饰符 interface 接口名称{public abstract 返回值类型 方法名称(可选参数信息)//其他非抽象方法内容}
@FuncationInterface
public interface Myfunction{void myMethod( );
}
  • @FuncationInterface注解
  • 作用:检测接口是否为一个函数式接口。
  • 是:编译成功 否:编译失败(接口中没有抽象方法或者抽象方法的个数多于一个)
    (三)函数式接口的使用
    一般可以作为方法的参数和返回值类型
@FunctionalInterface
public interface MyFun {public abstract void method();
}
public class MyFunImp implements MyFun{@Overridepublic void method() {}
}
public class Myfunmain {public static void show(MyFun mf){mf.method();}public static void main(String[] args) {show(new MyFun() {@Overridepublic void method() {System.out.println("匿名内部类实现。");}});show(()->{System.out.println("Lambda表达式实现。");});show(()->System.out.println("简化Lambda表达式实现。"));}
}

函数式编程
(一)Lambda延迟执行
性能浪费的日志案例

public class log {private static void show(int level,String msg ){if(level==1){System.out.println(msg);}}public static void main(String[] args) {String msg1="Hello";String msg2="World";String msg3="Java";show(1,msg1+msg2+msg3);}
}

使用Lambda优化日志案例
Lambda特点:延迟加载
使用前提:必须存在函数式接口

@FunctionalInterface
public interface Msg {public abstract  String build();
}
public class logs {private static void show(int level,Msg msg ){if(level==1){System.out.println(msg.build());}}public static void main(String[] args) {String msg1="Hello";String msg2="World";String msg3="Java";show(1,()->{return msg1+msg2+msg3;});}
}
public class logs {private static void show(int level,Msg msg ){if(level==1){System.out.println(msg.build());}}public static void main(String[] args) {String msg1="Hello";String msg2="World";String msg3="Java";show(1,()->{return msg1+msg2+msg3;});}
}

(二)使用Lambda作为参数和返回值
使用Lambda表达式作为方法参数,其实就是使用函数式接口作为方法参数。

  • Runnable接口就是一个函数式接口,假设有一个startThread方法使用该接口作为参数,那么就可以使用Lambda进行传参,这种情况和Thread类的构造方法参数为Runnable没有本质区别。
public class Lam1 {private static void startThread(Runnable task){new Thread(task).start();}public static void main(String[] args) {startThread(()-> System.out.println("线程任务执行"));}
}

**如果一个方法的返回值类型是一个函数式接口,就可以直接返回一个Lambda表达式。**当需要通过一个方法来获取Comparator接口类型对象作为排序器时,就可以调用该方法获取。
直接return一个Lambda表达式即可

import java.util.Arrays;
import java.util.Comparator;public class Lam2 {private static Comparator<String>  newcom(){return (a,b)->b.length()-a.length();}public static void main(String[] args) {String[] array ={"abc","ab","abcd"};System.out.println(Arrays.toString(array));//[abc, ab, abcd]Arrays.sort(array,newcom());System.out.println(Arrays.toString(array));//[abcd, abc, ab]}
}

(三)常用的函数式接口
Supplier接口

  • java.util.function.Supplier<T>:接口仅包含一个无参的方法:T get( )。用来获取一个泛型指定类型的对象数据。
  • Supplier<T>接口被称之为生产型接口,指定接口的泛型是什么类型,那么接口中的get方法就会产生什么类型的数据。
import java.util.function.Supplier;public class Sup {public static String getString(Supplier<String> sup){return sup.get();}public static void main(String[] args) {String s =getString(()->{return "zhangsan";});//简化Lambda表达式String s2=getString(()->"lisi");System.out.println(s);}
}

Consumer接口

  • java.tuil.function.Consumer<T>接口与Supplier接口相反,它不生产数据,而是消费数据,其数据类型由泛型决定。
  • Consumer接口中包含抽象方法void accept(T t),是为消费一个指定泛型的数据。
  • Consumer接口是一个消费型接口,泛型执行什么类型就可以使用accept方法消费什么类型的数据。具体怎么使用,需要自定义。
import java.util.function.Consumer;public class Cor {public static void method(String name, Consumer<String> con){con.accept(name);}public static void main(String[] args) {method("zhangsan",(String name)->{String rename = new StringBuffer(name).reverse().toString();System.out.println(rename);});}
}
  • 默认方法:andthen
    作用:需要两个Consumer接口,可以把两个接口组合到一起对数据进行消费。
import java.util.function.Consumer;public class Corps {public static void method(String s, Consumer<String> con1,Consumer<String> con2){con1.andThen(con2).accept(s);}public static void main(String[] args) {method("Hello", (t)->{System.out.println(t.toUpperCase());},(t)->{System.out.println(t.toLowerCase());});}
}

Predicate接口

  • java.util.function.Predicate<T>接口
    作用:对某种数据类型进行判断,结果返回一个boolean值
    Predicate接口中包含一个抽象方法:
    - boolean test(T t):用来对指定数据类型进行判断的方法
    结果:
    符合条件返回true
    不符合条件返回false
import java.util.function.Predicate;public class pred {public static boolean check(String s, Predicate<String> pre){return pre.test(s);}public static void main(String[] args) {String s = "abcdef";boolean b = check(s,str->str.length()>5);System.out.println(b);}}

-默认方法and
将两个Predicate条件使用”与“逻辑连接起来实现”并且“的效果时,可以使用default方法and

  • 使用and方法,一个用于判断字符串长度。一个用于判断字符串中是否包含’ a '。
import java.util.function.Predicate;public class pred1{public static boolean check(String s, Predicate<String> pre1,Predicate<String> pre2){return pre1.and(pre2).test(s);}public static void main(String[] args) {String s = "HelloJava";boolean b = check(s,(String str)->{return str.length()>5;},(String str)->{return str.contains("a");});System.out.println(b);}
}
  • 默认方法or
    and类似,or方法实现逻辑关系中的“或。
    -默认方法:negate
    表示非即取反
import java.util.function.Predicate;public class pred2 {public static boolean check(String s, Predicate<String> pre1,Predicate<String> pre2){return pre1.or(pre2).test(s);}public static  boolean check2(String s,Predicate<String> pre){return pre.negate().test(s);}public static void main(String[] args) {String s="HelloJava";boolean b = check(s,(String str)->{return str.length()>5;},(String str)->{return str.contains("a");});System.out.println(b);boolean b2 =check2(s,(String str)->{return str.length()<10;});System.out.println(b2);}
}

Function接口
-java.util.function.Function<T,R>接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。
-抽象方法apply

  • R apply(T t):根据类型T的参数获取类型R的结果。例如将String类型转换为Integer类型。
import java.util.function.Function;public class Fun1 {public static void change(String s, Function<String,Integer> fun){int in = fun.apply(s);System.out.println(in);}public static void main(String[] args) {String s = "1234";change(s,(String str)->{return Integer.parseInt(str);});//优化Lambdachange(s,str->Integer.parseInt(str));}
}

默认方法andthen

import java.util.function.Function;public class Fun2 {public static void change(String s, Function<String,Integer> fun1,Function<Integer,String> fun2){String str = fun1.andThen(fun2).apply(s);System.out.println(str);}public static void main(String[] args) {String s = "123";change(s,(String str)->{return Integer.parseInt(str)+10;},(Integer i)->{return i+" ";});change(s,str->Integer.parseInt(str)+10,i->+i+" ");}
}

http://www.ppmy.cn/news/812806.html

相关文章

JAVASE(3.15)

学习不要眼高手低&#xff0c;学习是一点点积累的。即使你现在很菜&#xff0c;坚持学一个学期不会差的&#xff01;只要花时间学习&#xff0c;每天都是进步的&#xff0c;这些进步可能你现在看不到&#xff0c;但是不要小瞧了积累效应&#xff0c;30天&#xff0c;60天&#…

解读NE555

NE555 1、简介2、数据手册功耗相关封装功能图 3、工作原理 1、简介 NE555是一种集成电路&#xff0c;也称为555计时器&#xff0c;广泛应用于模拟电路中。NE555集成电路具有多种应用&#xff0c;包括方波发生器、多谐振荡器、脉冲宽度调制器、定时器等。它是一种通用、可靠、经…

【ts类型体操】00004-easy-pick

要求&#xff1a;实现TS内置的Pick<T,K> 从类型T中选择出属性K&#xff0c;构造一个新的类型 type MyPick<T, K>any import type { Equal, Expect } from type-challenges/utilstype cases [Expect<Equal<Expected1, MyPick<Todo, title>>>,E…

胖子的纠结

02.* Copyright (c) 2013, 烟台大学计算机学院 03.* All rights reserved. 04.* 作 者&#xff1a;石尧 05.* 完成日期&#xff1a;2014 年 2 月 28 日 06.* 版 本 号&#xff1a;v1.0 07.*/ #include <iostream> #include <string.h> struct xinxi {char name[…

618运动好物清单、必买运动装备推荐

618已经进行得如火如荼&#xff0c;不知道你们是否已经将心动好物收入囊中。作为一个运动健身爱好者&#xff0c;这种薅羊毛的时候我肯定不会放过&#xff01;下边我给大家整理了一份自己的购物清单&#xff0c;身边达人大神好评推荐&#xff0c;大家可以抄作业~ 1、南卡runne…

防汗耳机选什么牌子好、适合运动佩戴的运动耳机推荐

运动和音乐是很多人生活中不可或缺的元素&#xff0c;一款好的耳机可以让运动更加有激情&#xff0c;也能更好地享受运动的乐趣。对于喜欢运动的人来说&#xff0c;选择一款佩戴舒适、稳固、防水的运动耳机是非常重要的。今天&#xff0c;我们分享一下我用过的5款最好用的运动耳…

高品质运动耳机哪款更好用、运动耳机最好的牌子推荐

在运动的时候大家都会选择戴上耳机&#xff0c;用音乐来”调味“&#xff0c;让跑步的过程不那么枯燥乏味。说到运动耳机&#xff0c;除了老生常谈的音质以外&#xff0c;耳机的材质、耳机的工艺&#xff0c;耳机的佩戴稳固性等&#xff0c;也都在影响着用户的体验&#xff0c;…

大胖子走迷宫

题目描述 小明是个大胖子&#xff0c;或者说是个大大胖子&#xff0c;如果说正常人占用 1 \times 111 的面积&#xff0c;小明要占用 5\times 555 的面积。 由于小明太胖了&#xff0c;所以他行动起来很不方便。当玩一些游戏时&#xff0c;小明相比小伙伴就吃亏很多。 小明的…