注解

通过使用 注解增强"类、方法、属性"的功能。

内置注解

Java 定义了一套注解,共有 7 个,3 个在 java.lang 中,剩下 4 个在 java.lang.annotation 中。

@Deprecated  -- @Deprecated 所标注内容,不再被建议使用。
@Override    -- @Override 只能标注方法,表示该方法覆盖父类中的方法。
@Documented  -- @Documented 所标注内容,可以出现在javadoc中。
@Inherited   -- @Inherited只能被用来标注“Annotation类型”,它所标注的Annotation具有继承性。
@Retention   -- @Retention只能被用来标注“Annotation类型”,而且它被用来指定Annotation的RetentionPolicy属性。
@Target      -- @Target只能被用来标注“Annotation类型”,而且它被用来指定Annotation的ElementType属性。
@SuppressWarnings -- @SuppressWarnings 所标注内容产生的警告,编译器会对这些警告保持静默

@SuppressWarnings(value="unchecked")//压制警告 (虽然可以使用SuppressWarnings压制警告,但不建议使用。)//忽略对泛型等的检查操作。value值:unchecked ,deprecation(忽略一些过期的API) ,unused (是否未被使用) ,fallthrough(swtich 是否一致往下执行,而没有break);path(忽略 对类路径不存在的检查) ,serialVersionUID(忽略 一个类可以序列化、但却没有序列化的 警告),all

//压制警告(虽然可以使用SuppressWarnings压制警告,但不建议使用。)
@SuppressWarnings(value="all")//忽略对泛型等的检查操作
public class Demo {
    public static void main(String[] args) {
        int a = 0 ;
        //未使用a,不会被提示
        List list = new ArrayList();
        //未加泛型,不会被提示
    }
}

自定义注解

元数据:修饰数据的数据元注解:修饰注解的注解, @Target、@Retention、@Document、@Inherited

  • @interface -- 它的用来修饰 Inherited,意味着 Inherited 实现了 java.lang.annotation.Annotation 接口;即 Inherited 就是一个注解。
  • @Documented -- 它的作用是说明该注解能出现在 javadoc 中。

如果现在javadoc文档中 也包含对注解的说明,则需要使用 @Document标注

  • @Retention(RetentionPolicy.RUNTIME) -- 它的作用是指定 Inherited 的策略是 RetentionPolicy.RUNTIME。这就意味着,编译器会将 Inherited 的信息保留在 .class 文件中,并且能被虚拟机读取。

    //限制注解的生命周期
    public enum RetentionPolicy {
        /**
        * Annotations are to be discarded by the compiler.
        jvm直接将该注解丢弃 
        */
        SOURCE,
    
        /**
        * Annotations are to be recorded in the class file by the compiler
        * but need not be retained by the VM at run time.  This is the default
        * behavior.
        .java -> .class
        程序在编译时 会使用注解,在运行时不会使用
        */
        CLASS,
    
        /**
        * Annotations are to be recorded in the class file by the compiler and
        * retained by the VM at run time, so they may be read reflectively.
        *
        * @see java.lang.reflect.AnnotatedElement
        程序在编译以及运行时,都会使用注解
        */
        RUNTIME
    }
  • @Target(ElementType.ANNOTATION_TYPE) -- 它的作用是指定 Inherited 的类型是 ANNOTATION_TYPE。这就意味着,@Inherited 只能被用来标注 "Annotation 类型"。

能够使用哪些元素上(属性、方法、类);如果一个注解没有@Target描述,则该注解 可以修饰任何类型的元素; 如果有@Target修饰,该注解就只能用于 被@Target修饰的地方

  • @Inherited 的含义是,它所标注的Annotation将具有继承性。

    @Inherited
    public @interface MyAnnotation {}
    
    @MyAnnotation
    public  class A {}
    
    public  class B extends A {}
    //默认情况下,B不会继承A中的注解;如果要想继承,则需要加@Inherited
@Target(value = { ElementType.PACKAGE, ElementType.FIELD })
public @interface MyAnnontation {
    /*
    * 用定义方法的形式,定义一个属性value
    * 方法的名字,就是属性的名字
    * 方法的返回值,就是属性的类型
    */
    String value() default "str";
    int age() default 10;
}

public class tmp {
    public static void main(String[] args) {

    }
    @MyAnnontation(value = "22", age = 6)
    public void a() {
    }
}

以上内容仅初步了解,以后填坑 注解+反射

IO流

流是一种FIFO的数据结构

流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象。即数据在两设备间的传输称为流,流的本质是数据传输,根据数据传输特性将流抽象为各种类,方便更直观的进行数据操作。

