java笔记

java笔记


网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来。

java.net 包中 J2SE 的 API 包含有类和接口,它们提供低层次的通信细节。你可以直接使用这些类和接口,来专注于解决问题,而不用关注通信细节。

java.net 包中提供了两种常见的网络协议的支持:

TCP:TCP(英语:Transmission Control Protocol,传输控制协议) 是一种面向连接的、可靠的、基于字节流的传输层通信协议,TCP 层是位于 IP 层之上,应用层之下的中间层。TCP 保障了两个应用程序之间的可靠通信。通常用于互联网协议,被称 TCP / IP。

UDP:UDP (英语:User Datagram Protocol,用户数据报协议),位于 OSI 模型的传输层。一个无连接的协议。提供了应用程序之间要发送数据的数据报。由于UDP缺乏可靠性且属于无连接协议,所以应用程序通常必须容许一些丢失、错误或重复的数据包

Socket 编程
套接字使用TCP提供了两台计算机之间的通信机制。 客户端程序创建一个套接字,并尝试连接服务器的套接字。

当连接建立时,服务器会创建一个 Socket 对象。客户端和服务器现在可以通过对 Socket 对象的写入和读取来进行通信。

java.net.Socket 类代表一个套接字,并且 java.net.ServerSocket 类为服务器程序提供了一种来监听客户端,并与他们建立连接的机制。

以下步骤在两台计算机之间使用套接字建立TCP连接时会出现:

服务器实例化一个 ServerSocket 对象,表示通过服务器上的端口通信。

服务器调用 ServerSocket 类的 accept() 方法,该方法将一直等待,直到客户端连接到服务器上给定的端口。

服务器正在等待时,一个客户端实例化一个 Socket 对象,指定服务器名称和端口号来请求连接。

Socket 类的构造函数试图将客户端连接到指定的服务器和端口号。如果通信被建立,则在客户端创建一个 Socket 对象能够与服务器进行通信。

在服务器端,accept() 方法返回服务器上一个新的 socket 引用,该 socket 连接到客户端的 socket。

连接建立后,通过使用 I/O 流在进行通信,每一个socket都有一个输出流和一个输入流,客户端的输出流连接到服务器端的输入流,而客户端的输入流连接到服务器端的输出流。

TCP 是一个双向的通信协议,因此数据可以通过两个数据流在同一时间发送.

ServerSocket 类的方法
服务器应用程序通过使用 java.net.ServerSocket 类以获取一个端口,并且侦听客户端请求。

ServerSocket 类有四个构造方法:

序号    方法描述
1    public ServerSocket(int port) throws IOException
创建绑定到特定端口的服务器套接字。
2    public ServerSocket(int port, int backlog) throws IOException
利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号。
3    public ServerSocket(int port, int backlog, InetAddress address) throws IOException
使用指定的端口、侦听 backlog 和要绑定到的本地 IP 地址创建服务器。
4    public ServerSocket() throws IOException
创建非绑定服务器套接字。
创建非绑定服务器套接字。 如果 ServerSocket 构造方法没有抛出异常,就意味着你的应用程序已经成功绑定到指定的端口,并且侦听客户端请求。

这里有一些 ServerSocket 类的常用方法:

序号    方法描述
1    public int getLocalPort()
  返回此套接字在其上侦听的端口。
2    public Socket accept() throws IOException
侦听并接受到此套接字的连接。
3    public void setSoTimeout(int timeout)
 通过指定超时值启用/禁用 SO_TIMEOUT,以毫秒为单位。
4    public void bind(SocketAddress host, int backlog)
将 ServerSocket 绑定到特定地址(IP 地址和端口号)。
Socket 类的方法
java.net.Socket 类代表客户端和服务器都用来互相沟通的套接字。客户端要获取一个 Socket 对象通过实例化 ,而 服务器获得一个 Socket 对象则通过 accept() 方法的返回值。

Socket 类有五个构造方法.

