第17章 网络编程

本章将主要介绍Java网络通信的支持,通过这些网络支持类,Java程序可以非常方便地访问互联网上的HTTP服务、FTP服务等,并可以直接取得互联网上的远程资源,还可以向远程资源发送GET、POST请求。

17.1 网络编程的基础知识

17.1.1 网络基础知识

  • 计算机网络,就是把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息,共享硬件、软件、数据信息等资源。
  • IP(Internet Protocol)协议又称互联网协议,是支持网间互联的数据报协议。它提供网间连接的完善功能,包括IP数据报规定互联网络范围内的地址格式。
  • TCP(Transmission Control Protocol)协议,即传输控制协议,它规定一种可靠的数据信息传递服务。虽然IP和TCP这两个协议功能不尽相同,也可以分开单独使用,但它们是在同一个时期作为一个协议来设计的,并且在功能上也是互补的。
  • TCP/IP协议四层模型,OSI七层模型:

17.1.2 IP地址和端口号

  • IP地址用于唯一地标识网络中的一个通信实体,这个通信实体既可以是一台主机,也可以是一台打印机,或者是路由器的某一个端口。而在基于IP协议网络中传输的数据包,都必须使用IP地址来进行标识
  • IP地址被分成了A、B、C、D、E五类,每个类别的网络标识和主机标识各有规则:
    A类:10.0.0.0~10.255.255.255
    B类:172.16.0.0~172.31.255.255
    C类:192.168.0.0~192.168.255.255
  • 端口是一个16位的整数,用于表示数据交给哪个通信程序处理。因此,端口就是应用程序与外界交流的出入口,它是一种抽象的软件结构,包括一些数据结构和I/O(基本输入/输出)缓冲区。
  • 端口号可以从0到65535,通常将它分为如下三类。
    公认端口(Well Known Ports):从0到1023,它们紧密绑定(Binding)一些特定的服务。
    注册端口(Registered Ports):从1024到49151,它们松散地绑定一些服务。应用程序通常应该使用这个范围内的端口。
    动态和/或私有端口(Dynamic and/or Private Ports):从49152到65535,这些端口是应用程序使用的动态端口,应用程序一般不会主动使用这些端口。

17.2 Java的基本网络支持

Java为网络支持提供了java.net包,该包下的URL和URLConnection等类提供了以编程方式访问Web服务的功能,而URLDecoder和URLEncoder则提供了普通字符串和application/x-www-form-urlencoded MIME字符串相互转换的静态方法。

17.2.1 使用InetAddress

  • Java提供了InetAddress类来代表IP地址,InetAddress下还有两个子类:Inet4Address、Inet6Address。
  • InetAddress类没有提供构造器,而是提供了如下两个静态方法来获取InetAddress实例。

getByName(String host):根据主机获取对应的InetAddress对象。
getByAddress(byte[] addr):根据原始IP地址来获取对应的InetAddress对象。

  • InetAddress还提供了如下三个方法来获取InetAddress实例对应的IP地址和主机名。

String getCanonicalHostName():获取此IP地址的全限定域名。
String getHostAddress():返回该InetAddress实例对应的IP地址字符串(以字符串形式)。
String getHostName():获取此IP地址的主机名。

  • InetAddress类还提供了一个getLocalHost()方法来获取本机IP地址对应的InetAddress实例。提供了一个isReachable()方法,用于测试是否可以到达该地址。

17.2.2 使用URLDecoder和URLEncoder

  • URLDecoder和URLEncoder用于完成普通字符串application/x-www-form-urlencodedMIME字符串之间的相互转换。
  • URLDecoder类包含一个decode(String s, String enc)静态方法,它可以将看上去是乱码的特殊字符串转换成普通字符串。
  • URLEncoder类包含一个encode(String s, String enc)静态方法,它可以将普通字符串转换成application/x-www-form-urlencoded MIME字符串。

17.2.3 URL、URLConnection和URLPermission

  • URL(Unifore Resource Locator)对象代表统一资源定位器,指向互联网“资源” 的指针。可以由协议名、主机、端口和资源组成,即满足如下格式:
