Java学习笔记

在这里插入代码片# Java学习笔记
博客仅用于记录学习Java过程遇到的问题

Java学习笔记

初遇Java

1.Java语言特点

  • Simple
    Java语言简单,它的编译器和解释器所占空间内存不到250KB
  • Object-oriented(面向对象)
    Java是纯面向对象的语言
  • Distributed(分布式)
    Java语言在操作和数据上分布,但在逻辑上统一。数据分布是指数据分散存放在网络上的不同主机中,从而解决了数据量大的问题。操作分布是指将计算分布到不同的主机上进行处理
  • High-performance(高性能)
    Java字节码转换为机器码非常方便。
  • Multi-threaded(多线程)
  • Dynamic(动态)
    Java在执行中可以动态加载各种类库
  • Robust and secure(健壮,安全)
    Java没有c++的指针类型,从而避免了利用指针恶意篡改不属于程序的内存空间,除此之外,Java还具有字节码校验器、运行时间内存分布、文件访问限制、和类装载器,提高了安全性
  • Architecture-netutral(平台无关性)
  • Portable(可移植性)
  • Interpreted(解释性)

2.Java语言跨平台实现的原理是什么?

程序运行的操作系统可以是Windows/Linux/UNIX… 一般情况下在一种操作系统能运行的程序,换个操作系统就无法运行,需要重新编写,而Java却能解决这个问题。
在这里插入图片描述
平台指的是操作系统+CPU,CPU的种类有多种,此外不同CPU支持的指令集有可能相同也有可能不同,指令集是CPU用来计算和控制计算机系统的指令的集合。不同的操作系统支持不同的CPU,实际上是不同的指令集合。

*.c或.cpp程序不可跨平台原因

编译器将.c或.cpp文件便以为可执行的代码,由于这里的编译器是与平台相关的,因此可执行代码也与平台相关,导致程序不可跨平台运行。

Java语言跨平台使用原因

在C、C++中可执行代码与平台相关导致语言不能跨平台使用,在Java语言中,与平台无关的编译器编译源程序,生成与平台无关的中间码.class,再由与平台对应的虚拟机(JVM),编译为特定平台下的机械码然后运行,不同的平台有相对应的虚拟机。

3.JDK,JRE,JVM有什么区别?

JDK是 Java 语言的软件开发工具包。JDK的安装目录下有一个jre目录,里面有两个文件夹bin和lib,bin里的是jvm,lib中则是jvm工作所需要的类库,而jvm和 lib合起来就称为jre。

Java语言基础

1.Java数据类型

Java数据类型包括基本数据类型和复合数据类型。

基本数据类型复合数据类型
整数类型:byte,short,int,long; 浮点类型:fioat,double; 字符类型:char; 布尔类型:booleanclass; interface(接口)

2.基本数据类型转换

自动类型转换:不同的基本数据类型进行混合运算时,不同的数据类型先转换为同种数据类型(低级数据类型转换为高级数据类型),再进行运算。
在这里插入图片描述

强制类型转换:高级数据类型转换为低级数据类型。

3.为什么需要包装类?

Java是纯面向对象的语言,但它的基本数据类型却不是对象,导致基本数据类型在一些场合不能直接使用,比如转型,为了解决这个问题Java语言为每个基本数据类型设计了一个对应的类。

4.基本数据类型与对应的包装类有什么区别?它们之间的相互转换又是怎样的?

以int和Integer为例

intInteger
存储
初始值0null
方法中的传递值传递引用传递
是否能放入LinkedList和ArrayList不能
不是对象,没有方法和字段是对象、具有方法和字段

int转Integer(基本数据类型转换为包装类)(装箱):

int i=1;
//手动装箱
Integer a=new Integer(i);
//自动装箱
Integer b=i;

Integer转int(包装类转基本数据类型)(拆箱):

Integer x=new Integer(1);
//手动拆箱
int i=x.intValue();
//自动拆箱
int k=x;

5.逻辑运算符&与&&区别、逻辑运算符&与位运算符&区别

逻辑运算符&与&&的区别
当运算符左边的表达式为false时
a&&b 不会再计算右边的表达式,结束运算,结果为false;
a&b 会继续运算右边表达式,结果为false;
逻辑运算符&与位运算符&区别
位运算&,先将两个表达式的值按二进制位展开,然后对应的位按值进行”与”运算,结果保留在该位上。

