创建对象的四种方式
- New 对象
开辟内存空间,在堆中存放 - 克隆 拷贝创建对象
- 反序列化
把字节序列恢复为原来的Java对象 - 反射
序列化与反序列化
序列化:是一个Java对象作一下“变换”,变成字节序列。这样一来方便持久化存储到磁盘,避免程序运行结束后对象就从内存里消失,另外变换成字节序列也更便于网络运输和传播。
反序列化: 把字节序列恢复为原来的Java对象。
实现序列化的接口:Serializable
Serializable是一个标记性接口,没有实现任何内容,只是告诉JVM当前对象需要序列化。
(Cloneable接口也是一个标记性接口,没有任何内容,只是告诉JVM该对象需要克隆)
SerialVersionUID是序列化前后唯一的标识符,如果没有人为定义过SerialVersionUID,那么编译器会自动声明一个。一般不需要人为处理。
- 注:
static修饰的不会被序列化
transient修饰的不会被序列化
Demo
Car.java
package com.wdy.stream;
import java.io.Serializable;
public class Car implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L; //版本信息,编译器自动声明。一般不需要人为修改
private int id;
private String brand;
private String color;
private double price;
public Car() {
}
public Car (int id, String brand, String color, double price) {
this.id = id;
this.brand = brand;
this.color = color;
this.price = price;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
@Override
public String toString() {
return "Car [id=" + id + ", brand=" + brand + ", color=" + color + ", price=" + price + "]";
}
}
输出流 写入Car对象的属性
package com.wdy.stream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/*
* 输出流 写入Car对象的属性
*/
public class ObjectOutputStreamDemo {
public static void main(String[] args) throws Exception {
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("D:\\car.dat")); //创建输入流对象 字节流对象
Car c = new Car(1, "bmw", "黑色", 1200000.00);
out.writeObject(c);//写入属性
out.close();
}
}
执行结果:
package com.wdy.stream;
import java.io.FileInputStream;
import java.io.ObjectInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
/*
* 输出流 把文件中的内容读出
*/
public class ObjectInputStreamDemo {
public static void main(String[] args) throws Exception {
ObjectInputStream in = new ObjectInputStream(new FileInputStream("D:\\car.dat"));
Car car = (Car) in.readObject();//.readObject() 读取对象的方法 读到的对象是Car对象 。强转
System.out.println(car);
}
}
执行结果:
NIO
java.nio全称java non-blocking 10- (实际上是new io),是指JDK 1.4及以上版本里提供的新api (New IO) ,为所有的原始类型(boolean类型除外):提供缓存支持的数据容器,使用它可以提供非阻塞式的高伸缩性网络。
NIO的组成
-
Channel (通道)
通道表示打开到IO设备(例如:文件、套接字)的连接。若需要使用NIO系统,需要获取用于连接IO设备的通道以及用于容纳数据的缓冲区。然后操作缓冲区,对教据进行处理。
Channel (通道)比IO中的Stream(字符流)更加高效, Channel 可以异步双向传输,但必须和buffer一起使用。 -
Buffer(缓存区)
缓冲区本质上是一块可以写入数据, 然后可以从中读
取教据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法, 用来方便的访问该块内存。 -
Selector
允许单线程处理多个Channel ,如果你的应用打开了多个连
接(通道),但每个连接的流量都很低,使用Selector方法就会很方
便。
Selector可以检测多个NIO Channel,看读或者写事件是否就绪。
多个Chanel以事件的方式可以注册到同一个Seletor,从而使用一个线程处理多个请求成为可能。
Demo
nio和普通的输入输出流相比,可以同时读和写,实现非阻塞同步 。普通的流在执行读(写)任务就会阻塞写(读)线程。
package com.wdy.stream;
import java.io.FileNotFoundException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class NIODemo {
public static void main(String[] args) throws Exception {
String path = Thread.currentThread().getContextClassLoader().getResource("").getPath();
System.out.println(path);
path =path.substring(0, path.length()-4);
System.out.println(path);
String fileName = path+"src/io/file/FileDemo02.java";
RandomAccessFile raf = new RandomAccessFile(fileName, "rw");//创建一个NIO读取的对象 “rw”代表可读可写
FileChannel inChannel = raf.getChannel(); //开辟通道 ,开辟了通道(nio)和普通的输入输出流相比,可以同时读和写,非阻塞同步 。普通的流在执行读(写)任务就会阻塞写(读)线程
ByteBuffer buffer = ByteBuffer.allocate(64);//开辟缓存空间。大小根据情况确认
int n = 0;
while((n=inChannel.read(buffer))!=-1) { //通过通道读取缓存中的内容
buffer.flip();//移动到缓存的第一个位置
while(buffer.hasRemaining()) {//判断缓存是否有数据
System.out.print((char)buffer.get()); //按字节读。强转为char
}
buffer.clear();
}
raf.close();
}
}