protoclo://host:port/resourceName
//例如下面的URL地址:
http://www.crazyit.org/index.php
  • URL类提供了多个构造器用于创建URL对象,一旦获得了URL对象之后,就可以调用如下方法来访问该URL对应的资源。

String getFile():获取该URL的资源名。
String getHost():获取该URL的主机名。
String getPath():获取该URL的路径部分。
int getPort():获取该URL的端口号。
String getProtocol():获取该URL的协议名称。
String getQuery():获取该URL的查询字符串部分。
URLConnection openConnection():返回一个URLConnection对象,它代表了与URL所引用的远程对象的连接。
InputStream openStream():打开与此URL的连接,并返回一个用于读取该URL资源的InputStream。

  • 提供的openStream()方法可以读取该URL资源的InputStream,通过该方法可以非常方便地读取远程资源——甚至实现多线程下载
  • Java 8新增了一个URLPermission工具类,用于管理HttpURLConnection的权限问题,如果在HttpURLConnection安装了安全管理器,通过该对象打开连接时就需要先获得权限。
  • 通常创建一个和URL的连接,并发送请求、读取此URL引用的资源需要如下几个步骤。
    (1)通过调用URL对象的openConnection()方法来创建URLConnection对象。
    (2)设置URLConnection的参数和普通请求属性。
    (3)如果只是发送GET方式请求,则使用connect()方法建立和远程资源之间的实际连接即可;如果需要发送POST方式的请求,则需要获取URLConnection实例对应的输出流来发送请求参数。
    (4)远程资源变为可用,程序可以访问远程资源的头字段或通过输入流读取远程资源的数据。

17.3 基于TCP协议的网络编程

TCP/IP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket,从而在通信的两端之间形成网络虚拟链路。java使用Socket对象来代表两端的通信端口,通过Socket产生的IO流来进行网络通信。

17.3.1 TCP协议基础

  • IP协议是Internet上使用的一个关键协议,它的全称是Internet Protocol,即Internet协议,通常简称IP协议。通过使用IP协议,从而使Internet成为一个允许连接不同类型的计算机和不同操作系统的网络。
  • TCP协议被称作一种端对端协议。这是因为它对两台计算机之间的连接起了重要作用:当一台计算机需要与另一台远程计算机连接时,TCP协议会让它们建立一个连接:用于发送和接收数据的虚拟链路。
  • IP协议保证了计算机之间可以发送和接收数据;
  • TCP协议解决数据分组在传输过程中可能出现的问题。

17.3.2 使用ServerSocket创建TCP服务器端

  • Java中能接收其他通信实体连接请求的类是ServerSocket,ServerSocket对象用于监听来自客户端的Socket连接,如果没有连接,它将一直处于等待状态。
  • ServerSocket包含一个监听来自客户端连接请求的方法:

Socket accept():如果接收到一个客户端Socket的连接请求,该方法将返回一个与客户端Socket对应的Socket;否则该方法将一直处于等待状态,线程也被阻塞。

  • 为了创建ServerSocket对象,ServerSocket类提供了如下几个构造器

ServerSocket(int port):用指定的端口port来创建一个ServerSocket。该端口应该有一个有效的端口整数值,即0~65535。
ServerSocket(int port, int backlog):增加一个用来改变连接队列长度的参数backlog。
ServerSocket(int port, int backlog, InetAddress localAddr):在机器存在多个IP地址的情况下,允许通过localAddr参数来指定将ServerSocket绑定到指定的IP地址。

  • 当ServerSocket使用完毕后,应使用ServerSocket的close()方法来关闭该ServerSocket。
  • 在通常情况下,服务器不应该只接收一个客户端请求,而应该不断地接收来自客户端的所有请求,所以Java程序通常会通过循环不断地调用ServerSocket的accept()方法。

17.3.3 使用Socket进行通信

  • 客户端通常可以使用Socket的构造器来连接到指定服务器,Socket通常可以使用如下两个构造器。