6.跳出多重循环语句

break;break lab

continue
return
throw

面向对象(上)

1.对象与对象引用的区别

内存:对象引用存储在栈,对象在堆上;
对象引用相当于遥控器,而对象相当于电视机,对象引用能操纵对象。

2.对象作为参数传递的特点

对象作为参数传递时其实传的是参数的地址

3.对象初始化顺序

eg:FighterPlane fp=new FighterPlane()
在上述语句中,先创建一个对象“new FighterPlane()”,之后再将对象赋值给对象引用“fp”
具体过程:1.“new FighterPlane()”根据类模板产生一个对象,并在计算机的堆中为此对象分配一块内存空间,类中的属性赋值到新生成的对象中,然后对象将地址传递给引用。引用在栈中有自己的内存空间

4.类的static数据成员与非static数据成员的区别,什么用static属性

static方法是专属于类的,不属于类的任何对象
非static方法实际上是为对象服务的
static方法可以被所有对象访问,但其内部代码只能访问static属性和方法
非static方法可以访问static属性方法
static域变量储存在堆中的公共存储单元,非static域变量储存在变量的内存区

5.Java中final与finalize的区别

6.Java中float[10]arr语句是否正确?

不正确
float [ ] arr=new float[10];
“=”左面只是声明数组,执行完左面后,计算机并未分配新的内存,“=”右面才为其分配内存空间

7.Java数组元素类型为基本数据类型和引用类型时,有什么不同?

由于对象数组的数组元素类型是引用类型,这就需要我们在使用对象数组的成员前先创建新的对象,并将元素指向新的对象。

下面展示一些 内联代码片

String []arr=new String[10];
for(String x:arr)
    System.out.println(x);

面向对象(中)

1、Java的访问控制修饰符

在这里插入图片描述

2、子类对于从父类继承的哪些属性与方法是可见的?

子类继承了父类的所有方法和属性,但只有public和protected方法和属性在子类是可见的(当子类和父类在同一个包中子类,或者子类和父类不在同一个包中,但父类的类前修饰符必须为public,以满足父类能被访问的前提)

3、什么是组合?组合的作用是什么?

组合和继承都是实现代码复用的方法,组合是通过对象内部属性的引用实现的,

什么是重载?重载的作用是什么?

重载定义:如果有两个方法的方法名相同,但参数不一致,哪么可以说一个方法是另一个方法的重载。
作用:
定义端(方法的提供者):使用相同的方法名(一个方法)来表示功能相同的(多个)方法。
调用端(方法的使用者): 在调用的时候,可以使用相同名字(一个名字)的方法实现不同的功能。
重载也是多态性的体现:一个内容,可以实现多个功能

什么是覆盖?覆盖的作用是什么?

定义:子类中定义一个方法,其名称、返回类型及参数签名正好与父类中某个方法的名称、返回类型及参数签名相匹配。

作用:可以在不更改父类的方法情况下创建了子类的方法,因此使程序更加安全。

面向对象(下)

1.消息

向一方发消息

public class Communicate {
    public static void main(String []args){
        MessageA a0=new MessageA("林海",18);
        MessageB b0=new MessageB(a0);
        b0.PrintMessageA();    
    }
}
class MessageA{
    String name;
    int age;
    public MessageA(String name,int age){
        this.name=name;this.age=age;
    }
}
class MessageB{
    MessageA a;
    public MessageB(MessageA a0){
        this.a=a0;
    }
    
}

互发消息

public class Communicate {
    public static void main(String []args){
        MessageA a0=new MessageA("林海",18);
        MessageB b0=new MessageB(a0);
        b0.PrintMessageA();
        a0.PrintMessageB();
    }
}
class MessageA{
    String name;
    int age;
    MessageB bInmsgA;
    public MessageA(String name,int age){
        this.name=name;this.age=age;
    }
    public void SetAtoB(MessageB bb){
        this.bInmsgA=bb;
    }
    public void PrintMessageB(){
        System.out.print("Bcode"+"="+bInmsgA.Bcode);
    }

}
class MessageB{
    MessageA a;
    int Bcode=10001;
    public MessageB(MessageA a0){
        this.a=a0;
        a.SetAtoB(this);//this指当前的对象
    }
    public void PrintMessageA(){
        System.out.println(a.name+a.age);
    }
}

