注解
通过使用 注解
增强"类、方法、属性"的功能。
内置注解
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)
模板:
- 客户端建立连接 ;服务端准备服务(ip[默认本机]:端口)
- 通过socket生成inputstream/outputstream(准备发送数据)
- 使用inputstream/outputstream进行发送、接受数据
- 关闭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();
}
}
}
}
对象流
网络传递一个对象:
- 将要传递的对象序列化
- 使用对象流(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();
}
}
}
}
参考链接:
版权属于:moluuser
本文链接:https://archive.moluuser.com/archives/17/
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。