Socket(InetAddress/String remoteAddress, int port):创建连接到指定远程主机、远程端口的Socket,该构造器没有指定本地地址、本地端口,默认使用本地主机的默认IP地址,默认使用系统动态分配的端口。
Socket(InetAddress/String remoteAddress, int port, InetAddress localAddr, intlocalPort):创建连接到指定远程主机、远程端口的Socket,并指定本地IP地址和本地端口,适用于本地主机有多个IP地址的情形。

  • 当客户端、服务器端产生了对应的Socket之后,程序无须再区分服务器端、客户端,而是通过各自的Socket进行通信。Socket提供了如下两个方法来获取输入流和输出流。

InputStream getInputStream():返回该Socket对象对应的输入流,让程序通过该输入流从Socket中取出数据。
OutputStream getOutputStream():返回该Socket对象对应的输出流,让程序通过该输出流向Socket中输出数据。

17.3.4 加入多线程

  • 在使用传统BufferedReader的readLine)方法读取数据时,在该方法成功返回之前,线程被阻塞,程序无法继续执行。考虑到这个原因,服务器端应该为每个Socket单独启动一个线程,每个线程负责与一个客户端进行通信。
  • 客户端读取服务器端数据的线程同样会被阻塞,所以系统应该单独启动一个线程,该线程专门负责读取服务器端数据。

17.3.5 记录用户信息

(1)客户端发送来的信息必须有特殊的标识——让服务器端可以判断是公聊信息,还是私聊信息。

  • 为了解决第一个问题,可以让客户端在发送不同信息之前,先对这些信息进行适当处理,比如在内容前后添加一些特殊字符——这种特殊字符被称为协议字符。本例提供了一个CrazyitProtocol接口,该接口专门用于定义协议字符。

(2)如果是私聊信息,客户端会发送该消息的目的用户(私聊对象)给服务器端,服务器端如何将该信息发送给该私聊对象。

  • 为了解决第二个问题,可以考虑使用一个Map来保存聊天室所有用户和对应Socket之间的映射关系——这样服务器端就可以根据用户名来找到对应的Socket。但实际上本程序并未这么做,程序仅仅是用Map保存了聊天室所有用户名和对应输出流之间的映射关系,因为服务器端只要获取该用户名对应的输出流即可。服务器端提供了一个HashMap的子类,该类不允许value重复,并提供了根据value获取key,根据value 删除key等方法。

17.3.6 半关闭的Socket

  • 在第15章介绍IO时提到,如果要表示输出已经结束,则可以通过关闭输出流来实现。但在网络通信中则不能通过关闭输出流来表示输出已经结束,因为当关闭输出流时,该输出流对应的Socket也将随之关闭,这样导致程序无法再从该Socket的输入流中读取数据了。
  • 在这种情况下,Socket提供了如下两个半关闭的方法,只关闭Socket的输入流或者输出流,用以表示输出数据已经发送完成。

shutdownlnput():关闭该Socket的输入流,程序还可通过该Socket的输出流输出数据。
shutdownOutput():关闭该Scoket的输出流,程序还可通过该Socket的输入流读取数据。

  • 当调用shutdownlnput()或shutdownOutput()方法关闭Socket的输入流或输出流之后,该Socket处于“半关闭”状态,Socket 可通过isInputShutdown()方法判断该Socket是否处于半读状态(read-half),通过isOutputShutdown()方法判断该Socket是否处于半写状态(write-half)。

17.3.7 使用NIO实现非阻塞Socket通信

  • 从JDK1.4开始,Java提供了NIOAPI来开发高性能的网络服务器,前面介绍的网络通信程序是基于阻塞式API的一—即当程序执行输入、输出操作后,在这些操作返回之前会一直阻塞该线程,所以服务器端必须为每个客户端都提供一个独立线程进行处理,当服务器端需要同时处理大量客户端时,这种做法会导致性能下降。使用NIO API则可以让服务器端使用一个或有限几个线程来同时处理连接到服务器端的所有客户端。
  • Selector类:它是SelectableChannel对象的多路复用器,所有希望采用非阻塞方式进行通信的Channel都应该注册到Selector对象。可以通过调用此类的open()静态方法来创建Selector实例,该方法将使用系统默认的Selector来返回新的Selector。

