TwentyTwoDay-java File的常用方法、序列化与反序列化、 创建线程
1、java.io.File的常用方法
public static void main(String[] args) {
//创建一个File对象
File file=new File("D:\\word文档/file01");
//判断文件是否存在
System.out.println(file.exists());//false 不存在
//若不存在,以文件形式新建一个
/*if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
*/
//若不存在,以目录形式新建
/*if(!file.exists()){
file.mkdir();
}*/
//新建多重目录
File file1=new File("D:\\word文档/file01/A/B");
if(!file1.exists()){
file1.mkdirs();
}
//获取父文件的路径 返回String类型
String parentPath=file1.getParent();
System.out.println(parentPath);//D:\word文档\file01\A
//获取父文件的路径,返回File类型
File parentP=file1.getParentFile();
System.out.println(parentP);//D:\word文档\file01\A
//获取父文件的绝对路径
System.out.println(parentP.getAbsolutePath());//D:\word文档\file01\A
//获取文件的绝对路径
System.out.println(file1.getAbsolutePath());//D:\word文档\file01\A\B
//获取文件名
System.out.println("文件名:"+file1.getName());//文件名:B
//判断是不是一个文件
System.out.println(file1.isFile());//false
//判断是不是一个目录
System.out.println(file1.isDirectory());//true
//获取最后一次的修改时间
long l = file1.lastModified();//返回的是从1970年到现在的毫秒数
Date date=new Date(l);//转化成日期
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd hh:mm:ss SSS");//格式化日期
String dateTime = sdf.format(date);
System.out.println(dateTime);//2021-07-14 09:42:06 545
//获取文件大小
System.out.println(file1.length());//0 没放东西
}
*File类的File[] listFiles() 方法 返回当前目录下的所有子文件
public static void main(String[] args) {
File file=new File("D:/word文档");
File[] files = file.listFiles();
//遍历输出file里的子文件名
for (File file1 : files) {
System.out.println(file1.getAbsolutePath());
}
}
2、序列化与反序列化
序列化serialize java对象存储到文件中,将Java对象的状态保存下来的过程(ObjectOutputStream)
反序列化Deserialize 将硬盘上的数据重新恢复到内存当中,恢复成Java对象(ObjectInputStream)
需要序列化与反序列化的对象必须实现Serializable接口 这个接口是一个标志性接口,无任何方法和属性,不然会报NotSerializableException错,不支持序列化
这个接口的作用? 起到标识的作用,java虚拟机看到这个类实现了这个接口,可能会对这个类进行特殊待遇。会对这个类自动形成一个序列化版本号。
//student类
public class student implements Serializable {
int sno;
String sName;
public student(int sno, String sName) {
this.sno = sno;
this.sName = sName;
}
public int getSno() {
return sno;
}
public void setSno(int sno) {
this.sno = sno;
}
public String getsName() {
return sName;
}
public void setsName(String sName) {
this.sName = sName;
}
@Override
public String toString() {
return "student{" +
"sno=" + sno +
", sName='" + sName + '\'' +
'}';
}
}
//序列化student
public static void main(String[] args) throws Exception {
student stu=new student(18010,"zhangsan");
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("student"));
//序列化
oos.writeObject(stu);
oos.flush();
oos.close();
}
序列化结果 生成一个保存student对象的文件
//反序列化student
public static void main(String[] args) throws Exception {
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("student"));
//反序列化
Object o = ois.readObject();
//调用student的toString方法
System.out.println(o);
ois.close();
}
反序列运行结果
student{sno=18010, sName='zhangsan'}
3、序列化多个对象
//User类
public class User implements Serializable {
int uno;
String name;
public User(int uno, String name) {
this.uno = uno;
this.name = name;
}
public int getUno() {
return uno;
}
public void setUno(int uno) {
this.uno = uno;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"uno=" + uno +
", name='" + name + '\'' +
'}';
}
}
//序列化User
以把多个对象放进一个List集合中,序列化集合 注意:User与List集合都必须实现java.io.Serializable
public static void main(String[] args) throws Exception {
List<User> Users=new ArrayList<>();
//把User对象放进List集合中
Users.add(new User(12,"mary"));
Users.add(new User(13,"jack"));
Users.add(new User(14,"dawei"));
ObjectOutputStream oos=new ObjectOutputStream(new FileOutputStream("user"));
oos.writeObject(Users);
oos.flush();
oos.close();
}
运行结果 生成保存User对象的文件
//反序列化User
public static void main(String[] args) throws Exception{
ObjectInputStream ois=new ObjectInputStream(new FileInputStream("user"));
Object o = ois.readObject();
// System.out.println(o instanceof List); true
List<User> UserList=(List<User>)o;
for (User user : UserList) {
System.out.println(user);
}
ois.close();
}
运行结果
User{uno=12, name='mary'}
User{uno=13, name='jack'}
User{uno=14, name='dawei'}
注意:有一个transient关键字,表示游离的,不参与序列化(transient int uno;)反序列化后运行结果为 User{uno=0, name='mary'}
4、序列化版本号的用途?
java语言中采用什么机制来区分类的?
第一:首先对比类名,类名不一样,就是两个类
第二:类名一样,则通过序列化版本号进行比较
当有两个类名相同的类,都实现了Serializable接口,则在编译的时候,两个类有不同的序列化版本号(这是序列化版本号的优点)
缺点:一旦代码确定后,不能进行后续修改,只要修改,必然重新编译,此时会生成一个新的序列化版本号。
综上所述:序列化版本号需要固定不变,故手写!如在student类里加上”private static final long serialVersionUID = 7826354836987L;“
5、IO+Properties的联合使用
设计理念: 经常改变的数据,可以单独写到一个文件里,使用程序动态读取
将来只需要改变文件的内容,java代码不需要改变,不需要重新编译,服务器也不需要重新启动
类似于这样的文件称为配置文件。
当配置文件内容格式为:
key1=123
key2=890 的时候,我们把这种配置文件叫做属性配置文件
java规范中有要求:属性配置文件建议以.properties结尾,但是不必须。
Properties是专门存放属性配置文件内容的一个类
public static void main(String[] args) throws Exception {
/*
把文件tempfile02里的数据传入Map集合
*/
//创建一个输入流对象
FileReader file=new FileReader("java基础语法/tempfile02");
//创建一个集合
Properties properties=new Properties();
properties.load(file);
String user = properties.getProperty("user");
System.out.println(user);//root
}
6、线程的理解
进程:就是一个应用程序(两个进程内存独立不共享)
线程就是一个进程中的执行场景/执行单元(两个线程堆内存和方法区共享,栈内存独立,一个线程一个栈,多线程并发机制,目的提高程序的处理效率 )
思考:使用多线程机制,main方法结束,是不是有可能程序不会结束。
main结束只是主线程结束,其它栈并未结束。
多线程并发:线程之间互不影响,各自执行各自的。
对于单核的cpu来说,可以做到多线程并发吗?不能够,但是可以做到给人一种多线程并发的感觉。其实它是多个线程频繁切换执行的,速度很快,但在某一时间点只能处理一件事情。
7、线程状态图(图为b站老师所画)