2.构造方法的多态

构造方法的重载

public class poly {
    public static void main(String []args){
        A a0=new A(2,3,5);
        System.out.println(a0.add());
        A a1=new A(6,7);
        System.out.println(a1.add());
        A a2=new A(8);
        System.out.println(a2.add());
    }
}
class A{
    int x=0,y=0,z=0;
    public A(int x){
        this.x=x;
    }
    public A(int x,int y){
        this(x);
        this.y=y;
    }
    public A(int x,int y,int z){
        this(x,y);
        this.z=z;
    }
    public int add(){
        return x+y+z;
    }
}

调用过程描述:以a0为例
1,在内存中为A类对象分配空间,这时对象的属性值都还为默认值0;
2,匹配方法的参数列表,调用第三个构造函数,第三个构造函数入栈,在栈空间中为局部变量x,y,z分配空间并且传值(2,3,5)。
3,执行到this(x,y)时,调用第二个构造函数,第二个构造函数入栈,在栈空间中为局部变量x,y分配空间并且传值(2,3)。
4,执行到this(x)时,调用第一个构造函数,第一个构造函数入栈,在栈空间中为局部变量x分配空间并且传值(2)。
5,执行到this.x=x时,并不会将局部变量x的值赋给域变量x,而是执行类中的初始化字段“int x=0,y=0,z=0;”。
6,之后执行“this.x=x”,…
构造方法的继承调用

异常

1.Java error类和exception类的区别

error不是程序需要捕获和进行处理的,当error发生时,程序将会停止。
exception发生时,虚拟机会根据异常的类别,产生对应的异常对象,程序再对异常对象进行相应的处理。

2.异常处理的两种方式

隐式声明抛出
这类异常处理要求异常必须是RuntimeException或是其子类,程序方法对异常不会做声明抛出或处理,而是交给调用该方法的地方处理,程序能编译通过,不会对可能产生异常的代码行给出提示。
例:main()方法中出现除数为零的情况,main()方法并未对异常进行处理,而是交给了调用该方法的虚拟机去处理。

public class yichangchuli{
    public static void main(String []args){
        int a=2;
        int b=0;
        int c=a/b;
        System.out.print(c);
    }
}

在这里插入图片描述

显示声明抛出
当异常是非RuntimeException或其子类时,怎样可以使程序编译通过呢?
这时可以使用显示声明抛出
方法()throws 异常类
如果方法中发生异常,且方法不做处理,交给调用该方法的地方处理。

public class yichangchuli {
    public static void main(String [] args)throws IOException{
        BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
        String c1;
        int i=0;
        String []e=new String[10];
        while(i<10){
            c1=keyin.readLine();
            e[i]=c1;
            i++;
        }
    }
public class yichangchuli {
    public static void main(String [] args){
        BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
        String c1;
        int i=0;
        String []e=new String[10];
        while(i<10){
            c1=keyin.readLine();
            e[i]=c1;
            i++;
        }
    }

在这里插入图片描述

非嵌套捕获处理
假如try中发生异常,紧跟其后的catch根据try中抛出的异常类型对异常进行捕获,若相同则在catch中进行处理,没有则继续比较。最后必须执行Finally语句
嵌套捕获处理
虽然try-catch-finally最终捕获异常,但try中代码块中异常语句后面的语句可能会无法执行,这时可以利用嵌套进行解决。

算术异常

public class ExampleExecption{
    public stastic void main(String[]args){   int a,b,c;
    a=3;b=0;c=a/b;
    System.out.println(c);
    }       
}

空指针异常

public class yichangchuli{
    private stastic int[]x;
    public stastic void main(String []args)
    {
        System.out.println (x[0]);
    }
}

数组越界异常

public class yichangchuli{
    public static void main(String [] args){
        String foo=args[1];
        System.out.println(foo);

    }
}

在这里插入图片描述

自定义异常类

public class yichangchuli extends Exception {
    public yichangchuli(String msg) {
        super(msg);
    }

    static void throwone() throws yichangchuli {
        int a = 1;
        if (a == 1) {
            throw new yichangchuli("a为1");
        }
    }