17.3.8 使用Java 7 的AIO实现非阻塞通信

  • Java7的NIO.2提供了异步Channel支持,这种异步Channel可以提供更高效的IO,这种基于异步Channel的IO机制也被称为异步IO(AsynchronousIO)。
  • NIO.2提供了一系列以Asynchronous 开头的Channel接口和类,NIO.2为AIO提供了两个接口和三个实现类,其中AsynchronousSocketChannelAsynchronousServerSocketChannel是支持TCP通信的异步Channel

17.4 基于UDP协议的网络编程

UDP协议是一种不可靠的网络协议,它在通信实例的两端各建立一个Socket,但这两个Socket之间并没有虚拟链路,这两个Socket只是发送、接收数据报的对象。Java提供了DatagramSocket对象作为基于UDP协议的Socket,使用DatagramPacket代表DatagramSocket发送、接收的数据报。

17.4.1 UDP协议基础

  • UDP协议是英文User Datagram Protocol的缩写,即用户数据报协议,主要用来支持那些需要在计算机之间传输数据的网络连接。
  • UDP协议是一种面向非连接的协议,面向非连接指的是在正式通信前不必与对方先建立连接,不管对方状态就直接发送。至于对方是否可以接收到这些数据内容,UDP协议无法控制,因此说UDP协议是一种不可靠的协议。UDP协议适用于一次只传送少量数据、对可靠性要求不高的应用环境。
  • UDP协议和TCP协议简单对比如下:
    TCP协议(打电话):可靠,传输大小无限制,但是需要连接建立时间,差错控制开销大。
    UDP协议(发短信):不可靠,差错控制开销较小,传输大小限制在64KB以下,不需要建立连接。

17.4.2 使用DatagramSocket发送、接收数据

  • Java使用DatagramSocket代表UDP协议的Socket,DatagramSocket本身只是码头,不维护状态,不能产生IO流,它的唯一作用就是接收和发送数据报,Java使用DatagramPacket来代表数据报,DatagramSocket接收和发送的数据都是通过DatagramPacket对象完成的。
  • DatagramSocket的构造器:

DatagramSocket():创建一个DatagramSocket实例,并将该对象绑定到本机默认IP地址、本机所有可用端口中随机选择的某个端口。
DatagramSocket(int prot):创建一个DatagramSocket实例,并将该对象绑定到本机默认IP地址、指定端口。
DatagramSocket(int port, InetAddress laddr):创建一个DatagramSocket实例,并将该对象绑定到指定IP地址、指定端口。

  • 得到了DatagramSocket实例之后,就可以通过如下两个方法来接收和发送数据。

receive(DatagramPacket p):从该DatagramSocket中接收数据报。
send(DatagramPacket p):以该DatagramSocket对象向外发送数据报。

  • 从上面两个方法可以看出,使用DatagramSocket发送数据报时,DatagramSocket并不知道将该数据报发送到哪里,而是由DatagramPacket自身决定数据报的目的地
  • DatagramPacket的构造器:

DatagramPacket(byte[] buf, int length):以一个空数组来创建DatagramPacket对象,该对象的作用是接收DatagramSocket中的数据。
DatagramPacket(byte[] buf, int length, InetAddress addr, int port):以一个包含数据的数组来创建DatagramPacket对象,创建该DatagramPacket对象时还指定了IP地址和端口—这就决定了该数据报的目的地。
DatagramPacket(byte[] buf, int offset, int length):以一个空数组来创建DatagramPacket对象,并指定接收到的数据放入buf数组中时从offset开始,最多放length个字节。
DatagramPacket(byte[] buf, int offset, int length, InetAddress address, int port):创建一个用于发送的DatagramPacket对象,指定发送buf数组中从offset开始,总共length个字节。

  • 在接收数据之前,应该采用上面的第一个或第三个构造器生成一个DatagramPacket对象,给出接收数据的字节数组及其长度。然后调用DatagramSocket的receive()方法等待数据报的到来,receive()将一直等待(该方法会阻塞调用该方法的线程),直到收到一个数据报为止。如下代码所示。
