Notes on crazy java handout: Annotation and input and output

Crazy java handout reading notes (6): annotation and input / output

(1) Annotation

The five basic annotations are as follows:

  • @Override: used to specify a method override that forces a subclass to override a method of its parent. However, it can only modify methods.
  • @Deprecated: tags are obsolete, such as a class or element.
  • @Suppresswarnings: suppresses compiler warnings. Use this annotation to modify a class to suppress the display of a compiler's progress, and at the same time modify a method in the class to suppress the display of another compiler's warning. Then the method will suppress the display of another compiler's warning at the same time, and the method will suppress the display of both compiler's warnings at the same time.
  • @SafeVarargs: developers do not want to see the warning of heap pollution. They can use this annotation to modify the method or constructor that raises the warning. They can also use @ suppresswarnings ("unchecked") to suppress the heap pollution warning.
  • @Functional interface: if there is only one abstract method in an interface, the interface is a functional interface. This annotation is used to specify that an interface must be a functional interface.

###(2) I / O

Class 1.File

File can create, delete, rename files and directories. File cannot access the file content itself. If you need to access the file content itself, you need to use the input / output stream. In the method related to directory operation, there is a String[] list(), which is used to list all the sub file names and path names of the file object, and return the String array. This method can accept a FilenameFilter parameter, through which only the qualified files can be listed, which is equivalent to a file filter. The FilenameFilter interface is also a functional interface. You can use lambda expressions to create objects that implement the interface.

2. Understand the IO flow of Java

There are many kinds of methods from different angles. For example, input stream and output stream; byte stream and character stream; node stream and processing stream.

Input stream: data can only be read from, not written to.

Output stream: data can only be written to, not read from.

InputStream and Reader are the base classes, while OutputStream and Writer are the main output streams. However, they are abstract base classes and cannot create instances directly.

The usage of byte stream and character stream are almost the same. If some methods are involved later, the description will be omitted. Just consult the API. The data unit of byte stream operation is 8-bit byte, while the data unit of character stream operation is 16 bit character. Byte stream is mainly based on InputStream and OutputStream, and character stream is based on Reader and Writer.

Node flow refers to the flow that can read / write data from a specific IO device. The processing flow is used to connect or encapsulate an existing flow, and realize the data read / write function through the encapsulated flow.

3. Object serialization

The goal of object serialization is to save the object to disk, or to allow the object to be transferred directly in the network. The object serialization mechanism allows the Java object in memory to be converted into a platform independent binary stream, so as to allow the binary stream to be stored on the disk for a long time and transmitted to another network node through the network. Once other programs get the binary stream, they can restore the binary stream to the original Java object. That is to say, when the object is serialized, a Java object is written to the IO stream, and deserialization is to recover the Java object from Io.

In order for a class to be Serializable, one of the Serializable or Externalizable interfaces must be implemented. However, many Java classes have already implemented Serializable, which is a tag interface. There is no need to implement any method to implement this interface. It just shows that the instances of this class are Serializable.

The following procedures of serialization and deserialization are shown below.

//Create a new Person class to implement the serializable interface
public class Person implements Serializable {
	private String name;
	private int age;

