科普时间
对象:java实例化一个类的时候,可以称为一个对象,或者一个实例,比如下方的myPuppy (其他方法忽略)
Puppy myPuppy = new Puppy("tommy");
抽象类:父类是将子类所共同拥有的属性和方法进行抽取,这些属性和方法中,有的是已经明确实现了的,有的还无法确定,那么我们就可以将其定义成抽象,在以后的子类中进行重用,进行具体化(就是继承父类的方法名,重新定义方法内容)
用abstract关键字来修饰抽象方法,用abstract来修饰抽象类
抽象方法:在抽象类中的用abstract修饰的方法,只定义个方法名字,没有内容,方便子类继承这个类的时候具体将此方法内容定义出来
package javastudy;
public class AbstractDemo1 {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
}
// 这就是一个抽象类
abstract class Animal {
String name;
int age;
// 动物会叫 这就是一个抽象方法
public abstract void cry(); // 不确定动物怎么叫的。定义成抽象方法,来解决父类方法的不确定性。抽象方法在父类中不能实现,所以没有函数体。但在后续在继承时,要具体实现此方法。
}
// 抽象类可以被继承
// 当继承的父类是抽象类时,需要将抽象类中的所有抽象方法全部实现。
class cat extends Animal {
// 实现父类的cry抽象方法
public void cry() {
System.out.println("猫叫:");
}
}
接口:是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
//一个简单的接口
interface in1 {
// 默认为 Public Static Final
final int a =10;
// 默认为抽象方法 public and abstract
void display();
}
继承接口的方式是使用implements去实现接口,当你为了实现接口写的类中实现了接口所有的方法,才算这个类实现接口成功:
class testClass implements in1 {
// 实现接口中的方法
public void display() {
System.out.println("Study");
}
}
写一个测试类,用来测试一下刚才实现的这个接口,因为testclass类的对象t实现了接口规定的display方法,那么自然而然就可以调用display()方法咯。
class testClass implements in1 {
// 实现接口中的方法
public void display() {
System.out.println("Study");
}
public static void main (String[] args) {
testClass t = new testClass();
t.display();
System.out.println(a);
}
}
概念
-
序列化:把对象转换为字节序列的过程称为对象的序列化。
-
反序列化:把字节序列恢复为对象的过程称为对象的反序列化。
在Java中,我们可以通过多种方式来创建对象,并且只要对象没有被回收我们都可以复用此对象。但是,我们创建出来的这些对象都存在于JVM中的堆(heap)内存中,只有JVM处于运行状态的时候,这些对象才可能存在。一旦JVM停止,这些对象也就随之消失,但是在真实的应用场景中,我们需要将这些对象持久化下来,并且在需要的时候将对象重新读取出来,Java的序列化和反序列化可以帮助我们实现该功能。
主要两种用途:
1) 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中;
2) 在网络上传送对象的字节序列。
最常见的是Web服务器中的Session对象,当有 10万用户并发访问,就有可能出现10万个Session对象,内存可能吃不消,于是Web容器就会把一些session先序列化到硬盘中,等要用了,再把保存在硬盘中的对象还原到内存中。
相关接口及类
Java为了方便开发人员将java对象序列化及反序列化提供了一套方便的API来支持,其中包括以下接口和类
java.io.Serializable //接口1
java.io.Externalizable //接口2
ObjectOutput
ObjectInput
ObjectOutputStream
ObjectInputStream
Demo
-
使用Java.io.Serializable对类的序列化和反序列化
package com.company; import java.io.*; public class SerializableDemo1 { //建立User类实现java提供的Serializable接口 public static class User implements Serializable { private String userName; public void setName(String userName) { this.userName = userName; } public String getName() { return userName; } } //序列化demo public static void main(String[] args) throws Exception, IOException { //初始化对象 User resOld = new User(); //要序列化的对象 resOld.setName("awsl"); System.out.println("序列化前:" + resOld.getName()); //首尾呼应~ //序列化对象到文件中 FileOutputStream creatFile = new FileOutputStream("ser"); //创建ser文件 ObjectOutputStream serResult = new ObjectOutputStream(creatFile); serResult.writeObject(resOld); //将序列化后的字节写入文件 serResult.close(); //反序列化 FileInputStream readFile = new FileInputStream("ser"); //读取ser文件 ObjectInputStream unserFile = new ObjectInputStream(readFile); //读取序列化后的字节 User resNew = (User) unserFile.readObject(); //反序列化还原对象 unserFile.close(); System.out.println("序列化后:" + resNew.getName()); //首尾呼应~ } }
-
使用java.io.Externalizable对类的序列化和反序列化
package com.company; import java.io.*; public class SerializableDemo2 { //建立Study类实现java提供的Externalizable接口 public static class Study implements Externalizable { private String myName; public void setName(String argsName){ this.myName = argsName; } public String getName() { return this.myName; } @Override //使用Externalizable接口会强制生成此类 public void writeExternal(ObjectOutput out) throws IOException { out.writeObject(myName); //不这样会导致序列化后,变量的值被清空 } @Override //使用Externalizable接口会强制生成此类 public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException { myName = (String)in.readObject(); //不这样会导致序列化后,变量的值被清空 } } public static void main(String[] args) throws IOException, ClassNotFoundException { //初始化参数 Study resOld = new Study(); resOld.setName("xmsl"); System.out.println("序列化前:" + resOld.getName()); //首尾呼应 //创建用来存储序列化字节码的文件 FileOutputStream creatFile = new FileOutputStream("ser2"); //序列化 ObjectOutputStream serResult = new ObjectOutputStream(creatFile); serResult.writeObject(resOld); serResult.close(); //读取刚才用来存储序列化字节码的文件 FileInputStream readFile = new FileInputStream("ser2"); //反序列化 ObjectInputStream unserResult = new ObjectInputStream(readFile); Study resNew = (Study) unserResult.readObject(); unserResult.close(); System.out.println("序列化后:" + resNew.getName()); //首尾呼应 } }
其他
-
序列化保存的是对象的状态
-
静态变量属于类的状态,因此 序列化并不保存静态变量
-
使用transient修饰不想被序列化的变量,在变量声明前加上该关键字,可以阻止该变量被序列化到文件中,在被反序列化后,transient 变量的值被设为初始值,如 int 型的是 0,对象型的是 null。
public transient int youAge;