//创建一个接收数据的DatagramPacket对象
DatagramPacket packet = new DatagramPacket(buf,256):
//接收数据报
socket.receive(packet);
  • 在发送数据之前,调用第二个或第四个构造器创建DatagramPacket对象,此时的字节数组里存放了想发送的数据。除此之外,还要给出完整的目的地址,包括IP地址和端口号。发送数据是通过DatagramSocket的send()方法实现的,send()方法根据数据报的目的地址来寻径以传送数据报。如下代码所示。
//创建一个发送数据的DatagramPacket对象
DatagramPacket packet = new Datagrampacket(buf,length,address,port);
//发送数据报
socket.send(packet);

17.4.3 使用MulticastSocket实现多点广播

  • DatagramSocket 只允许数据报发送给指定的目标地址,而MulticastSocket可以将数据报以广播方式发送到多个客户端。

  • 从图17.8中可以看出,MulticastSocket类是实现多点广播的关键,当MulticastSocket 把一个DatagramPacket发送到多点广播IP地址时,该数据报将被自动广播到加入该地址的所有Multicast Socket。MulticastSocket既可以将数据报发送到多点广播地址,也可以接收其他主机的广播信息。

  • MulticastSocket是DatagramSocket的一个子类,也就是说,MulticastSocket是特殊的DatagramSocket。当要发送一个数据报时,可以使用随机端口创建MulticastSocket,也可以在指定端口创建MulticastSocket。

  • MulticastSocket提供了如下三个构造器。

public MulticastSocket():使用本机默认地址、随机端口来创建MulticastSocket对象。
public MulticastSocket(int portNumber):使用本机默认地址、指定端口来创建MulticastSocket对象。
public MulticastSocket(SocketAddress bindaddr):使用本机指定IP地址、指定端口来创建MulticastSocket对象。

  • 创建MulticastSocket对象后,还需要将该MulticastSocket加入到指定的多点广播地址,MulticastSocket使用joinGroup()方法加入指定组;使用leaveGroup()方法脱离一个组。

joinGroup(InetAddress multicastAddr):将该MulticastSocket加入指定的多点广播地址。
leaveGroup(InetAddress multicastAddr):让该MulticastSocket离开指定的多点广播地址。

17.5 使用代理服务器

  • 从Java5开始,Java在java.net包下提供了Proxy和ProxySelector两个类,其中Proxy代表一个代理服务器,可以在打开URLConnection连接时指定Proxy,创建Socket连接时也可以指定Proxy;而ProxySelector代表一个代理选择器,它提供了对代理服务器更加灵活的控制,它可以对HTTP、HTTPS、FTP、SOCKS等进行分别设置,而且还可以设置不需要通过代理服务器的主机和地址。通过使用ProxySelector,可以实现像在Internet Explorer、Firefox等软件中设置代理服务器类似的效果。
  • 代理服务器的功能就是代理用户去取得网络信息。当使用浏览器直接连接其他Internet站点取得网络信息时,通常需要先发送请求,然后等响应到来。代理服务器是介于浏览器和服务器之间的一台服务器,设置了代理服务器之后,浏览器不是直接向Web服务器发送请求,而是向代理服务器发送请求,浏览器请求被先送到代理服务器,由代理服务器向真正的Web服务器发送请求,并取回浏览器所需要的信息,再送回给浏览器。由于大部分代理服务器都具有缓冲功能,它会不断地将新取得的数据存储到代理服务器的本地存储器上,如果浏览器所请求的数据在它本机的存储器上已经存在而且是最新的,那么它就无须从Web服务器取数据,而直接将本地存储器上的数据送回浏览器,这样能显著提高浏览速度。
  • 归纳起来,代理服务器主要提供如下两个功能。
    (1)突破自身IP限制,对外隐藏自身IP地址。突破IP限制包括访问国外受限站点,访问国内特定单位、团体的内部资源。
    (2)提高访问速度,代理服务器提供的缓冲功能可以避免每个用户都直接访问远程主机,从而提高客户端访问速度。