分类

  • 按流向(以内存为参照点)分类:

    • 输入流java.io.InputStream抽象类(字节形式)/Reader(字符形式)
    • 输出流
      java.io.OutputStream抽象类(字节形式)/Writer(字符形式)
  • 按处理单元

    • 字节流
    • 字符流

字符流和字节流

  • 字符流的由来: 因为数据编码的不同,而有了对字符进行高效操作的流对象。本质其实就是基于字节流读取时,去查了指定的码表。
  • 字节流和字符流的区别:

    • 读写单位不同:字节流以字节(8bit)为单位,字符流以字符为单位,根据码表映射字符,一次可能读多个字节。
    • 处理对象不同:字节流能处理所有类型的数据(如图片、avi等),而字符流只能处理字符类型的数据。
  • 结论:只要是处理纯文本数据,就优先考虑使用字符流。 除此之外都使用字节流。

输入流

import java.io.*;

public class tmp {
    public static void main(String[] args) {
        InputStream in = null;
        try {
            in = new FileInputStream(new File("d:/a.txt"));
            // 自适应斜杠File.separator
            byte[] buf = new byte[in.available()];
            in.read(buf);
            System.out.print(new String(buf));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

输出流

import java.io.*;

public class tmp {
    public static void main(String[] args) {
        OutputStream out = null;
        try {
            out = new FileOutputStream("d:/a.txt");
            out.write("hello".getBytes()); // 内存到文件
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

文件复制

import java.io.*;

public class FileCopy {
    // abc.txt->内存->xyz.txt
    public static void main(String[] args) {
        InputStream in = null;
        OutputStream out = null;
        try {
            // abc.txt->内存
            in = new FileInputStream("d:/abc.txt");

            out = new FileOutputStream("d:/xyz.txt");
            // 开辟10字节的内存
            byte[] buf = new byte[10];
            int len = -1;
            // 注意最后一次操作,如果文件不是10的整数倍会出错,以下代码避免
            while ((len = in.read(buf)) != -1) {// in ->buf
                out.write(buf, 0, len);// buf->out
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null)
                    out.close();
                if (in != null)
                    in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

字符流实现文件复制


import java.io.*;

public class FileCopyCharactor {
    public static void main(String[] args) {
        // 文件->内存(Reader)
        Reader reader = null;
        Writer writer = null;
        try {
            reader = new FileReader("d:/个人介绍.txt");
            writer = new FileWriter("d:/个人完整介绍.txt");

            char[] buf = new char[4];
            StringBuffer sb = new StringBuffer();

            int len = -1;
            while ((len = reader.read(buf)) != -1) {
                // str += buf ;
                sb.append(buf, 0, len);// 将每次读取到的 4个字符 拼接起来
            }
            System.out.println(sb);
            // 在内存中 替换占位符
            String content = sb.toString();
            content = content.replace("{name}", "name").replace("{enterprise}", "school").replace("{weixin}", "123");
            // 将替换后的内容 输出 到文件, 内存 ->文件(Writer)
            writer.write(content);
            System.out.println("成功...");
            // 如果不close会失败,write后文件在管道中,close后到文件
            // writer.flush(); 将管道中的数据 刷出到 文件中
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null)
                    writer.close();
                if (reader != null)
                    reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

带缓冲区的字符流

  • 缓冲区大小:一行
  • BufferedReader / BufferedWriter
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.*;

public class FileCopyCharactorBuffered {
    public static void main(String[] args) {
        // 文件->内存(Reader)
        Reader reader = null;
        Writer writer = null;

        BufferedReader br = null;
        BufferedWriter bw = null;

        try {
            reader = new FileReader("d:/个人介绍.txt");
            writer = new FileWriter("d:/个人完整介绍2.txt");

            br = new BufferedReader(reader);
            bw = new BufferedWriter(writer);

            StringBuffer sb = new StringBuffer();

            String line = null;

            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            System.out.println(sb);
            // 在内存中 替换占位符
            String content = sb.toString();
            content = content.replace("{name}", "name").replace("{enterprise}", "school").replace("{weixin}", "123");
            // 将替换后的内容 输出到文件 ,内存 ->文件(Writer)
            bw.write(content);
            System.out.println("成功...");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 1先关出,再关入 2从外往内关 br外 = new BufferedReader( reader内) ;
            try {
                if (bw != null)
                    bw.close();
                if (br != null)
                    br.close();
                if (writer != null)
                    writer.close();
                if (reader != null)
                    reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

二进制流

  • DataInputStream/DataOutputStream
  • 二进制流 对象 = new 二进制流(字节流);

装饰模式(IO设计的核心思想)

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

以后填坑设计模式

网络编程

基本概念

  • TCP协议:面向连接的,可靠的(不丢失,不重复,有序),基于字节流的传输协议
  • UDP协议:无连接的协议。S/C之间不建立和维护连接,不可靠的。传输速度相对快。
  • socket(套接字):基于TCP协议的网络通信,可以提供双向安全连接的网络通信。socket需要借助于数据流(字节流)来完成数据的传递工作.(USE TCP)

模板:

  1. 客户端建立连接 ;服务端准备服务(ip[默认本机]:端口)
  2. 通过socket生成inputstream/outputstream(准备发送数据)
  3. 使用inputstream/outputstream进行发送、接受数据
  4. 关闭inputstream/outputstream、socket

C/S通信

服务端(ServerSocket)

package demo;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class MyServer {
    public static void main(String[] args) {
        // 1.准备服务.ip:默认本机127.0.0.1,端口8888
        ServerSocket serverSocket = null;
        Socket socket = null;
        InputStream in = null;
        BufferedReader reader = null;
        OutputStream out = null;
        try {
            serverSocket = new ServerSocket(8888);
            System.out.println("服务器启动");
            // 准备完毕,可以监听客户端请求
            socket = serverSocket.accept();// 一直阻塞,直到有客户端连接
            System.out.println("服务端检测到客户端连接成功!");
            // 2.通过socket生成inputstream/outputstream(准备发送数据)
            // 3.使用inputstream/outputstream进行发送、接受数据
            in = socket.getInputStream();
            // 带缓冲区的字符流(字节流-转换流-字符流)
            reader = new BufferedReader(new InputStreamReader(in));
            String info = null;
            while ((info = reader.readLine()) != null) {
                System.out.println("I am server,接受到客户端信息是:" + info);
            }
            socket.shutdownInput();
            // 服务端做出反馈
            out = socket.getOutputStream();
            out.write("welcome client....".getBytes());
            socket.shutdownOutput();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                // 4.关闭inputstream/outputstream、socket
                if (reader != null)
                    reader.close();
                if (out != null)
                    out.close();
                if (in != null)
                    in.close();
                if (socket != null)
                    socket.close();
                if (serverSocket != null)
                    serverSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

客户端(Socket)

package demo;

import java.io.*;
import java.net.Socket;

public class MyClient {
    public static void main(String[] args) {
        Socket socket = null;
        OutputStream out = null;
        InputStream in = null;
        BufferedReader reader = null;
        try {
            socket = new Socket("127.0.0.1", 8888);
            System.out.println("客户端链接成功!");
            out = socket.getOutputStream();
            out.write("hello server".getBytes());
            socket.shutdownOutput();
            // 接收服务端的反馈
            in = socket.getInputStream();
            reader = new BufferedReader(new InputStreamReader(in));
            String info = null;
            while ((info = reader.readLine()) != null) {
                System.out.println("I am client,接收到的服务端消息:" + info);
            }
            socket.shutdownInput();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null)
                    out.close();
                if (in != null)
                    in.close();
                if (socket != null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

对象流

网络传递一个对象:

  1. 将要传递的对象序列化
  2. 使用对象流(ObjectInputStream/ObjectOutputStream)

对象:

package demo02;

import java.io.Serializable;

public class Student implements Serializable {// 将要传递的对象序列化
    private int sid;
    private String sname;
    private int age;

    public Student() {

    }

    public Student(int sid, String sname, int age) {
        this.sid = sid;
        this.sname = sname;
        this.age = age;
    }

    public int getSid() {
        return sid;
    }

    public void setSid(int sid) {
        this.sid = sid;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Student{" + "sid=" + sid + ", sname='" + sname + '\'' + ", age=" + age + '}';
    }
}

服务端

package demo02;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class MyServer {
    public static void main(String[] args) {
        ServerSocket serverScoket = null;
        Socket socket = null;
        InputStream in = null;
        ObjectInputStream ois = null;
        try {
            serverScoket = new ServerSocket(8888);
            socket = serverScoket.accept();
            // 接受客户端发来的对象
            in = socket.getInputStream();
            // 对象流
            ois = new ObjectInputStream(in);
            try {
                Student student = (Student) ois.readObject();// 读取对象
                System.out.println(student);
                socket.shutdownInput();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (ois != null)
                    ois.close();
                if (in != null)
                    in.close();
                if (socket != null)
                    socket.close();
                if (serverScoket != null)
                    serverScoket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

客户端

package demo02;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;

public class MyClient {
    public static void main(String[] args) {
        Socket socket = null;
        OutputStream out = null;
        ObjectOutputStream oos = null;
        try {
            socket = new Socket("localhost", 8888);
            Student student = new Student(1001, "zs", 23);
            out = socket.getOutputStream();
            // 将OutputStream转为对象流
            oos = new ObjectOutputStream(out);
            oos.writeObject(student);// 发送对象
            socket.shutdownOutput();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (oos != null)
                    oos.close();
                if (out != null)
                    out.close();
                if (socket != null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

多客户端

  • 客户端代码不变;服务端:每当有一个客户端,就开启一个新线程去处理(每个线程专门处理一个客户端对象)。

服务端线程

package demo03;

import java.io.*;
import java.net.Socket;

public class ServerThread extends Thread {
    Socket socket;

    public ServerThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        InputStream in = null;
        ObjectInputStream ois = null;
        OutputStream out = null;
        try {
            // 接受客户端数据(客户端—>服务端)
            in = socket.getInputStream();
            ois = new ObjectInputStream(in);
            Student student = (Student) ois.readObject();
            System.out.println(student);
            socket.shutdownInput();
            // 给客户端反馈(服务端->客户端)
            out = socket.getOutputStream();
            out.write("已收到....".getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                out.close();
                ois.close();
                in.close();
                socket.close();
                ;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

服务端

package demo03;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class MyServer {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8888);
            while (true) {
                Socket socket = serverSocket.accept();// 阻塞,接受客户端请求
                ServerThread serverThread = new ServerThread(socket);
                serverThread.start();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

客户端

package demo03;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;

public class MyClient {
    public static void main(String[] args) {
        Socket socket = null;
        OutputStream out = null;
        ObjectOutputStream oos = null;
        try {
            socket = new Socket("localhost", 8888);
            Student student = new Student(1001, "zs", 23);
            out = socket.getOutputStream();
            // 将OutputStream转为对象流
            oos = new ObjectOutputStream(out);
            oos.writeObject(student);// 发送对象
            socket.shutdownOutput();
            // 接受服务端的反馈
            InputStream in = socket.getInputStream();
            byte[] buf = new byte[100];
            in.read(buf);
            System.out.println("接收到的服务端反馈:" + new String(buf));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (oos != null)
                    oos.close();
                if (out != null)
                    out.close();
                if (socket != null)
                    socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

UDP编程

DatagramPacket(数据):封装了数据报的数据、数据长度、目标地址和目标端口。
DatagramScoket(收发器):接收和发送DatagramPacket中封装好的数据。

接收方

package demo04;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

public class Receive {
    public static void main(String[] args) {
        DatagramSocket ds = null;
        byte[] data = new byte[64];
        // 准备接收数据的对象
        DatagramPacket dp = new DatagramPacket(data, data.length);
        // 接收数据
        try {
            ds = new DatagramSocket(9999);
            ds.receive(dp);
            // 显示接收到的数据
            String receiveData = new String(dp.getData(), 0, data.length);
            System.out.println("接收到的数据:" + receiveData);
            System.out.println("显示发送方的信息:" + dp.getAddress().getHostAddress());
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            ds.close();
        }
    }
}

发送方

package demo04;

import java.io.IOException;
import java.net.*;

public class Send {
    public static void main(String[] args) {
        DatagramSocket ds = null;
        // 创建一个InetAddress对象
        InetAddress ip = null;
        try {
            ip = InetAddress.getByName("127.0.0.1");
            String msg = "helloserver..";
            DatagramPacket dp = new DatagramPacket(msg.getBytes(), msg.length(), ip, 9999);
            ds = new DatagramSocket();
            ds.send(dp);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            ds.close();
        }
    }
}
  • 总结:发送数据使用的工具

    • TCP:字节流
    • UDP:DatagramScoket

InetAddress/URLConnection

  • InetAddress
    public static void main(String[] args) {
        InetAddress host = null;
        try {
            // 本机
            host = InetAddress.getLocalHost();
            System.out.println(host);
            // 网络中任意一台
            InetAddress host163 = InetAddress.getByName("www.163.com");
            System.out.println(host163);
        } catch (UnknownHostException e) {
            e.printStackTrace();
        }
    }
  • URL/URLConnection
package demo05;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

public class URLDemo {
    public static void main(String[] args) {
        InputStream in = null;
        URLConnection urlConnection = null;
        OutputStream out = null;
        try {
            URL url = new URL("https://www.163.com/");
            urlConnection = url.openConnection();
            in = urlConnection.getInputStream();
            out = new FileOutputStream("d:\\163.txt");
            byte[] buf = new byte[64];
            int len = -1;
            while ((len = in.read(buf)) != -1) {
                out.write(buf, 0, len);
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (out != null)
                    out.close();
                if (in != null)
                    in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

参考链接:




扫一扫在手机打开当前页
最后修改:2020 年 07 月 23 日 08 : 33 PM