黑马程序员--Java基础--网络通信

——Java培训、Android培训、iOS培训、.Net培训 期待与您共同交流!——



文章大纲:

1.网络基础

2.TCP通信

3.UDP通信


1. 网络基础

1.1. 网络协议

1.1.1. 网络协议分层

OSI(开放系统互联(Open System Interconnection))模型是国际标准化组织ISO创立的。这是一个理论模型,并无实际产品完全符合OSI模型。制订OSI模型只是为了分析网络通讯方便而引进的一套理论。也为以后制订实用协议或产品打下基础。

OSI模型共分七层:从上至下依次是

图- 1

应用层:指网络操作系统和具体的应用程序,对应WWW服务器、FTP服务器等应用软件

表示层:数据语法的转换、数据的传送等

会话层: 建立起两端之间的会话关系,并负责数据的传送

传输层:负责错误的检查与修复,以确保传送的质量,是TCP工作的地方。

网络层:提供了编址方案,IP协议工作的地方(数据包)

数据链路层:将由物理层传来的未经处理的位数据包装成数据帧

物理层:对应网线、网卡、接口等物理设备(位)

1.1.2. TCP/IP协议栈
  • Transmission Control Protocol/Internet Protocol的简写,中译名为传输控制协议/因特网互联协议,又名网络通讯协议.
  • 由网络层的IP协议和传输层的TCP协议组成。TCP/IP 定义了电子设备如何连入因特网,以及数据如何在它们之间传输的标准。协议采用了4层的层级结构,每一层都呼叫它的下一层所提供的协议来完成自己的需求。通俗而言:TCP负责发现传输的问题,一有问题就发出信号,要求重新传输,直到所有数据安全正确地传输到目的地。而IP是给因特网的每一台电脑规定一个地址。
  • TCP/IP协议栈(按TCP/IP参考模型划分),TCP/IP分为4层,不同于OSI,他将OSI中的会话层、表示层规划到应用层:应用层,传输层,IP网络层,网络接口层

1.2. IP层协议

1.2.1. IP协议简介
  • IP是英文Internet Protocol(网络之间互连的协议)的缩写,也就是为计算机网络相互连接进行通信而设计的协议。

在因特网中,它是能使连接到网上的所有计算机网络实现相互通信的一套规则,规定了计算机在因特网上进行通信时应当遵守的规则。任何厂家生产的计算机系统,只要遵守 IP协议就可以与因特网互连互通。

1.2.2. 路由器简介
  • 路由器(Router)又称网关设备(Gateway)是用于连接多个逻辑上分开的网络,所谓逻辑网络是代表一个单独的网络或者一个子网。当数据从一个子网传输到另一个子网时,可通过路由器的路由功能来完成。因此,路由器具有判断网络地址和选择IP路径的功能,它能在多网络互连环境中,建立灵活的连接,路由器只接受源站或其他路由器的信息,属网络层的一种互联设备。
1.2.3. IP地址及其含义

互联网协议地址(Internet Protocol Address,又译为网际协议地址),缩写为IP地址(IP Address)。IP地址是IP协议提供的一种统一的地址格式,它为互联网上的每一个网络和每一台主机分配一个逻辑地址,以此来屏蔽物理地址的差异

IP地址是一个32位的二进制数,通常被分割为4个“8位二进制数”(也就是4个字节)。IP地址通常用“点分十进制”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~255之间的十进制整数。例:点分十进IP地址(100.4.5.6),实际上是32位二进制数(01100100.00000100.00000101.00000110)。

1.3. 传输层协议

1.3.1. TCP协议简介

TCP (Transmission Control Protocol)和UDP(User Datagram Protocol)协议属于传输层协议。其中TCP提供IP环境下的数据可靠传输,它提供的服务包括数据流传送、可靠性、有效流控、全双工操作和多路复用。通过面向连接、端到端和可靠的数据包发送。