8、实现线程的第一种方式:
编写一个类,直接继承Thread,重写run()方法
怎样创建线程对象?new线程
怎样启动线程? 调用线程对象的start()方法
//编写一个MyThread类
class MyThread extends Thread{
@Override
public void run() {
//编写程序,这段程序运行在分支栈中
for (int i = 0; i < 100; i++) {
System.out.println("分支线程-->"+i);
}
}
}
public static void main(String[] args) {
//新建一个分支线程对象
MyThread myTread=new MyThread();
//若直接调用run方法:myTread.run(),则没有开辟新的栈空间只有一个主线程(这种方式就是单线程)
//启动分支线程
myTread.start();//作用:在Jvm中开辟一个新的栈空间,任务完成之后,瞬间结束,启动成功后自动调用run方法
//run与main方法都在底部,run在分支栈底部,main在主栈底部
//主线程代码运行
for(int i=0;i<100;i++){
System.out.println("主线程--》"+i);
}
}
9、第二种方式
编写一个类实现java.lang.Runnable接口
接口的方式比继承的方式好,因为实现了接口还能继承其他的类
//创建一个MyRunnable类
class MyRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("分支线程-->"+i);
}
}
}
//线程的实现
public static void main(String[] args) {
/* //创建一个可运行的对象
MyRunnable myRunnable=new MyRunnable();
//把可运行对象封装为线程对象
Thread tread=new Thread(myRunnable);
把两行合并
*/
Thread thread=new Thread(new MyRunnable());
//启动分支线程
thread.start();
for(int i=0;i<100;i++){
System.out.println("主线程--》"+i);
}
}
注:可以用内部类的方式
public static void main(String[] args) {
Thread t=new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("分支"+i);
}
}
});
t.start();
for (int i = 0; i < 100; i++) {
System.out.println("主线程"+i);
}
}
10、
1>、怎样获取当前线程对象? 使用static Thread currentThread()静态方法
2>、获取线程对象的名字 :String name=t.getName();
3>、修改线程对象的名字:t.setName("修改后的名字");
4>、当线程没有设置名字的时候 默认 Thread-0,Thread-1...
//创建MyThread类
class MyThread extends Thread{
@Override
public void run() {
//获取当前线程
Thread currentThread=Thread.currentThread();
System.out.println("当前线程的名字:"+currentThread.getName());//当前线程的名字:t
}
}
//线程的实现
public static void main(String[] args) {
//获取当前线程的名字(当前线程在现在是主线程)
Thread currentThread=Thread.currentThread();
System.out.println(currentThread.getName());//main
MyThread myThread=new MyThread();
//修改线程的名字
myThread.setName("t");
//获取线程的名字
String name=myThread.getName();
System.out.println(name);//t
myThread.start();
}
浙公网安备 33010602011771号