JAVA基础笔记
1.java语言的概述
1.1.简介
发明人 James·Gosling(詹姆斯·高斯林),诞生于1995年5月23日。
1996年推出jdk1.0,1998年jdk2.0,java更名为java2(原型:Oak)。
原本属于sum公司,2010sum公司被Oracle公司收购。
1.2.定义:
Java是一种可以撰写跨平台应用软件的面向对象的程序设计语言。
Java 技术具有卓越的通用性、高效性、平台移植性和安全性。
1.3.主要特点:
- 简单,安全
- 完全面向对象
- 可移植(平台无关性)
- 多线程:一个程序里可执行多个小任务
- 解释的:java解释器(运行系统)能直接运行目标代码指令
- 分布式:包括支持HTTP和FTP等基于TCP/IP协议的类库
- 动态:Java程序需要的类能动态的被载入运行环境,也可通过网络载入
- 健壮、结构中立、类装载、高性能、开源
1.4.java两种核心机制:
**一、JAVA虚拟机(JVM)**
1. java虚拟机可也理解成一个以字节码为机器指令的CPU。
2. 对于不同的运行平台,有不同的虚拟机。
3. java虚拟机机制屏蔽了底层运行平台的差别,能够很好的实现跨平台。
二、垃圾收集(Garbage Collection)
Java的内存管理实际上就是对象的管理,其中包括对象的分配和释放。
2.环境变量配置
JAVA_HOME:jdk路径
Path:要把jdk的bin目录路径,添加到path变量
3.八种基本数据类型
3.1.基本数据类型
序号 | 数据类型 | 位数 | 默认值 | 取值范围 | 举例说明 |
---|---|---|---|---|---|
1 | byte(位) | 8 | 0 | -2^7 - 2^7-1 | byte b = 10; |
2 | short(短整数) | 16 | 0 | -2^15 - 2^15-1 | short s = 10; |
3 | int(整数) | 32 | 0 | -2^31 - 2^31-1 | int i = 10; |
4 | long(长整数) | 64 | 0 | -2^63 - 2^63-1 | long l = 10l; |
5 | float(单精度) | 32 | 0.0 | -2^31 - 2^31-1 | float f = 10.0f; |
6 | double(双精度) | 64 | 0.0 | -2^63 - 2^63-1 | double d = 10.0d; |
7 | char(字符) | 16 | 空 | 0 - 2^16-1 | char c = ‘c’; |
8 | boolean(布尔值) | 8 | false | true、false | boolean b = true; |
3.2.引用数据类型
- 类 Class
- 接口 Interface
- 数组 Array
3.3.基本数据类型的运算规则
1. 计算结果的数据类型与运算中的最大类型一致
2. byte,short,char三种比int小的整数,计算时会自动转成int。
3.4.基本数据类型的转换
数字类型之间可以互相转换,从小到大自动转换,从大到小需要强制转型。
3.5.运算符
- && :逻辑与(短路与),两边同为真结果才为真,短路与:左边是假,右边忽略不执行。
- & :不管左边结果是什么都要执行右边(&的左右两边都要参与运算)。
- || :逻辑或(短路或),两边只要有一个真结果就是真,短路或:左边是真,右边忽略不执行。
4.流程控制语句
4.1.swith语句
从成立的case 无条件穿透所有的case包括default直到结束或者遇到break中断跳出循环
switch (判断语句){
case 1:
执行代码
break;
...
default:
执行代码
}
4.2.for循环
for(变量赋值;执行条件;变量更改){
执行代码
}
4.3.for-each增强for循环
数组遍历、集合迭代遍历的语法简化
for(String s:arr(数组名)){
处理s
}
for(String s:list(集合名)){
处理s
}
5.数组(Array)
数组用来存放一组数据的数据结构,数组是相同数据类型组成的集合,数组中的元素按线性顺序排序,索引从0开始。
5.1.数组的创建
创建数组的第一种方法
int(数据类型) []arr=new int[5(数组长度)];
创建数组的第二种方法
int(数据类型) []arr={1,2,3,4,5(数组元素)};
5.2.数据的长度属性 arr.length
- 数组一旦创立,长度不可变。
- 最大索引值为 arr.length-1。
- 允许长度为0的数组。
5.3.二维数组
二位数组的创建
int[][] arr=new int[3][2];
表示长度为3,内部3个数组长度为2,一共有4个数组,内部数组默认值是0.
int[][] arr=new int[3][];
表示只创建一个外围数组长度3,3个位置都是null,之后可以新建数组放入内部
5.4.Arrays 数组常见工具类
- Arrays.toString(数组) 把数组数据连接成字符串。
- Arrays.sort(数组) 数组升序排序。
- Arrays.copyof(数组,长度) 复制数组成一个指定长度的新数组。
- Arrays.equals(数组,数组)比较两个数组元素是否相等,相等则返回true。
- Arrays.toString(数组)返回指定数组内容的字符串表示形式。
6.面向对象思想
6.1.面向对象的三大特征:
- 封装:核心思想就是“隐藏细节”、“数据安全”,将对象不需要让外界访问的成员变量和方法私有化,只提供符合开发者意愿的公有方法来访问这些数据和逻辑,保证了数据的安全和程序的稳定。
- 继承:子类可以继承父类的属性和方法,并对其进行拓展。
- 多态:同一种类型的对象执行同一个方法时可以表现出不同的行为特征。通过继承的上下转型、接口的回调以及方法的重写和重载可以实现多态。
一、封装
6.2.类:类中定义对象的属性数据(成员变量),方法(成员方法)
class Student(类名){
//成员变量
int id;
String name,
int age;
//成员方法
public void Study(){
System.out.println("学习")
}
}
6.3.创建对象:从模板中创建具体的实例
public class Test{
public static void main(String[] args){
Student s(对象名)=new Student();
}
}
6.4.构造方法:新建实例对象时,立即执行的一个特殊方法,构造方法一般用来给属性赋值
class Cat(){
String name;
int age;
//构造方法
public Cat(){
}
}
注意:
- 一个类中必须要有构造方法,如果自己没定义,系统会自动添加一个无参构造方法。
- 如果我们自己定义过有参数的构造方法,推荐再定义一个无参构造方法。
- 构造方法必须和类名相同,并且没有返回值类型。
6.5.构造方法的重载
一个类中可以定义多个参数不同参数的构造方法,是方法重载的一种体现。
class Dog{
String name;
int age;
//构造方法
public Dog(){
}
public Dog(String name,int age){
}
public Dog(String food){
}
}
应用:在定义类时给成员变量赋值private,并提供get和set方法用于外部访问,这样可以提高数据的安全性。
6.5.private关键字
private可以修饰成员变量和成员方法, 被修饰的成员只能在本类中被访问
public class Animals{
private String name,age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
6.6.this关键字
this关键字主要有三个作用:
- this调用本类中的属性,也就是类中的成员变量。
- this调用本类中的其他方法;
- this调用本类中的其他构造方法, 调用时要放在构造方法的首行。
调用成员变量:
class Student{
String name;
public void SetName(String name){
this.name=name;
}
}
首先创建了一个类名叫 Student,有成员变量name和成员方法SetName(String name),由于成员方法的形参名称和成员变量相同,所以可以使用this关键字来调用本类的成员变量。
调用成员方法:
public class Test{
public static void main(String[] args){
Student s=new Student();
s.setName("小明");
s.TestName();
}
}
class Student{
String name;
public void setName(String name){
this.name=name;
}
public void TestName(){
this.setName(name);
System.out.println("TestName:"+this.name);
}
}
运行结果为:
TestName:小明
调用构造方法:
class Student(){
String name;
//定义一个带形式参数的构造方法
public Student(String name){
}
//定义一个构造方法
public Student(){
this("haha");
}
}
``
注意:
- 只能在构造方法中通过this来调用其他构造方法,普通方法中不能使用。
- 通过this调用其他构造方法必须放在构造方法的第一行。
- 不能与super关键字同时出现在一个构造方法中。
二、继承(extends)
java的继承是单继承多实现,只能继承一个父类(如果不继承其他类,则默认基础Object类),但可以实现多个接口。
注意:不能继承的有:构造方法, 私有成员。
2.方法重写:override
class Amimals{
public void eat(){
System.out.println("吃东西");
}
}
class Cat extends Animals{
@override
public void eat(){
System.out.println("猫吃鱼");
}
}
在子类中重新定义父类中的方法(只能在子类重写),方法名相同,参数个数、参数类型、返回值类型都必须相同。
3.父类的构造方法
- 新建子类对象时会先新建父类对象,也会先执行父类的构造方法
- 默认执行父类的无参构造,默认隐含调用super();
- new 类名 ()默认执行父类的无参构造
- new 类名 (…)默认执行父类的有参构造
- 手动调用父类的有参构造,super(参数):父类没有无参构造时必须手动调用
4.super关键字
- super.function()方法重写时,调用父类中同一个方法的代码
- super(参数)调用父类的构造方法, 默认调用父类的无参构造,手动调用有参构造super()必须是在首行代码
注意:super关键字不能再静态方法中使用
5.接口(Interface)
接口是一个标准,用来解绝程序的耦合度。
- 接口只能定义常量
- 接口只能定义抽象方法
- 接口只能继承接口,不能继承普通类 抽象类
- 接口没有构造方法
public Interface A{
int num=10; //定义常量
public static void show{
//定义抽象方法
}
}
注意:
- 在接口中定义常量时,可以不用手动输入final static修饰,编译器会自动加上。
- 在接口中定义抽象方法时,也可以省略abstract关键字。
三、多态
一个对象具有多种形态的表现,多态的前提是必须要有继承关系
多态的体现为:父类引用变量可以指向子类对象
注意:在使用多态后的父类引用父类变量调用方法时,会调用子类重写后的方法。
1.多态的定义与使用格式
父类类型 变量名 = new 子类类型();
2.多态中成员的特点
class Father{
int number=10;
public void show(){
System.out.println("我是父类的方法")
}
}
class Son extends Father{
int number=20;
@override
public void show(){
System.out.println("我是子类的方法")
}
}
Father f=new Son();
System.out.println(f.number)
/*
运行结果是:10
f是父类的对象实例,所以只能取到父类中的值
多态成员变量:编译运行看左边
*/
Father f2=new Son();
System.out.println(f2.show);
/*
运行结果是:“我是子类的方法”
f2的实际类型是Son,所以调用的是子类重写后的方法
多态成员方法:编译看左边,运行看右边
*/
3.instanceof关键字
用来判断某个对象是否属于某种数据类型
注意:返回值类型为布尔类型(boolean)
Father f=new Son();
Father f2=new Son();
if(f instanceof f2){
System.out.println("f是Father的类型");
}else{
System.out.println("f2是Son的类型");
}
4.多态的转型
多态的转型分为向上转型和向下转型两种
1.向上转型:多态本身就是向上转型的过程
使用格式:父类类型 变量名=new 子类类型();
使用场景:当不需要面对子类类型时,直接通过父类的功能就能完成想要的操作
2.向下转型:一个已经向上转型的子类对象可以使用强制类型转换的格式,将父类引用类型转为子类引用类型
使用格式:子类类型 变量名=(子类类型)父类类型的变量;
使用场景:当要使用子类特有功能时
7.String 类
String类在java.lang包中,java使用String类创建一个字符串变量,字符串变量属于对象。
String字符串变量的创建:
声明和初始化:String 变量名=“初始值”;
String str="hello,world!";
String 常用的方法:
1、int length();语法:字符串变量名.length;返回值为int类型,得到一个字符串的字符个数。
String str="good";
int length=str.length;
System.out.println(l);
//运行结果为:4
2、char charAt(值);语法:字符串名.charAt(值);返回值为char类型,从字符串中取出指定位置的字符。
String str="你好世界";
char c=str.charAt(2);
System.out.println("指定字符为:"+c);
//运行结果为:指定字符为: 世
3、char toCharArray();语法:字符串名.toCharArray();返回值为char数组类型,将字符串变成一个字符数组。
String str="java";
char[] c=str.toCharArray();
for(int i=0;i<c.length;i++){
System.out.println("转为数组输出:"+c[i]);
}
/*
运行结果为:
转为数组输出:j
转为数组输出:a
转为数组输出:v
转为数组输出:a
*/
4、int indexOf(“字符”);语法:字符串名.indexOf(“字符”,“值”);查找数组中一指定的字符串是否存在,返回的是字符串的位置,如果不存在,则返回-1;
int lastIndexOf(“字符”)得到指定内容最后一次出现的索引值。
String str="早睡早起身体好";
int index1=str.indexOf("睡"); //查找字符"睡"的位置
int index2=str.indexOf("好",2); //查找字符"好"的位置,从第3个开始查找
int index3=str.lastIndexOf("早");//查找字符"早"最后一次出现的索引值
System.out.println("睡的位置为:"+index1);
System.out.println("好的位置为:"+index2);
System.out.println("早最后出现的位置为:"+index3);
/*运行结果:
睡的位置为:1
好的位置为:6
早最后出现的位置为:2
*/
5、toUpperCase();toLowerCase();字符串大小写的转换。
String str="hello,world";
String str2="HELLO,WORLD";
System.out.println("将字符串转换成大写为:"+str.toUpperCase());
System.out.println("将字符串转换成小写为:"+str2.toLowerCase());
/*
运行结果为:
将字符串转换成大写为:HELLO,WORLD
将字符串转换成小写为:hello,world
*/
6、String[ ] split(“字符”) ;根据给定的正则表达式的匹配来拆分此字符串,形成一个新的String数组。
String str="good:well:nice";
String[] arr=str.split(":");
for(int i=0;i<arr.length;i++){
System.out.println(arr[i]);
}
/*
运行结果:
{"good","well","nice"}
*/
7、boolean equals(Object anObject)语法:字符串变量名.equals(字符串变量名);比较两个字符串是否相等,相等返回true,不相等返回false;
String str="hello";
String str2="world";
if(str.equals(str2)){
System.out.println("这两个字符串相等");
}else{
System.out.println("这两个字符串不相等");
}
/*
运行结果:
这两个字符串不相等
*/
8、trim();去掉字符串左右的空格。
String str=" 哈哈哈 ";
System.out.println("去掉字符串左右空格后:"+str.trim());
/*
运行结果:
去掉字符串左右空格后:哈哈哈
*/
9、String substring(int startIndex,int endIndex);截取字符串。
String str="123456789";
System.out.println("截取后的字符串为:"+str.substring(0,3)) //截取0-3个位置内容,不包含3
System.out.println("截取后的字符串为:"+str.substring(2)) //从第3个位置开始截取 包含3
/*
运行结果为:
截取后的字符串为:123
截取后的字符串为:3456789
*/
10、boolean contais(String)判断一个字符串里是否包含指定的内容,有返回true,没有返回false;
String str="helloworld";
String str2="world";
if(str.contains(sr2)){
System.out.println("str中包含world");
}else{
System.out.println("不包含");
}
/*
运行结果:
str中包含world
*
12、boolean startsWith(String)判断此字符串是否以指定的前缀开始,是返回true,不是则返回false。
String str="helloworld";
String str2="he";
if(str.startWith(sr2)){
System.out.println("str字符串中是以he前缀开头");
}else{
System.out.println("str字符串不是以he前缀开头");
}
/*
运行结果:
str字符串中是以he前缀开头
*/
13、boolean endsWith(String)判断此字符串是否以指定的后缀结束,是返回true,不是则返回false。
String str="helloworld";
String str2="ld";
if(str.endsWith(sr2)){
System.out.println("str字符串中是以ld后缀结束");
}else{
System.out.println("str字符串不是以ld后缀结束");
}
/*
运行结果:
str字符串中是以ld后缀结束
*/
8.static关键字
在类中,用static关键字声明的成员变量为静态成员变量,也成为类变量,同类一起加载。类变量的声明周期和类相同。static关键字也能用来修饰方法,静态方法不依赖于任何对象就可以直接访问。
注意:
- static修饰的成员变量和方法,从属于类。
- 普通变量和方法从属于对象。
- 静态方法不能调用非静态成员和非静态成员方法,否则编译会报错。
class StaticTest{
private static String name="小明";
private String address="成都";
public StaticTest(){
}
public void test1(){
System.out.println(name);
System.out.println(address);
test2();
}
public static void test2(){
System.out.println(name);
System.out.println(address);
test1();
}
}
- 因为address是非静态的成员变量,所以 test2() 调用时会报错。
- 静态方法 test()2 调用非静态方法 test1() 编译失败。这是因为编译器无法预知在非静态成员方法test1() 中是否访问了非静态成员变量,所以也禁止了在静态方法中调用非静态成员方法。
9.Object类
如果一个类不继承其他类,则默认继承Object类
Object常用方法
1、toString()获得一个对象的字符串表示。
2、Object中的默认实现是:“类名@地址”可在子类中重写toString方法。
3、equals()当前对象与参与对象比较是否相等。
4、a.equals(b) Object中默认实现是比较内存地址
10.正则表达式
一般用来判断用户的输入内容是否符合格式要求
- matches()字符串的方法,用来判断是否匹配
if(str.matches(regex)){
}
- split(正则):用匹配的子串来拆分字符串
String str="aaa,bbb,ccc";
String[] arr=s.split(",");
/*
运行结果:
aaa bbb ccc
*/
- replace(正则,子串)替换所有匹配的子串
11.基本类型的包装类
- byte —— Byte
- short —— Short
- int —— Integer
- long —— Long
- float —— Float
- double —— Double
- char —— Character
- boolean —— Boolean
12.抽象类(abstract)
抽象类不能创建实例,主要作用是被用来继承。抽象方法没有代码,只有方法的定义。
abstract class Animlas{
public abstract void eat(){
System.out.println("吃东西")
}
}
注意:抽象方法作为通用方法,需要在父类中定义,要求子类必须实现这个方法。
抽象类的作用:
- 抽象类可以有自己的构造方法
- 抽象类可以有具体的方法
- 抽象类不能使用new关键字来创建实例
- 抽象类可以定义实例变量和静态变量以及常亮
- 抽象类可以在继承抽象类,也可以继承普通的类
13.final关键字
在java中,final关键字可以用来修饰类、方法和变量(包括成员变量和局部变量)
1、修饰类
当使用final修饰一个类时,表示这个类不能被继承
2、修饰方法
当使用final修饰一个方法时,表示这个方法不能被重写
3、修饰变量
1.final修饰变量表示常量,只能被赋值一次,赋值后值不再可以被改变。
2.final修饰一个成员变量(属性),必须要显示初始化。有两种初始化方式,一种是在变量声明时候初始化。另一种是声明变量时不赋初值,但是要在这个变量所在的类的所有构造函数中对这个变量赋初值。
14.异常
1、捕获异常
使用 try 和 catch 关键字可以捕获异常,try/cath 代码块放在异常可能会发生在的地方
try{
//可能会出现异常的代码
}catch(Exception e){
//解决异常的代码
}
catch 关键字要包含捕获异常类型的声明
2、throws和thorw 关键字
如果一个方法没有捕获到一个检查性异常,那么该方法必须要使用throws关键字来声明,throws关键字要放再方法签名的尾部
也可以使用 thorw 关键字手动抛出一个异常,类似return;当程序出现逻辑错误,不自动创建并抛出异常,可以手动判断逻辑错误,手动创建异常对象并抛出。底层的异常往上层抛,在上层处理。
import java.io.*;
public class className
{
public void deposit(double amount) throws RemoteException
{
// Method implementation
throw new RemoteException();
}
//Remainder of class definition
}
15.线程
线程是在进程内部,并行执行的任务
创建线程的两种方式
-
继承 Thread类
编写Thread的子类,并重写 run()方法。
public class MyThread extends Thread{ @override public void run(){ for(int i=0;i<10;i++) { System.out.println(Thread.currentThread()+":"+i); } } public static void main(String[] args){ MyThread t=new MyThread(); t.start(); } }
-
实现 Runnable接口(推荐此方法)
public class MyThread implements Runnable{
public static int count=20;
public void run() {
while(count>0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"-当前剩余票数:"+count--);
}
}
public static void main(String[] args) {
MyThread Thread1=new MyThread();
Thread mThread1=new Thread(Thread1,"线程1");
Thread mThread2=new Thread(Thread1,"线程2");
Thread mThread3=new Thread(Thread1,"线程3");
mThread1.start();
mThread2.start();
myThread3.start();
}
继承Thread类和实现Runnable接口的区别
- 实现Runnable接口避免多继承的局限
- 实现Runnable接口可以更好的体现共享的概念
线程安全问题
出现线程安全问题的根本原因:
- 存在两个或两个以上的线程对象共享同一个资源
- 多线程操作共享资源代码有多个语句
线程安全问题的解决方案(两个方法)
方法一:同步代码块
格式:synchronize(锁对象){
//需要被同步的代码
}
注意:
- 锁对象可以是任意一个对象
- 锁对象必须是多线程共享的一个资源
例子:窗口售票
class SaleTicket extends Thread{
static int num = 50;//票数
public SaleTicket(String name) {
super(name);
}
@Override
public void run() {
while(true){
//同步代码块
synchronized ("锁") {
if(num>0){
System.out.println(Thread.currentThread().getName()+"售出了第"+num+"号票");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
num--;
}else{
System.out.println("票已经卖完了!");
break;
}
}
}
}
}
public class Demo4 {
public static void main(String[] args) {
//创建三个线程对象,模拟三个窗口
SaleTicket thread1 = new SaleTicket("窗口1");
SaleTicket thread2 = new SaleTicket("窗口2");
SaleTicket thread3 = new SaleTicket("窗口3");
//开启线程售票
thread1.start();
thread2.start();
thread3.start();
}
}
方法二:同步函数(同步函数就是使用synchronized修饰一个函数)
注意:如果函数是一个非静态的同步函数,那么锁对象是this对象
public class Ticket implements Runnable{
private int num=50;
@Override
public void run() {
while(true){
ticket();
}
}
//同步方法,默认有锁对象,锁对象是它本身
private synchronized void ticket(){
if (tickets>0){
try {
//线程休眠50ms
Thread.sleep(50);
System.out.println(Thread.currentThread().getName()+"...剩余票数:"+--tickets);
}catch (Exception e){
e.printStackTrace();
}
}else {
return;
}
}
}
16、集合
用来存放一些数据的数据结构
为什么要用集合?
数组的缺点:长度固定;访问方式单一只能通过下表访问;前面增删数据操作繁琐。
常用集合介绍
- Collection是对象集合,Collection有两个子接口,分别是List(有序、可重复)和Set(无序、不可重复)。
- ArrayList、Vector、LinkedList是List的实现类。
注意:ArrayList是线程不安全的,Vector是线程安全的,这两个类底层都是由数组实现的
- LinkedList是线程不安全的,底层是由链表实现的。
- Map是键值对集合
ArrayList
数组列表,封装了一个数组,及其操作代码和更方便的方法。
常用方法:
- add(数据)——添加数据到集合当中
- get(int i)——返回指定索引的数据
- remove(int i)——移除指定索引位置的数据,并返回
- remove(数据)——找到第一个相等的数据,找到后移除并返回true,找不到则返回false
- size()——集合中元素的数量
- iterator()——迭代器
LinkedList——双向链表
LinkedList两端数据操作方法(效率高):
addFirst(数据);addLast(数据);getFirst();getLast();removeFirst();removeLast()
HashMap
存放键值对数据,用键来快速定位数据,来提取键对应的值。键:不重复、无序的。
常用方法:
1. put(key,value)放入键值对数据,重复的键会覆盖旧值
2. get(key)获得键对应的值,如果键不存在,则返回null
3. remove(key)移除键值对数据,返回被移除的值
4. size()键值对的数量
17、IO流
文件、字符操作流
File
封装一个磁盘路径字符串 ,提供了一组对文件、文件夹操作的方法,可以封装文件夹路径、文件路径、不存在的路径。
常用方法:
- getName()——获取文件名
- getpatrent()——获取父目录
- getAbsolutePath()——完整路径
- length()——文件字节量,对文件夹无效,会返回假数据
- isFile()——判断是否是文件
- isDirectory()——是否是文件夹
- cteateNewFile()——新建文件,文件已存在不会新建,返回false
- mkdirs()——逐层创建多层文件夹
- delete()——删除文件、空目录
InputStream,OutputStream
字节流的抽象父类
常用方法:
- write(int b) 只输出int四个字节
- write(byte[], start, length) 输出byte[] 数组
- read() 读取一个字节值
- read(byte[] buff) 按数组的长度,读取一批字节值,存放到指定的数组中,并返回这一批的字节数量,读取结束后,再读取会返回 -1。
FileInputStream,FileOutputStream——文件流
ObjectInputStream,ObjectOutputStream —对象序列化、反序列化。
序列化是把一个对象的信息,按固定的字节格式,变成一串字节序列输出。
常用方法:
- writeObject(Object obj)——把对象变成一串字节序列输出
- readObject()——读取序列化数据,反序列化恢复对象
- Serializable接口——被序列化的对象, 必须实现Serializable接口
不被序列化的变量:
- static——属于类,不随对象被序列化输出
- transient——临时,只在程序运行期间,在内存中存在,不会被序列化持久保存