“面向连接”就是在正式通信前必须要与对方建立起连接。比如你给别人打电话,必须等线路接通了、对方拿起话筒才能相互通话。

1.3.2. UDP协议简介

UDP 是User Datagram Protocol的简称, 中文名是用户数据报协议,是OSI参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务。是与TCP相对应的协议。它是面向非连接的协议,它不与对方建立连接,而是直接就把数据包发送过去!

1.3.3. 端口号的概念
  • 一般是指TCP/IP协议中的端口,端口号的范围从0到65535,比如用于浏览网页服务的80端口,用于FTP服务的21端口等等。
  • 一台拥有IP地址的主机可以提供许多服务,比如Web服务、FTP服务、SMTP服务等,这些服务通过1个IP地址来实现。通过“IP地址+端口号”来区 分不同的服务的。
  • 不同的协议间端口不冲突。比如我们可以同时使用UDP打开8088端口的与TCP的8088端口。
1.3.4. TCP协议与UDP协议的区别
  • TCP协议需要创建连接,而UDP协议则不需要。
  • TCP是可靠的传输协议,而UDP是不可靠的。
  • TCP适合传输大量的数据,而UDP适合传输少量数据。
  • TCP的速度慢,而UDP的速度快。

1.4. 应用层协议

1.4.1. HTTP协议简介