序号    方法描述
1    public Socket(String host, int port) throws UnknownHostException, IOException.
创建一个流套接字并将其连接到指定主机上的指定端口号。
2    public Socket(InetAddress host, int port) throws IOException
创建一个流套接字并将其连接到指定 IP 地址的指定端口号。
3    public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException.
创建一个套接字并将其连接到指定远程主机上的指定远程端口。
4    public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException.
创建一个套接字并将其连接到指定远程地址上的指定远程端口。
5    public Socket()
通过系统默认类型的 SocketImpl 创建未连接套接字
当 Socket 构造方法返回,并没有简单的实例化了一个 Socket 对象,它实际上会尝试连接到指定的服务器和端口。

下面列出了一些感兴趣的方法,注意客户端和服务器端都有一个 Socket 对象,所以无论客户端还是服务端都能够调用这些方法。

序号    方法描述
1    public void connect(SocketAddress host, int timeout) throws IOException
将此套接字连接到服务器,并指定一个超时值。
2    public InetAddress getInetAddress()
 返回套接字连接的地址。
3    public int getPort()
返回此套接字连接到的远程端口。
4    public int getLocalPort()
返回此套接字绑定到的本地端口。
5    public SocketAddress getRemoteSocketAddress()
返回此套接字连接的端点的地址,如果未连接则返回 null。
6    public InputStream getInputStream() throws IOException
返回此套接字的输入流。
7    public OutputStream getOutputStream() throws IOException
返回此套接字的输出流。
8    public void close() throws IOException
关闭此套接字。
InetAddress 类的方法
这个类表示互联网协议(IP)地址。下面列出了 Socket 编程时比较有用的方法:

序号    方法描述
1    static InetAddress getByAddress(byte[] addr)
在给定原始 IP 地址的情况下,返回 InetAddress 对象。
2    static InetAddress getByAddress(String host, byte[] addr)
根据提供的主机名和 IP 地址创建 InetAddress。
3    static InetAddress getByName(String host)
在给定主机名的情况下确定主机的 IP 地址。
4    String getHostAddress() 
返回 IP 地址字符串(以文本表现形式)。
5    String getHostName() 
 获取此 IP 地址的主机名。
6    static InetAddress getLocalHost()
返回本地主机。
7    String toString()
将此 IP 地址转换为 String。

GreetingClient.java 文件代码:
// 文件名 GreetingClient.java
 
import java.net.*;
import java.io.*;
 
public class GreetingClient
{
   public static void main(String [] args)
   {
      String serverName = args[0];
      int port = Integer.parseInt(args[1]);
      try
      {
         System.out.println("连接到主机:" + serverName + " ,端口号:" + port);
         Socket client = new Socket(serverName, port);
         System.out.println("远程主机地址:" + client.getRemoteSocketAddress());
         OutputStream outToServer = client.getOutputStream();
         DataOutputStream out = new DataOutputStream(outToServer);
 
         out.writeUTF("Hello from " + client.getLocalSocketAddress());
         InputStream inFromServer = client.getInputStream();
         DataInputStream in = new DataInputStream(inFromServer);
         System.out.println("服务器响应: " + in.readUTF());
         client.close();
      }catch(IOException e)
      {
         e.printStackTrace();
      }
   }
}

Socket 服务端实例

GreetingServer.java 文件代码:
// 文件名 GreetingServer.java
 
import java.net.*;
import java.io.*;
 
public class GreetingServer extends Thread
{
   private ServerSocket serverSocket;
   
   public GreetingServer(int port) throws IOException
   {
      serverSocket = new ServerSocket(port);
      serverSocket.setSoTimeout(10000);
   }
 