    public static void main(String[] args) {
        try {
            throwone();
        } catch (yichangchuli e) {
            e.printStackTrace();
        }

    }
}

在这里插入图片描述

3.为什么使用异常处理机制

假如一个代码块有除法的运算,为了使程序正常运行,我们可以用if-else语句判断除数是否为零,然而当除法运算很多时,这种解决办法非常麻烦,其实这些异常都可归为除零异常,如果我们用异常类解决这个问题呢?当程序运行到出现除零异常的地方时,JVM根据异常的类型生成一个指定异常类的对象,如果后面的程序没有对异常的处理,即底层不处理,则交给调用该方法的地方(JVM)进行处理,而JVM的默认处理方式就是输出异常信息,而后中断程序的运行。如果后面有对异常的处理,比如try-catch-finally语句,在try语句中产生的异常类对象,会和紧跟在try语句之后的catch语句进行匹配,匹配成功则执行catch中的语句,接着执行fianlly语句,否则继续匹配,如果没有匹配成功,会在执行完finally语句之后交给JVM进行默认处理,并且程序中断。(也可以不中断,我们可以在catch或者fianlly语句中给与程序改错的机会,这样程序就不会因为异常而终止)

实现两个对象之间互发消息

class FighterPlane
{
   String name;
   int missileNum;   
   public FighterPlane(String _name,int _missileNum){
	    name = _name;
		missileNum = _missileNum;
   }
   public void fire(){
       if (missileNum>0){
          System.out.println("now fire a missile !");
		  missileNum -= 1; 
       }
       else{
          System.out.println("No missile left !");
       }
   }   
}

class A 
{
    FighterPlane fp;//数据成员是FighterPlane的引用,可以变更对象,灵活性更高
    public A(FighterPlane fpp){
       this.fp = fpp; //A对象中拥有了FighterPlane对象的引用
    }
    public void invoke(){
       //A中对象发送消息给FighterPlane的对象
       System.out.println(fp.name); 
    }
}
public class  Run{
   public static void main(String[] args)
   {  
      FighterPlane ftp = new FighterPlane("su35",10);
	//产生A对象,并将ftp对象引用作为参数传入
      A  a   = new A(ftp); 
      //发送消息,产生调用关系
      a.invoke();
   }
}

instanceof运用场景

java中,instanceof运算符的前一个操作符是一个引用变量,后一个操作数通常是一个类(可以是接口),用于判断前面的对象是否是后面的类,或者其子类、实现类的实例。如果是返回true,否则返回false。

组合与继承的区别以及适用场景

和继承相比较,组合有几大优点:

​ ①不破坏封装,整体类与局部类松耦合,彼此相对独立。若是继承,子类必须继承父类方法,限制较大;父类的改动会影响子类;

​ ②具有较好的扩展性。继承制在成员较多时可能形成多代层次,复杂且易出错,组合则没有这个缺点;

​ ③支持动态组合,整体对象可以选择不同的局部对象。因为类与类之间相对独立,组合也会比继承更加灵活,修改更加容易;

​ ④整体类可以对局部类包装形成新的接口;调用新方法不再受到继承中命名等诸多限制;

​ 继承也有一些优点,比如子类可以自动获得父类的接口,调用子类时不需要纠结方法命名,可以实现多态,代码显得更简洁。但明显劣势是大于优势的。继承中,父类内部对子类是公开的,如果导致父类发生了变化,全部子类都会改变,这导致代码的不安全;

​ 总之,在不必要应用到继承的情况下,应该优先用组合,因为更高效,更灵活。

String,StringBuffer常用API

public class text1
{
   public static void main(String[] args)
   {
String s="accdedcba" ;
System.out.println("字符串的长度为:"+s.length());
System.out.println("字符c第一次出现的位置:"+s.indexOf('c'));
System.out.println("字符c最后一次出现的位置:"+s.lastIndexOf('c'));
   }
}


  
        StringBuffer sb=new StringBuffer();
        StringBuffer s1=sb.append(4).append(false).append("haha");
        sb.insert(1,"qwe");
        System.out.println(sb==s1);
        System.out.println(sb);



 StringBuffer sb=new StringBuffer("abce");
        sb.replace(2,3,"nab");//包含头不包含尾
        sb.setCharAt(2,'q');
        System.out.println(sb.toString());