HTTP协议(HyperText Transfer Protocol,超文本转移协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更加高效,使网络传输减少。它不仅保证计算机正确快速地传输超文本文档,还确定传输文档中的哪一部分,以及哪部分内容首先显示(如文本先于图形)等。

  • HTTP是一个应用层协议,由请求和响应构成,是一个标准的客户端服务器模型。 HTTP是一个无状态的协议。
1.4.2. FTP协议简介

FTP 是 TCP/IP 协议组中的协议之一,是英文File Transfer Protocol的缩写。该协议是Internet文件传送的基础,它由一系列规格说明文档组成,目标是提高文件的共享性,提供非直接使用远程计算机,使存储介质对用户透明和可靠高效地传送数据。

1.4.3. SMTP协议简介

SMTP(Simple Mail Transfer Protocol)即简单邮件传输协议,是一种提供可靠且有效电子邮件传输的协议。SMTP是建立在FTP文件传输服务上的一种邮件服务,主要用于传输系统之间的邮件信息并提供与来信有关的通知。

2. TCP通信

2.1. Socket原理

2.1.1. Socket简介

socket通常称作“套接字”,用于描述IP地址和端口,是一个通信链的句柄。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。

应用程序通常通过“套接字”向网络发出请求或者应答网络请求。Socket和ServerSocket类库位于java .net包中。ServerSocket用于服务端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。

2.1.2. 获取本地地址和端口号

java.net.Socket为套接字类,其提供了很多方法,其中我们可以通过Socket获取本地的地址以及端口号。

int getLocalPort()

该方法用于获取本地使用的端口号

InetAddress getLocalAddress()

该方法用于获取套接字绑定的本地地址

使用InetAddress获取本地的地址方法:

StringgetCanonicalHostName()

获取此 IP 地址的完全限定域名。

StringgetHostAddress()

返回 IP 地址字符串(以文本表现形式)。

代码如下:

public void testSocket()throws Exception {
            Socket socket =newSocket("localhost",8088);
            InetAddress add = socket.getLocalAddress();//获取本地地址信息
            System.out.println(add.getCanonicalHostName());
            System.out.println(add.getHostAddress());
            System.out.println(socket.getLocalPort());
}
2.1.3. 获取远端地址和端口号

Socket也提供了获取远端的地址以及端口号的方法:

int getPort()

该方法用于获取远端使用的端口号 。

InetAddress .getInetAddress()

该方法用于获取套接字绑定的远端地址 。

代码如下:

public void testSocket()throws Exception {
            Socket socket =newSocket("localhost",8088);
             InetAddress inetAdd = socket.getInetAddress();
            System.out.println(inetAdd.getCanonicalHostName());
            System.out.println(inetAdd.getHostAddress());
            System.out.println(socket.getPort());
}
2.1.4. 获取网络输入流和网络输出流

通过Socket获取输入流与输出流,这两个方法是使用Socket通讯的关键方法。封装了TCP协议的Socket是基于流进行通讯的,所以我们在创建了双方连接后,只需要获取相应的输入与输出流即可实现通讯。

InputStream getInputStream()

该方法用于返回此套接字的输入流。

OutputStream .getOutputStream()

该方法用于返回此套接字的输出流。

代码如下:

public void testSocket()throws Exception {

Socket socket =newSocket(“localhost”,8088);

InputStream in= socket.getInputStream();

OutputStream out = socket.getOutputStream();

}

2.1.5. close方法

当使用Socket进行通讯完毕后,要关闭Socket以释放系统资源。

void close()

当关闭了该套接字后也会同时关闭由此获取的输入流与输出流。

2.2. Socket通讯模型

2.2.1. Server端ServerSocket监听

java.net.ServerSocket是运行于服务端应用程序中。通常创建ServerSocket需要指定服务端口号,之后监听Socket的连接。监听方法为:

Socket accept()

该方法是一个阻塞方法,直到一个客户端通过Socket连接后,accept会封装一个Socket,该Socket封装与表示该客户端的有关的信息。通过这个Socket与该客户端进行通信。

代码如下:

…
//创建ServerSocket并申请服务端口8088
ServerSocket server =newServerSocket(8088);
/*方法会产生阻塞,直到某个Socket连接,并返回请求连接的Socket*/
Socket socket = server.accept();
…
2.2.2. Client端Socket连接

通过上一节我们已经知道,当服务端ServerSocket调用accept方法阻塞等待客户端连接后,我们可以通过在客户端应用程序中创建Socket来向服务端发起连接。

  • 需要注意的是,创建Socket的同时就发起连接,若连接异常会抛出异常。 我们通常创建Socket时会传入服务端的地址以及端口号。

    代码如下:

    //参数1:服务端的IP地址,参数2:服务端的服务端口
    Socket socket =newSocket(“localhost”,8088);
    …
2.2.3. C-S端通信模型

C-S的全称为(Client-Server):客户端-服务器端

客户端与服务端通信模型如下:

图- 2

服务端创建ServerSocket

通过调用ServerSocket的accept方法监听客户端的连接

客户端创建Socket并指定服务端的地址以及端口来建立与服务端的连接

当服务端accept发现客户端连接后,获取对应该客户端的Socket

双方通过Socket分别获取对应的输入与输出流进行数据通讯

通讯结束后关闭连接。

代码如下:


/**
     *    Server端应用程序
     */
publicclass Server {
publicstatic void main(String[] args){
        ServerSocket server =null;
try{
//创建ServerSocket并申请服务端口为8088
            server =newServerSocket(8088);
//侦听客户端的连接
            Socket socket = server.accept();
//客户端连接后,通过该Socket与客户端交互
//获取输入流,用于读取客户端发送过来的消息
            InputStream in= socket.getInputStream();
            BufferedReader reader
=newBufferedReader(
newInputStreamReader(
in,"UTF-8"
)
);
//获取输出流,用于向该客户端发送消息
            OutputStream out = socket.getOutputStream();
            PrintWriter writer
=newPrintWriter(
newOutputStreamWriter(
                        out,"UTF-8"
),true
);
//读取客户端发送的消息
String message = reader.readLine();
            System.out.println("客户端说:"+message);
//向客户端发送消息
            writer.println("你好客户端!");
}catch(Exception e){
            e.printStackTrace();
}finally{
if(server !=null){
try{
                    server.close();
}catch(IOException e){
}
}
}
}
}
/**
 * Client端应用程序
 */
publicclass Client {
publicstatic void main(String[] args){
        Socket socket =null;
try{
            socket  =newSocket("localhost",8088);
//获取输入流,用于读取来自服务端的消息
            InputStream in= socket.getInputStream();
            BufferedReader reader
=newBufferedReader(
newInputStreamReader(
in,"UTF-8"
)
);
//获取输出流,用于向服务端发送消息
            OutputStream out
= socket.getOutputStream();
            OutputStreamWriter osw
=newOutputStreamWriter(out,"UTF-8");
            PrintWriter writer
=newPrintWriter(osw,true);
//向服务端发送一个字符串
            writer.println("你好服务器!");
//读取来自客户端发送的消息
String message = reader.readLine();
            System.out.println("服务器说:"+message);
}catch(Exception e){
            e.printStackTrace();
}finally{
try{
if(socket !=null){
//关闭Socket
                    socket.close();
}
}catch(IOException e){
                e.printStackTrace();
}
}
}
}
2.2.4. Server端多线程模型

通过上一节我们已经知道了如何使用ServerSocket与Socket进行通讯了,但是这里存在着一个问题,就是只能“p2p”点对点。一个服务端对一个客户端。若我们想让一个服务端可以同时支持多个客户端应该怎么做呢?这时我们需要分析之前的代码。我们可以看到,当服务端的ServerSocket通过accept方法侦听到一个客户端Socket连接后,就获取该Socket并与该客户端通过流进行双方的通讯了,这里的问题在于,只有不断的调用accept方法,我们才能侦听到不同客户端的连接。但是若我们循环侦听客户端的连接,又无暇顾及与连接上的客户端交互,这时我们需要做的事情就是并发。我们可以创建一个线程类ClientHandler,并将于客户端交互的工作全部委托线程来处理。这样我们就可以在当一个客户端连接后,启动一个线程来负责与客户端交互,而我们也可以循环侦听客户端的连接了。

我们需要对服务端的代码进行修改:

/**
 *  Server端应用程序*
 */
publicclass Server {
publicstatic void main(String[] args){
        ServerSocket server =null;
try{
//创建ServerSocket并申请服务端口为8088
            server =newServerSocket(8088);
while(true){
//循环侦听客户端的连接
                Socket socket = server.accept();
//当一个客户端连接后,启动线程来处理该客户端的交互
newClientHandler(socket).start();
}
}catch(Exception e){
            e.printStackTrace();
}finally{
if(server !=null){
try{
                    server.close();
}catch(IOException e){
}
}
}
}
}
/**
 * 线程类
 * 该线程的作用是并发与客户端进行交互
 * 这里的代码就是原来在Server中客户端连接后交互的代码
 */
class ClientHandler extends Thread{
private Socket socket;
publicClientHandler(Socket socket){
this.socket = socket;
}
public void run(){
try{
//获取输入流,用于读取客户端发送过来的消息
            InputStream in= socket.getInputStream();
            BufferedReader reader
=newBufferedReader(
newInputStreamReader(
in,"UTF-8"
)
);
//获取输出流,用于向该客户端发送消息
            OutputStream out = socket.getOutputStream();
            PrintWriter writer
=newPrintWriter(
newOutputStreamWriter(
                        out,"UTF-8"
),true
);
//读取客户端发送的消息
String message = reader.readLine();
            System.out.println("客户端说:"+message);
//向客户端发送消息
            writer.println("你好客户端!");
}catch(Exception e){
            e.printStackTrace();
}
}
}

经过上面的改动,我们再次启动服务端,这个时候我们会发现,我们启动若干客户端都可以被服务器所接受并进行交互了。

3. UDP通信

3.1. DatagramPacket

3.1.1. 创建接收包

DatagramPacket:UDP数据报基于IP建立的,每台主机有65536个端口号可以使用。数据报中字节数限制为65536-8 。包含8字节的头信息。

构造接收包:

DatagramPacket(byte[] buf, int length)

将数据包中Length长的数据装进Buf数组。

DatagramPacket(byte[] buf, int offset, int length)

将数据包中从Offset开始、Length长的数据装进Buf数组。

3.1.2. 创建发送包

构造发送包:

DatagramPacket(byte[] buf, int length, InetAddress clientAddress, int clientPort)

从Buf数组中,取出Length长的数据创建数据包对象,目标是clientAddress地址,clientPort端口,通常用来发送数据给客户端。

DatagramPacket(byte[] buf, int offset, int length, InetAddress clientAddress, int clientPort)

从Buf数组中,取出Offset开始的、Length长的数据创建数据包对象,目标是clientAddress地址,clientPort端口,通常用来发送数据给客户端。

3.2. DatagramSocket

3.2.1. 服务端接收

DatagramSocke用于接收和发送UDP的Socket实例 。

DatagramSocket(int port)

创建实例,并固定监听Port端口的报文。通常用于服务端。

其中方法:

receive(DatagramPacket d)

接收数据报文到d中。receive方法产生 “阻塞”。会一直等待知道有数据被读取到。

3.2.2. 客户端发送

无参的构造方法DatagramSocket()通常用于客户端编程,它并没有特定监听的端口,仅仅使用一个临时的。程序会让操作系统分配一个可用的端口。

其中方法:

send(DatagramPacket dp)

该方法用于发送报文dp到目的地。

代码如下:

/**
     *  Server端程序
     */
publicclass Server {
publicstatic void main(String[] args){
        DatagramSocket socket =null;
try{
            socket =newDatagramSocket(8088);//申请8088端口
            byte[] data =new byte[1024];
            DatagramPacket packet
=newDatagramPacket(data, data.length);//创建接收包
            socket.receive(packet);//会产生阻塞,读取发送过来的数据
String str =newString(packet.getData(),0,packet.getLength());//从包中取数据
            System.out.println(str);
}catch(Exception e){
            e.printStackTrace();
}finally{
if(socket !=null){
                socket.close();//关闭释放资源
}
}
}
}
/**
 *  Client端程序
 */
publicclass Client {
publicstatic void main(String[] args){
        DatagramSocket socket =null;
try{
            socket =newDatagramSocket();//创建Socket
            byte[] data ="你好服务器!".getBytes();
            DatagramPacket packet =newDatagramPacket(
                                        data,
                                        data.length,
                                        InetAddress.getByName("localhost"),
8088
);//创建发送包
            socket.send(packet);//发送数据
}catch(Exception e){
            e.printStackTrace();
}finally{
if(socket !=null){
                socket.close();//关闭以释放资源
}
}
}
}

3.3. UDP穿透

3.3.1. UDP穿透原理

在讲解UDP穿透之前,我们先来介绍一些相关的知识。  

NAT(Network Address Translators),网络地址转换:网络地址转换是在IP地址日益缺乏的情况下产生的,它的主要目的就是为了能够使IP地址重用。NAT分为两大类,基本的NAT和NAPT(Network Address/Port Translator)。 最开始NAT是运行在路由器上的一个功能模块。   基本的NAT实现的功能很简单,在子网内使用一个保留的IP子网段,这些IP对外是不可见的。如果这些节点需要访问外部网络,那么基本NAT就负责将这个节点的子网内IP转化为一个全球唯一的IP然后发送出去。(基本的NAT会改变IP包中的原IP地址,但是不会改变IP包中的端口)

假设一台在NAT211.133.111.022后的192.168.1.77:8000要向NAT211.134.222.123后的192.168.1.88:9000发送数据,假设你向211.134.222.123这个IP地址的9000端口直接发送数据包,则数据包在到达NAT211.134.222.123之后,会被当做无效非法的数据包被丢弃,NAT在此时相当于一个防火墙,会对没有建立起有效SESSION的数据包进行拒绝转递。当然,你也不能直接用内网地址192.168.1.88进行发送数据包,因为这样是找自己内网的其他机器。 凡是经过NAT发出去的数据包,都会通过一定的端口转换(而非使用原端口)再发出去,也就是说内网和外网之间的通信不是直接由内网机器与外网NAT进行,而是利用内网对外网的NAT建立起SESSION与外网NAT的SESSION进行。 根据SESSION的不同,NAT主要分成两种:SymmetricNAPT以及CONE NAPT。简单的说,Symmetric NAPT是属于动态端口映射的NAT,而CONE NAPT是属于静态端口映射的NAT。而市场上目前大多属于后者,CONE的英文意思锥,意思就是一个端口可以对外部多台NAT设备通信。这个也正是我们做点对点穿透的基本,是我们所希望的,否则现在的大部分点对点软件将无法正常使用。

像上面的例子,NAT211.133.111.022和NAT211.134.222.123之间需要进行通信,但开始不能直接就发数据包,我们需要一个中间人,这个就是外部索引服务器(我们假设是211.135.134.178:7000),当NAT211.133.111.022向211.135.134.178:7000发送数据包,211.135.134.178:7000是可以正常接收到数据,因为它是属于对外型开放的服务端口。当211.135.134.178:7000收到数据包后可以获知NAT211.133.111.022对外通信的临时SESSION信息(这个临时的端口,假设是6000会过期,具体的时间不同,索引服务器此时应将此信息保存起来。而同时,NAT211.134.222.123也在时刻向索引服务器发送心跳包,索引服务器就向NAT211.134.222.123发送一个通知,让它向NAT211.133.111.022:6000发送探测包(这个数据包最好多发几个),NAT211.133.111.022在收到通知包之后再向索引服务器发送反馈包,说明自己已经向NAT211.133.111.022:6000发送了探测包,索引服务器在接收到反馈包之后再向NAT211.133.111.022转发反馈包,NAT211.133.111.022在接收到数据包之后再向原本要请求的NAT211.134.222.123发送数据包,此时连接已经打通,实现穿透,NAT211.134.222.123会将信息转发给192.168.1.88的9000端口。

3.3.2. UDP穿透参考实例

以上一节的案例说明具体过程:

我们要从一个内网中的机器A连接另一个内网机器B。

假设:

A的内网IP和端口为: 192.168.1.77:8000

B的内网IP和端口为: 192.168.1.88:9000

A所连接的路由器NA的公网IP为: 211.133.111.022

B所连接的路由器NB的公网IP为: 211.134.222.123

需要借助的服务器C的公网IP和端口为: 211.135.134.178:7000

那么我们实现穿透需要做以下操作:

1:首先A请求服务器C,这时A的路由器会做端口映射,记录来自服务器的消息是允许进入并转发给内网A的。

图- 3

2:同样的,B也连接服务器C

图- 4

3:若A想与B连接,需要先让服务器C将B的地址发送给A,使得A主动向B发送消息。如此一来,A的路由器NA会记录来自B所在的公网IP的消息允许进入。但是,实际上这次A向B所在的路由器NB发送的消息会被NB当做无效信息而被屏蔽,不过没有关系。我们的目的是告诉NA来自NB的消息是允许进入的。

图- 5

4:之后A请求服务器C,使服务器C通知B向A所在的路由器NA发送消息以连接A。

图- 6

图- 7

6:同时在步骤5发送消息后,NB也允许来自NA的消息了。从而实现了NA的内网机器A与NB的内网机器B的双向连通,可以互发信息了。实现了UDP穿透。

图- 8

文章到此结束,谢谢阅读,如有不足之处请愿与你共同商讨。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-20 23:16:27

黑马程序员--Java基础--网络通信的相关文章

黑马程序员——Java基础---IO(下)

黑马程序员——Java基础---IO(下) ------<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------ 一.概述 Java除了基本的字节流.字符流之外,还提供了File类.properties类.打印流.序列流等和输入输出相关的类,它们能够帮助我们更好的处理信息.下面将对它们进行简单的介绍. 一.正

黑马程序员——Java基础---集合框架工具类

黑马程序员——Java基础<a href="http://www.itheima.com" target="blank">Java培训.Android培训.iOS培训..Net培训</a>.期待与您交流! ------ 一.概述 Java为操作Set.List和Map提供了一系列工具类,主要有Collections和Arrays.这两个工具类的特点:类中的方法都是静态的,不需要创建对象,直接使用类名调用即可.Collections:是集合对象

黑马程序员——java基础——多线程

 黑马程序员--java基础--多线程 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 进程:是一个正在执行中的程序.每一个进程执行都有一个执行顺序.该顺序是一个执行路径,或者叫一个控制单元. 线程:就是进程中的一个独立的控制单元.线程在控制着进程的执行.一个进程中至少有一个线程. 一个进程至少有一个线程在运行,当一个进程中出现多个线程时,就称这个应用程序是多线程应用程序,每个线程在栈区中都有自己的执行空间,自己的方法区.自己的变量.

黑马程序员——java基础---IO(input output)流字符流

黑马程序员——java基础---IO(input output)流字符流 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- io(input output)流特点: 1,io流用来处理数据之间的传输 2,java对数据的操作是通过流的方式: 3,java用于操作流的对象都在io包中: 4,流按操作数据分为两种:字节流和字符流: 5,流按流向分为:输入流和输出流. 注意:流只能操作数据,而不能操作文件. 3.IO流的常用基类: 1)字节流的抽象

黑马程序员——java基础——反射

 黑马程序员--java基础--反射 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 反射 其实就是动态加载一个指定的类,并获取该类中的所有的内容.而且将字节码文件封装成对象,并将字节码文件中的内容都封装成对象,这样便于操作这些成员. 反射就是把Java类中的各种成分映射成相应的java类. 简单说:反射技术可以对一个类进行解剖. 反射的基石-->Class类 1.java中的类是用来描述一类事物的共性,该类事物有什么属性,没有什么属性

黑马程序员——java基础——内部类

 黑马程序员--java基础--内部类 ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 内部类 如果A类需要直接访问B类中的成员,而B类又需要建立A类的对象.这时,为了方便设计和访问,直接将A类定义在B类中.就可以了.A类就称为内部类.内部类可以直接访问外部类中的成员.而外部类想要访问内部类,必须要建立内部类的对象. 内部类的访问规则 1,内部类可以直接访问外部类中的成员,包括私有. 之所以可以直接访问外部类中的成员,是因为内部类中持有

黑马程序员——java基础——集合(Collection)

 黑马程序员--java基础--集合(Collection) ------Java培训.Android培训.iOS培训..Net培训.期待与您交流! ------- 集合框架的构成及分类,如下图: 1.为什么出现集合类? 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式. 2.数组和集合类同是容器,有何不同? 数组虽然也可以存储对象,但长度是固定的:集合长度是可变的.数组中可以存储基本数据类型,集合只能存储对象. 3.

黑马程序员——Java基础篇之对象归要

1.static关键字 1.1.static可以修饰成员变量,成员方法,还有类(其中这里的类是内部类) 1.2.static修饰的部分会随着类的加载而加载: 加载过程:当JVM执行static修饰的代码时,会在内存的共享区给static部分开辟一个空间,供该类持有,static部分不是某个对象的部分,而是该类共有的,所以当一个函数会被多个对象调用时,最好定义成static,这样比较节省空间. 1.3.静态方法只能访问静态成员 原因:如果静态方法中调用了非静态的变量,那么由于静态方法是随着类的加载

黑马程序员--Java基础--01基本概念

1.Java的三大技术架构 JAVAEE(Java Platform Enterprise Edition):  开发企业环境下的应用程序,主要针对web程序开发: JAVASE(Java Platform Standard Edition): 完成桌面应用程序的开发,是其他两者的基础 JAVAME(Java Platform Micro Edition): 开发电子消费产品和嵌入式设备,如手机中的程序 我对三大技术构架理解 1.三大技术是指哪三大技术呢? 答:三大技术分别指JAVAEE,JAV