Java中的网络编程、反射

# 十九、Future
​        在执行多个任务的时候,使用Java标准库提供的线程池是非常方便的。我们提交的任务只需要实现`Runnable`接口,就可以让线程池去执行
    `Runnable`接口有个问题,它的方法没有返回值。如果任务需要一个返回结果,那么只能保存到变量,还要提供额外的方法读取,非常不便。所以,Java标准库还提供了一个`Callable`接口,和`Runnable`接口比,它多了一个返回值
# 二十、CompletableFuture
​        使用`Future`获得异步执行结果时,要么调用阻塞方法`get()`,要么轮询看`isDone()`是否为`true`,这两种方法都不是很好,因为主线程也会被迫等待。
​        从Java 8开始引入了`CompletableFuture`,它针对`Future`做了改进,可以传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法。
`CompletableFuture`的优点是:
​                1、异步任务结束时,会自动回调某个对象的方法;
​                2、异步任务出错时,会自动回调某个对象的方法;
​                3、主线程设置好回调后,不再关心异步任务的执行。
# Socket
# 一、Java 网络编程
​        网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来。
​        java.net 包中 J2SE 的 API 包含有类和接口,它们提供低层次的通信细节。你可以直接使用这些类和接口,来专注于解决问题,而不用关注通信细节
- **TCP**:TCP(英语:Transmission Control Protocol,传输控制协议) 是一种面向连接的、可靠的、基于字节流的传输层通信协议,TCP 层是位于 IP 层之上,应用层之下的中间层。TCP 保障了两个应用程序之间的可靠通信。通常用于互联网协议,被称 TCP / IP。
- **UDP**:UDP (英语:User Datagram Protocol,用户数据报协议),位于 OSI 模型的传输层。一个无连接的协议。提供了应用程序之间要发送数据的数据报。由于UDP缺乏可靠性且属于无连接协议,所以应用程序通常必须容许一些丢失、错误或重复的数据包。
## 1、Socket 编程
​        套接字使用TCP提供了两台计算机之间的通信机制。 客户端程序创建一个套接字,并尝试连接服务器的套接字。当连接建立时,服务器会创建一个 Socket 对象。客户端和服务器现在可以通过对 Socket 对象的写入和读取来进行通信。java.net.Socket 类代表一个套接字,并且 java.net.ServerSocket 类为服务器程序提供了一种来监听客户端,并与他们建立连接的机制
## 2、Socket整体流程
​        Socket编程主要涉及到客户端和服务端两个方面,首先是在服务器端创建一个服务器套接字(ServerSocket),并把它附加到一个端口上,服务器从这个端口监听连接。端口号的范围是0到65536,但是0到1024是为特权服务保留的端口号,我们可以选择任意一个当前没有被其他进程使用的端口。
## 2、ServerSocket 类的方法
​        服务器应用程序通过使用 java.net.ServerSocket 类以获取一个端口,并且侦听客户端请求。ServerSocket 类有四个构造方法:
| 方法                                                         | **方法描述**                                                 |
| ------------------------------------------------------------ | ------------------------------------------------------------ |
| **public ServerSocket(int port) throws IOException**         | 创建绑定到特定端口的服务器套接字。                           |
| **public ServerSocket(int port, int backlog) throws IOException** | 利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。 |
| **public ServerSocket(int port, int backlog, InetAddress address) throws IOException** | 使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。 |
| **public ServerSocket() throws IOException**                 | 创建非绑定服务器套接字。                                     |

## 3、Socket 类的方法
​        java.net.Socket 类代表客户端和服务器都用来互相沟通的套接字。客户端要获取一个 Socket 对象通过实例化 ,而 服务器获得一个 Socket 对象则通过 accept() 方法的返回值。
## 4、InetAddress 类的方法
​        这个类表示互联网协议(IP)地址。下面列出了 Socket 编程时比较有用的方法:
| 方法                                                         | **方法描述**                                        |
| ------------------------------------------------------------ | --------------------------------------------------- |
| **static InetAddress getByAddress(byte[] addr)**             | 在给定原始 IP 地址的情况下,返回 InetAddress 对象。 |
| **static InetAddress getByAddress(String host, byte[] addr)** | 根据提供的主机名和 IP 地址创建 InetAddress。        |
| **static InetAddress getByName(String host)**                | 在给定主机名的情况下确定主机的 IP 地址。            |
| **String getHostAddress()**                                  | 返回 IP 地址字符串(以文本表现形式)。              |
| **String getHostName()**                                     | 获取此 IP 地址的主机名。                            |
| **static InetAddress getLocalHost()**                        | 返回本地主机。                                      |
| **String toString()**                                        | 将此 IP 地址转换为 String。                         |