 StringBuffer sb=new StringBuffer("abce");
        sb.delete(0,sb.length());//清空缓冲区
        sb.deleteCharAt(2);
        System.out.println(sb.toString());

String,StringBuffer,Stringbuilder的共同点,区别

String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且浪费大量优先的内存空间。
StringBuffer是可变类,和线程安全的字符串操作类,任何对它指向的字符串的操作都不会产生新的对象。每个StringBuffer对象都有一定的缓冲区容量,当字符串大小没有超过容量时,不会分配新的容量,当字符串大小超过容量时,会自动增加容量 可变类,速度更快,多线程操作字符串,线程安全。
StringBuilder可变,线程不安全,是单线程操作字符串。

为什么不建议在for循环中使用"+"进行字符串拼接

因为每进行一次拼接,都需要创建一个新的String类对象,浪费了大量的空间,比较好的做法是,在for循环外部先将String转换成StringBuffer,循环内部调用append()方法进行拼接,循环完成后,再将StringBuffer转为String

编码与解码

编码:将Unicode转为本地字符集
解码:将本地字符集转为unicode字符

线程

volatile有什么作用?

假如有一个对象A里面有一个boolean变量a,值为true,现在有两个线程T1,T2访问变量a,T1把a改成了false后T2读取a,T2这时读到的值可能不是false,即T1修改a的这一操作,对T2是不可见的。发生的原因可能是,针对T2线程,为了提升性能,虚拟机把a变量置入了寄存器(即C语言中的寄存器变量),这样就会导致,无论T2读取多少次a,a的值始终为true,因为T2读取了寄存器而非内存中的值。声明了volatile或synchronized 后,就可以保证可见性,确保T2始终从内存中读取变量,T1始终在内存中修改变量。

/*
这个模拟程序一共分为三个时间,烧开水,洗茶杯,泡茶
烧开水的时候可以洗茶杯
必须烧完开水,洗完茶杯以后才能开始泡茶
 */

import java.util.Date;

public class Tea implements Runnable{
    static Date date = new Date();
    public static void main(String[] args) throws Exception{
        HeatUpWater h1 = new HeatUpWater();
        WashCup w1 = new WashCup();
        Tea m1 = new Tea();
        Thread t1 = new Thread(h1);
        Thread t2 = new Thread(w1);
        Thread t3 = new Thread(m1);
        try{
            t1.start();
            t2.start();
            t2.join();
            t1.join();
        }catch (Exception e){
            System.out.println("Error!");
        }
        t3.start();
    }