   public void run()
   {
      while(true)
      {
         try
         {
            System.out.println("等待远程连接,端口号为:" + serverSocket.getLocalPort() + "...");
            Socket server = serverSocket.accept();
            System.out.println("远程主机地址:" + server.getRemoteSocketAddress());
            DataInputStream in = new DataInputStream(server.getInputStream());
            System.out.println(in.readUTF());
            DataOutputStream out = new DataOutputStream(server.getOutputStream());
            out.writeUTF("谢谢连接我:" + server.getLocalSocketAddress() + "\nGoodbye!");
            server.close();
         }catch(SocketTimeoutException s)
         {
            System.out.println("Socket timed out!");
            break;
         }catch(IOException e)
         {
            e.printStackTrace();
            break;
         }
      }
   }
   public static void main(String [] args)
   {
      int port = Integer.parseInt(args[0]);
      try
      {
         Thread t = new GreetingServer(port);
         t.run();
      }catch(IOException e)
      {
         e.printStackTrace();
      }
   }
}

Java的反射(reflection)机制是指在程序的运行状态中,可以构造任意一个类的对象,可以了解任意一个对象所属的类,可以了解任意一个类的成员变量和方法,可以调用任意一个对象的属性和方法。这种动态获取程序信息以及动态调用对象的功能称为Java语言的反射机制。反射被视为动态语言的关键。[2]

简单地说,就是对于任意的一个类,都可以获取到这个类的任意属性和任意方法。这种获取的方式被称之为反射。

反射的作用
反射可以让编码更加的灵活。在一些知名的框架中,不乏反射的身影,例如:Spring、Mybatis、Jackson、 GSON、Boon等。


在使用Java反射过程中,这些是常会被使用到的类。

类    说明
java.lang.Class    Class 类的实例表示正在运行的 Java 应用程序中的类和接口。 枚举是一种类,注解是一种接口。
java.lang.reflect.Method    Method提供有关类或接口上的单个方法的信息和对它的访问。 反射方法可以是类方法,也可以是实例方法(包括抽象方法)。
java.lang.reflect.Constructor    Constructor提供有关类的单个构造函数的信息和访问权限。
java.lang.reflect.Field    Field提供有关类或接口的单个字段的信息和对它们的动态访问。 反射字段可以是类(静态)字段或实例字段。

反射机制相关的重要的类有哪些?
类    含义
java.lang.Class    代表整个字节码。代表一个类型,代表整个类。
java.lang.reflect.Method    代表字节码中的方法字节码。代表类中的方法。
java.lang.reflect.Constructor    代表字节码中的构造方法字节码。代表类中的构造方法。
java.lang.reflect.Field    代表字节码中的属性字节码。代表类中的成员变量(静态变量+实例变量)。
注:必须先获得Class才能获取Method、Constructor、Field。

eg.

java.lang.Class:
public class User{
  
    // Field
    int no;
    
    // Constructor
    public User(){
  
    
    }
    public User(int no){
  
        this.no = no;
    }
    
    // Method
    public void setNo(int no){
  
        this.no = no;
    }
    public int getNo(){
  
        return no;
    }
}

获取Class的三方式
要操作一个类的字节码,需要首先获取到这个类的字节码,怎么获取java.lang.Class实例?

方式    备注
Class.forName(“完整类名带包名”)    静态方法
对象.getClass()    
任何类型.class

通过反射实例化对象
对象.newInstance()
注:newInstance()方法内部实际上调用了无参数构造方法,必须保证无参构造存在才可以。
否则会抛出java.lang.InstantiationException异常。

eg.

class ReflectTest02{
  
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
  
        // 下面这段代码是以反射机制的方式创建对象。

        // 通过反射机制,获取Class,通过Class来实例化对象
        Class c = Class.forName("javase.reflectBean.User");
        // newInstance() 这个方法会调用User这个类的无参数构造方法,完成对象的创建。
        // 重点是:newInstance()调用的是无参构造,必须保证无参构造是存在的!
        Object obj = c.newInstance();
        System.out.println(obj);
    }
}

Method类中invoke()使用注意事项:

方法.invoke(对象, 实参);
eg.通过反射机制调用一个对象的方法
/*
重点:必须掌握,通过反射机制怎么调用一个对象的方法?
    五颗星*****

    反射机制,让代码很具有通用性,可变化的内容都是写到配置文件当中,
    将来修改配置文件之后,创建的对象不一样了,调用的方法也不同了,
    但是java代码不需要做任何改动。这就是反射机制的魅力。
 */