# 反射
# 一、反射概念
​        Java 反射机制是 Java 语言的一个重要特性。在学习 Java 反射机制前,先了解两个概念,**编译期**和**运行期**。
​    **编译期**是指把源码交给编译器编译成计算机可以执行的文件的过程。在 Java 中也就是把 Java 代码编成 class 文件的过程。编译期只是做了一些翻译功能,并没有把代码放在内存中运行起来,而只是把代码当成文本进行操作,比如检查错误。
​        **运行期**是把编译后的文件交给计算机执行,直到程序运行结束。所谓运行期就把在磁盘中的代码放到内存中执行起来。
​        Java 反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为 Java 语言的反射机制。简单来说,反射机制指的是程序在运行时能够获取自身的信息。在 Java 中,只要给定类的名字,就可以通过反射机制来获得类的所有信息
​    Java 反射机制主要提供了以下功能,这些功能都位于java.lang.reflect包。
​                1、在运行时判断任意一个对象所属的类。
​                2、在运行时构造任意一个类的对象。
​                3、在运行时判断任意一个类所具有的成员变量和方法。
​                4、在运行时调用任意一个对象的方法。
​                5、生成动态代理。
​        要想知道一个类的属性和方法,必须先获取到该类的字节码文件对象。获取类的信息时,使用的就是 Class 类中的方法。所以先要获取到每一个字节码文件(.class)对应的 Class 类型的对象.
**Java 反射机制的优缺点**

**优点:**
        能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。
        与 Java 动态编译相结合,可以实现无比强大的功能。
        对于 Java 这种先编译再运行的语言,能够让我们很方便的创建灵活的代码,这些代码可以在运行时装配,无需在组件之间进行源代码的链接,更加容易实现面向对象。

**缺点:**
​        反射会消耗一定的系统资源,因此,如果不需要动态地创建一个对象,那么就不需要用反射;
​        反射调用方法时可以忽略权限检查,获取这个类的私有方法和属性,因此可能会破坏类的封装性而导致安全问题。
Java 反射机制在一般的 Java 应用开发中很少使用,即便是 Java EE 阶段也很少使用。
​    
# 二、反射机制API
    实现 Java 反射机制的类都位于 java.lang.reflect 包中,java.lang.Class 类是 Java 反射机制 API 中的核心类。
## 1、java.lang.Class 类
​        java.lang.Class 类是实现反射的关键所在,Class 类的一个实例表示 Java 的一种数据类型,包括类、接口、枚举、注解(Annotation)、数组、基本数据类型和 void。Class 没有公有的构造方法,Class 实例是由 JVM 在类加载时自动创建的
## 2、java.lang.reflect 包
java.lang.reflect 包提供了反射中用到类,主要的类说明如下:
- Constructor 类:提供类的构造方法信息。
- Field 类:提供类或接口中成员变量信息。
- Method 类:提供类或接口成员方法信息。
- Array 类:提供了动态创建和访问 Java 数组的方法。
- Modifier 类:提供类和成员访问修饰符信息

# 三、通过反射访问构造方法
​        为了能够**动态获取对象构造方法**的信息,首先需要通过下列方法之一创建一个 Constructor 类型的对象或者数组。
​                getConstructors()
​                getConstructor(Class<?>…parameterTypes)
​                getDeclaredConstructors()
​                getDeclaredConstructor(Class<?>...parameterTypes)
# 四、通过反射执行方法
​        要**动态获取**一个对象方法的信息,首先需要通过下列方法之一创建一个 Method 类型的对象或者数组。
​                getMethods()
​                getMethods(String name,Class<?> …parameterTypes)
​                getDeclaredMethods()
​                getDeclaredMethods(String name,Class<?>...parameterTypes)
​        如果是访问指定的构造方法,需要根据该方法的入口参数的类型来访问。例如,访问一个名称为 max,入口参数类型依次为 int 和 String 类型的方法。

# 五、通过反射访问成员变量

​        通过下列任意一个方法访问成员变量时将返回 Field 类型的对象或数组。
​                getFields()
​                getField(String name)
​                getDeclaredFields()
​                getDeclaredField(String name)
​        上述方法返回的 Field 对象代表一个成员变量。例如,要访问一个名称为 price 的成员变量,示例代码如下:
```java
object.getDeciaredField("price");

# 六、获取继承关系

​        当我们获取到某个`Class`对象时,实际上就获取到了一个类的类型:

```java
Class cls = String.class; // 获取到String的Class
```

​        还可以用实例的`getClass()`方法获取:

```java
String s = "";
Class cls = s.getClass(); // s是String,因此获取到String的Class
```

​        最后一种获取`Class`的方法是通过`Class.forName("")`,传入`Class`的完整类名获取:
```java
Class s = Class.forName("java.lang.String");
​        这三种方式获取的`Class`实例都是同一个实例,因为JVM对每个加载的`Class`只创建一个`Class`实例来表示它的类型。

## 4、小结
通过`Class`对象可以获取继承关系:
- `Class getSuperclass()`:获取父类类型;
- `Class[] getInterfaces()`:获取当前类实现的所有接口。
通过`Class`对象的`isAssignableFrom()`方法可以判断一个向上转型是否可以实现。

# 七、动态代理
我们来比较Java的`class`和`interface`的区别:
- 可以实例化`class`(非`abstract`);
- 不能实例化`interface`。

**小结**
​        Java标准库提供了动态代理功能,允许在运行期动态创建一个接口的实例;
​        动态代理是通过`Proxy`创建代理对象,然后将接口方法“代理”给`InvocationHandler`完成的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值