    public void run(){
        System.out.println(date+" 正在泡茶");
        try{
            Thread.sleep(1000);
        }catch (Exception e){

        }
    }


}


class HeatUpWater implements Runnable{
    static Date date = new Date();
    public void run(){
        int time = 10;
        while(time != 0){
            System.out.println(date+" 正在烧水");
            time--;
            try{
                Thread.sleep(1000);
            }catch (Exception e){
                System.out.println("Heat up water is in the Error!");
            }
        }
    }
}

class WashCup implements Runnable{
    static Date date = new Date();
    public void run(){
        int time = 5;
        while(time != 0){
            System.out.println(date+" 正在洗茶杯");
            time--;
            try{
                Thread.sleep(1000);
            }catch (Exception e){

            }
        }

    }
}

javaIO

java中流的分类

java中流可分为字节流和字符流,字节流以字节为基本单位,而字符流以字符为基本处理单位。字节流和字符流又可派生出一系列类。

InputStream和OutputStream的子类

字节流 InputStream/OutputStream(抽象类)
->子类 (文件流)FileInputStream /FileOutputStream(底层流,用来包装高级流)
->子类 (字节缓冲流)BufferedInputStream/BufferedOutputStream(文件复制)
InputStream fis=new FileInputStream(" “);
字节缓冲流 BufferedInputStream/BufferedOutputStream
在BufferedInputStream中包装一个InputStream
BufferedInputStream bis=new BufferedInputStream(new InputStream(” "));

字符流 Reader/Writer(抽象类)
->子类 InputStreamReader/OutputStreamWriter(底层流,用来包装高级流)
->子类 (字符缓冲流)BufferedReader/PrintWriter (内容读写)
字符流中包装了字节流
InputStream is=new FileInputStream("");
Reader isw= new InputStreamReader(is);

字符缓冲流 BufferedReader/PrintWriter
在BufferedReader中包装一个InputStreamReader
BufferedReader in= new BufferedReader(new InputStreamReader(" "));
ObjectInputStream / ObjectOutputStream ->操作对象,字节位单位

字节流和字符流的转换

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
 * InputSteramReader把字节流转换为字符流
 * 字节流转换为字符流
 */
public class ConvertInDemo {
 
	public static void main(String[] args) {
		
		InputStream is = System.in;
		//要想使用字符流的高效缓冲区来操作字节流需要转换
		BufferedReader br = new BufferedReader(new InputStreamReader(is));
		//定义要写入的文件流
		BufferedWriter bw = null;
		try {
			bw = new BufferedWriter(new FileWriter("c.txt"));
			
			
			
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		String line = null;
		try {
			while((line = br.readLine())!=null){
				if("exit".equals(line)){
					break;
				}
				bw.write(line);
				//换行
				bw.newLine();
				bw.flush();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(bw !=null){
				try {
					bw.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
	}
	
}

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
/**
 * OutputSteramWriter把字符流转换为字节流
 * 字符流转换为字节流
 */
public class ConvertOutDemo {
 
	public static void main(String[] args) throws IOException {
		BufferedReader br = null;
		BufferedWriter bw = null;
		try {
			br = new BufferedReader(new FileReader("c.txt"));
			//创建字符流向字节流转换的对象
			bw = new BufferedWriter(new OutputStreamWriter(System.out));
			String line = null;
			while((line = br.readLine())!=null){
				bw.write(line);
				bw.newLine();
				bw.flush();
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(bw != null){
				bw.close();
			}
			if(br != null){
				br.close();
			}
		}
		
	}
	
}

过滤流的作用

过滤流(filter stream)也称为包装流,是为某种目的过滤字节或字符的数据流。
基本输入流提供地读取方法只能用来读取字节或字符,而过滤器流能够读取整数值、双精度值或字符串,但需要一个过滤器类来包装输入流。
FilterInputStream 类和 FilterOutputStream 类分别是 DataInputStream 类和 DataOutputStream 类的父类,它们分别实现了 DataInput 和 DataOutput 接口,该接口定义了独立于具体机器的带格式的读写操作,从而可以实现对 Java 中的不同基本类型数据的读写。

对象的序列化和反序列化

(1)Java序列化是指把Java对象转换为字节序列的过程,而Java反序列化是指把字节序列恢复为Java对象的过程;

(2)**序列化:**对象序列化的最主要的用处就是在传递和保存对象的时候,保证对象的完整性和可传递性。序列化是把对象转换成有序字节流,以便在网络上传输或者保存在本地文件中。序列化后的字节流保存了Java对象的状态以及相关的描述信息。序列化机制的核心作用就是对象状态的保存与重建。

(3)**反序列化:**客户端从文件中或网络上获得序列化后的对象字节流后,根据字节流中所保存的对象状态及描述信息,通过反序列化重建对象。

实现Java对象序列化与反序列化的方法

对象序列化有如下三种方法:
1)若User类仅仅实现了Serializable接口,则可以按照以下方式进行序列化和反序列化
ObjectOutputStream采用默认的序列化方式,对User对象的非transient的实例变量进行序列化。ObjcetInputStream采用默认的反序列化方式,对对User对象的非transient的实例变量进行反序列化。

2)若User类仅仅实现了Serializable接口,并且还定义了readObject(ObjectInputStream in)和writeObject(ObjectOutputSteam out),则采用以下方式进行序列化与反序列化。
ObjectOutputStream调用User对象的writeObject(ObjectOutputStream out)的方法进行序列化。ObjectInputStream会调用User对象的readObject(ObjectInputStream in)的方法进行反序列化。

3)若User类实现了Externalnalizable接口,且User类必须实现readExternal(ObjectInput in)和writeExternal(ObjectOutput out)方法,则按照以下方式进行序列化与反序列化。
ObjectOutputStream调用User对象的writeExternal(ObjectOutput out))的方法进行序列化。
ObjectInputStream会调用User对象的readExternal(ObjectInput in)的方法进行反序列化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值