class ReflectTest10{
  
    public static void main(String[] args) throws Exception {
  
        // 不使用反射机制,怎么调用方法
        // 创建对象
        UserService userService = new UserService();
        // 调用方法
        /*
            要素分析:
                要素1:对象userService
                要素2:login方法名
                要素3:实参列表
                要素4:返回值
         */
        System.out.println(userService.login("admin", "123") ? "登入成功!" : "登入失败!");

        //使用反射机制调用方法
        Class userServiceClass = Class.forName("javase.reflectBean.UserService");
        // 创建对象
        Object obj = userServiceClass.newInstance();
        // 获取Method

Constructor类方法
方法名    备注
public String getName()    返回构造方法名
public int getModifiers()    获取构造方法的修饰符列表,返回的修饰符是一个数字,每个数字是修饰符的代号【一般配合Modifier类的toString(int x)方法使用】
public Class<?>[] getParameterTypes()    返回构造方法的修饰符列表(一个方法的参数可能会有多个。)【结果集一般配合Class类的getSimpleName()方法使用】
public T newInstance(Object … initargs)    创建对象【参数为创建对象的数据】

eg.反编译一个类的构造方法Constructor
/*
反编译一个类的Constructor构造方法。
 */
class ReflectTest11{
  
    public static void main(String[] args) throws ClassNotFoundException {
  
        StringBuilder s = new StringBuilder();

        Class vipClass = Class.forName("javase.reflectBean.Vip");

        //public class UserService {
  
        s.append(Modifier.toString(vipClass.getModifiers()));
        s.append(" class ");
        s.append(vipClass.getSimpleName());
        s.append("{\n");

        Constructor[] constructors = vipClass.getDeclaredConstructors();
        for (Constructor c : constructors){
  
            //public Vip(int no, String name, String birth, boolean sex) {
  
            s.append("\t");
            s.append(Modifier.toString(c.getModifiers()));
            s.append(" ");
//            s.append(c.getName());//包名+类名
            s.append(vipClass.getSimpleName());//类名
            s.append("(");
            Class[] parameterTypes = c.getParameterTypes();
            for (int i = 0; i < parameterTypes.length; i++){
  
                s.append(parameterTypes[i].getSimpleName());
                if (i != parameterTypes.length - 1 ) s.append(", ");
            }
            s.append("){}\n");
        }

        s.append("}");
        System.out.println(s);
    }
}、
射机制创建对象两步骤
先获取到这个有参数的构造方法【用ClassgetDeclaredConstructor()方法获取】
调用构造方法new对象【用Constructor类的newInstance()方法new对象】
eg.通过反射机制调用构造方法实例化java对象
/*
比上一个例子(ReflectTest11)重要一些!!!

通过反射机制调用构造方法实例化java对象。(这个不是重点)
 */
class ReflectTest12{
  
    public static void main(String[] args) throws Exception {
  
        //不适用反射创建对象
        Vip vip1 = new Vip();
        Vip vip2 = new Vip(123, "zhangsan", "2001-10-19", false);

        //使用反射机制创建对象(以前)
        Class vipClass = Class.forName("javase.reflectBean.Vip");
        // 调用无参数构造方法
        Object obj1 = vipClass.newInstance();//Class类的newInstance方法
        System.out.println(obj1);

        //使用反射机制创建对象(现在)
        // 调用有参数的构造方法怎么办?
        // 第一步:先获取到这个有参数的构造方法
        Constructor c1 = vipClass.getDeclaredConstructor(int.class, String.class, String.class, boolean.class);
        // 第二步:调用构造方法new对象
        Object obj2 = c1.newInstance(321, "lsi", "1999-10-11", true);//Constructor类的newInstance方法
        System.out.println(obj2);

        // 获取无参数构造方法
        Constructor c2 = vipClass.getDeclaredConstructor();
        Object obj3 = c2.newInstance();
        System.out.println(obj3);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值