17.5.1直接使用Proxy创建连接

  • Proxy有一个构造器:Proxy(Proxy.Type type,SocketAddress sa),用于创建表示代理服务器的Proxy对象。其中sa参数指定代理服务器的地址,type表示该代理服务器的类型,该服务器类型有如下三种。

Proxy.Type.DIRECT:表示直接连接,不使用代理。
Proxy.Type.HTTP:表示支持高级协议代理,如HTTP或FTP。
Proxy.Type.SOCKS:表示SOCKS(V4或V5)代理。

  • 一旦创建了Proxy对象之后,程序就可以在使用URLConnection 打开连接时,或者创建 Socket连接时传入一个Proxy对象,作为本次连接所使用的代理服务器。
  • 其中URL包含了一个URLConnection openConnection(Proxy proxy)方法,该方法使用指定的代理服务器来打开连接;而Socket则提供了一个Socket(Proxy proxy)构造器,该构造器使用指定的代理服务器创建一个没有连接的Socket对象。

17.5.2使用ProxySelector自动选择代理服务器

  • 前面介绍的直接使用Proxy对象可以在打开URLConnection或Socket时指定代理服务器,但使用这种方式每次打开连接时都需要显式地设置代理服务器,比较麻烦。如果希望每次打开连接时总是具有默认的代理服务器,则可以借助于ProxySelector来实现。
  • ProxySelector代表一个代理选择器,它本身是一个抽象类,程序无法创建它的实例,开发者可以考虑继承ProxySelector来实现自己的代理选择器。实现ProxySelector的步骤非常简单,程序只要定义一个继承ProxySelector的类,并让该类实现如下两个抽象方法。

List<Proxy>select(URI uri):根据业务需要返回代理服务器列表,如果该方法返回的集合中只包含一个Proxy,该Proxy将会作为默认的代理服务器。
connectFailed(URI uri,SocketAddress sa,IOException ioe):连接代理服务器失败时回调该方法。

  • 实现了自己的ProxySelector类之后,调用ProxySelector的setDefault(ProxySelector ps)静态方法来注册该代理选择器即可。
  • 除此之外,Java为ProxySelector提供了一个实现类:sun.net.spi.DefaultProxySelector(这是一个未公开API,应尽量避免直接使用该API),系统已经将DefaultProxySelector注册成默认的代理选择器,因此程序可调用ProxySelector.getDefault)方法来获取DefaultProxySelector实例。
  • DefaultProxySelector 继承了ProxySelector,当然也实现了两个抽象方法,它的实现策略如下。

connectFailed():如果连接失败,DefaultProxySelector将会尝试不使用代理服务器,直接连接远程资源。
select():DefaultProxySelector 会根据系统属性来决定使用哪个代理服务器。ProxySelector会检测系统属性与URL之间的匹配,然后决定使用相应的属性值作为代理服务器。关于代理服务器常用的属性名有如下三个。
(1)http.proxyHost:设置HTTP访问所使用的代理服务器的主机地址。该属性名的前缀可以改为https、ftp等,分别用于设置HTTPS访问和FTP访问所用的代理服务器的主机地址。(2)http.proxyPort:设置HTTP访问所使用的代理服务器的端口。该属性名的前缀可以改为https、ftp等,分别用于设置HTTPS访问和FTP访问所用的代理服务器的端口。
(3)http.nonProxyHosts:设置HTTP访问中不需要使用代理服务器的主机,支持使用*通配符;支持指定多个地址,多个地址之间用竖线( | )分隔。