	public Person(String name,int age){
		System.out.println("Parametrical constructor");
		this.name=name;
		this.age=age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

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

	public int getAge() {
		return age;
	}

	@Override
	public String toString() {
		return "Person{" +
				"name='" + name + '\'' +
				", age=" + age +
				'}';
	}
}

The following program writes a Person object to a disk file. After running, it will be found that an object.txt is generated, and the content of the file is the Person object.

//serialize
public class WriteObject {
	public static void main(String[] args) {
		try {
			ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("object.txt"));
			Person per=new Person("Wang Er Xiao",15);
			oos.writeObject(per);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

The readObject() method is used to read objects in the stream. When running, we can find that the program does not call the constructor, which means that the deserialization mechanism does not need to initialize Java objects through the constructor.

//De serialization
public class ReadObject {
	public static void main(String[] args) {
		try {
			ObjectInputStream ois=new ObjectInputStream(new FileInputStream("object.txt"));
			Person p=(Person)ois.readObject();
			System.out.println("name:"+p.getName()+" age:"+p.getAge());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}

//Operation result
//name: Wang erxiao age:15

If a reference type appears in the Person class, what happens to serialization. There is no doubt that the reference type must be serializable, otherwise the Person class cannot be serialized.

For another example, create a new Teacher class. Note that this class holds a reference to the Student object. No new Student class will be created here. In fact, it is the same as the Person class except for the name.

public class Teacher implements Serializable {
	private String name;
	private Student student;

	public Teacher(String name,Student student){
		this.name=name;
		this.student=student;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Student getStudent() {
		return student;
	}

	public void setStudent(Student student) {
		this.student = student;
	}
}

If I want to implement the following three lines of code, think about it. If I serialize t1 first, the system will serialize t1 together with the Student object. If I serialize t2, the Student object will be serialized once. If the program is displaying the serialized stu, I have to serialize the Student object 100 million times. It seems that three Student objects will be generated.

Student stu=new Student("Sun WuKong",500);
Teacher t1=new Teacher("Tang Seng",stu);
Teacher t2=new Teacher("master puti",stu);

If you deserialize, you will still get three Student objects, which will cause that t1 and t2 refer to different Student objects, which is obviously wrong. So the Java serialization mechanism has a special serialization algorithm:

All objects saved to disk have a serialization number.
When the program attempts to serialize an object, it will first check whether the object has been serialized, and if it has never been serialized, it will convert the object into a byte sequence and then output.
If an object is serialized, it will simply output a serialization number instead of deserializing the object again.

That is, only when the writeObject() method is called for the first time will the object be converted to a byte sequence and output.

Let's take a look at serialization. In fact, only three objects, t1, t2 and stu, are serialized.

public class WriteTeacher {

	public static void main(String[] args) {
		try {
			ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("teacher.txt"));
			Student stu=new Student("Sun WuKong",500);
			Teacher t1=new Teacher("Tang Seng",stu);
			Teacher t2=new Teacher("master puti",stu);
			oos.writeObject(t1);
			oos.writeObject(t2);
			oos.writeObject(stu);
			oos.writeObject(t2);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

Deserialize validation.

public class WriteTeacher {

	public static void main(String[] args) {
		try {
			ObjectInputStream ois=new ObjectInputStream(new FileInputStream("teacher.txt"));
			Teacher t1=(Teacher)ois.readObject();
			Teacher t2=(Teacher)ois.readObject();
			Student stu=(Student)ois.readObject();
			Teacher t3=(Teacher)ois.readObject();
			System.out.println("t1 Of student Reference and stu The same:"+(t1.getStudent()==stu));
			System.out.println("t2 Of student Reference and stu The same:"+(t2.getStudent()==stu));
			System.out.println("t2 and t3 Is it the same object"+(t2==t3));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}


/**Output result
 * t1 The student reference of is the same as stu: true
 * t2 The student reference of is the same as stu: true
 * t2 Whether and t3 are the same object: true
 */

To serialize the same Java object multiple times, only when the Java object is serialized for the first time can it be converted into a byte sequence and output, which may cause a potential problem, that is, when the program serializes a variable object, only when the writeObject() method is used for the first time to output, can the object be converted into a byte sequence and output, when the program calls writeobje again CT () method. The program just outputs the serialization number. Even if the instance variable value of the object changes later, the changed value will not be output.

This output result should explain the problem. The output is Wang Er Xiao, not Li Si.

public class Mutable implements Serializable {
	public static void main(String[] args) {
		try {
			ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("mutable.txt"));
			ObjectInputStream ois=new ObjectInputStream(new FileInputStream("mutable.txt"));
			Person per=new Person("Wang Er Xiao",15);
			oos.writeObject(per);
			per.setName("Li Si");
			oos.writeObject(per);
			Person p1=(Person)ois.readObject();
			Person p2=(Person)ois.readObject();
			System.out.println(p1==p2);
			System.out.println(p2.getName());
		} catch (IOException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}

/*
Output result
 Parametrical constructor
true
 Wang Er Xiao
 */
Published 43 original articles, won praise 5, visited 5612
Private letter follow

Tags: Java network Lambda

Posted on Wed, 15 Jan 2020 03:47:29 -0800 by saltedm8