《疯狂java讲义》第17章 网络编程相关推荐

  1. 疯狂java讲义第17章网络编程课后习题答案

    课后习题p845 练习书上的例子并且说出他们的用意 补充习题 1.说出nio的非阻塞式网络通信和aio的异步网络通信的含义和区别联系. 2.URL和Socket的区别和使用场景是什么?tcp和udp的 ...

  2. 疯狂java讲义第五章课后习题答案

    1.编写一个学生类,提供name.age.gender.phone.address.cmail成员变量,且为每个成员变量提供 seter.geter方法.为学生类提供默认的构造器和带所有成员变量的构造 ...

  3. 疯狂java讲义第四章习题答案

    1.使用循环输出九九乘法表. 疯狂java讲义第四章课后习题第1题答案 2.根据给定的层数,使用循环输出等腰三角形. 疯狂java讲义第四章课后习题第2题答案 3.给定半径输出圆形. 需要注意的是,计 ...

  4. Java 第十二章.网络编程

    网络编程 1.概述 2.网络通信要素概述 3.通信要素1:IP和端口号 3.1IP 3.2端口号 4.通信要素2:网络协议 5.TCP网络编程 6.UDP网络编程 7.URL编程 1.概述 Java是 ...

  5. 疯狂java讲义第七章补充习题第12题答案

    12.使用Calendar的各种方法 变量 ALL_STYLES AM AM_PM APRIL areFieldsSet AUGUST DECEMBER DST_OFFSET ERA FEBRUARY ...

  6. 疯狂java讲义第16章多线程课后习题答案

    课后习题p779 1. 2. 练习书上例子并说明它的用意 补充习题 1.尝试使用Android Studio的单步调试功能. 2.说出线程池和连接池的区别和联系 3.使用继承Thread的方法创建两个 ...

  7. 疯狂java的第四章答案_疯狂java讲义第四章第一题

    package chapter04; /**** * 本帖最后由 kongyeeku 于 2012-3-11 23:02 编辑 看到有一些读者询问关于该题的解题思路,其实这个题是有一些很绕的地方. 大 ...

  8. java疯狂讲义第四版第五章答案_疯狂java讲义第五章笔记

    1 定义类,成员变量和方法 类和对象 定义类 java的类名由一个或者多个有意义的单词组合而成,每个单词的首字母大写,其他的全部消协,并且单词之间没有分隔符. 成员变量:用于定义该类或者实例的所包含的 ...

  9. 疯狂java讲义第六章课后第4题答案

    4.定义一个类,该类用于封装一桌梭哈游戏,这个类应该包含桌上剩下的牌的信息,并包含5个玩家的状态信息:他们各自的位置.游戏状态(正在游戏或已放弃).手上已有的牌等信息.如果有可能,这个类还应该实现发牌 ...

  10. 【疯狂Java讲义】第二章 理解面向对象

最新文章

  1. 运行python程序ModuleNotFoundError?pip下载速度太慢?
  2. 不能用了 重装系统git_重装新版gitlab时遇到gitlab-rails database初始化失败
  3. Unity -- 入门教程三
  4. 关于HOG特征的一个Python代码
  5. 垃圾,还用汇编写单片机程序?
  6. python json dumps utf8_Python2操作JSON出现乱码的解决方案
  7. java编译多个包_javac一次性编译多个包下的.java文件
  8. spark更改分区_用于小文件的spark重新分区数据
  9. 大数据---单词释义
  10. 大数据学习笔记07:分布式文件系统HDFS
  11. java partialfunction,scala中方法和函数的区别
  12. html财务统计,财务统计.html · 举子/layuiadmin-templete - Gitee.com
  13. 计算机科学与技术专业实训手册,计算机科学与技术专业实习计划
  14. Spring Security视频地址
  15. 倒数第N个字符串 (15 分)
  16. 在lua的string库和正则表达式
  17. struct termios结构体详解
  18. Python基础知识从hello world 开始(第四天完结)
  19. 揭秘世界五大著名黑客
  20. 设为首页和收藏的JS

热门文章

  1. 数字化智慧园区建设方案
  2. rgb图像转换为二进制bin文件格式(matlab)
  3. 计算机硬故障指什么原因是,计算机常见硬故障的诊断及排除(7页)-原创力文档...
  4. 显卡煲机测试软件,铁三角耳机煲机方法三分钟让您学会煲耳机
  5. 如何使用Protel99 se给PCB文件添加汉字和图形?
  6. 计算机英语词汇电子书,计算机英语词汇-打印版.pdf
  7. 运算放大电路设计实验
  8. 实车开放道路真体验,开启车联网发展新征程
  9. 全国交通智慧升级,阿里云视频上云打造高速公路“视觉中枢”
  10. 最新出炉的Java面试题(2022亲身经历)