JavaSE面试题之基本IO流及面试官写了个双冒号考试答案[图]

一、JavaSE面试题之基本IO流
今天这篇是JavaSE系列的第十四篇,主要总结了Java中的IO流的问题,IO流分为两篇来讲,这篇是第一篇,主要是基本IO流,第二篇主要为网络IO流,在后续,会沿着第一篇开篇的知识线路一直总结下去,做到日更!如果我能做到百日百更,希望你也可以跟着百日百刷,一百天养成一个好习惯。
Q:
什么是IO流?
它是一种数据的流从源头流到目的地。比如文件拷贝,输入流和输出流都包括了。输入流从文件中读取数据存储到进程(process)中,输出流从进程中读取数据然后写入到目标文件。

JavaSE面试题之基本IO流及面试官写了个双冒号考试答案[图]

Q:
Java中有几种类型的流?
按照流的方向:
输入流(inputStream)
输出流(outputStream)。
按照实现功能分:
节点流(可以从或向一个特定的地方(节点)读写数据。如FileReader)
处理流(是对一个已存在的流的连接和封装,通过所封装的流的功能调用实现数据读写。如BufferedReader。处理流的构造方法总是要带一个其他的流对象做参数。一个流对象经过其他流的多次包装,称为流的链接。)
按照处理数据的单位:
字节流
字符流
字节流继承于InputStream和OutputStream
字符流继承于InputStreamReader和OutputStreamWriter
字符流.png
字节流.png
Q:
字节流和字符流的区别?
字节流在JDK1.0中就被引进了,用于操作包含ASCII字符的文件。JAVA也支持其他的字符如Unicode,为了读取包含Unicode字符的文件,JAVA语言设计者在JDK1.1中引入了字符流。ASCII作为Unicode的子集,对于英语字符的文件,可以可以使用字节流也可以使用字符流。
Q:
字节流有了为什么还要有字符流?
字符流是由Java虚拟机将字节转换得到的,问题就出在这个过程还算是非常耗时,并且,如果我们不知道编码类型就很容易出现乱码问题。所以,I/O流就干脆提供了一个直接操作字符的接口,方便我们平时对字符进行流操作。如果音频文件、图片等媒体文件用字节流比较好,如果涉及到字符的话使用字符流比较好。
Q:
FileInputStream和FileOutputStream是什么?
这是在拷贝文件操作的时候,经常用到的两个类。在处理小文件的时候,它们性能表现还不错,在大文件的时候,最好使用BufferedInputStream(或BufferedReader)和BufferedOutputStream(或BufferedWriter)
Q:
Files的常用方法都有哪些?
Files.size():查看文件个数。
Files.read():读取文件。
Files.write():写入文件。
Files.exists():检测文件路径是否存在。
Files.createFile():创建文件。
Files.createDirectory():创建文件夹。
Files.delete():删除一个文件或目录。
Files.copy():复制文件。
Files.move():移动文件。
Q:
什么是java序列化,如何实现java序列化?
序列化:
是一种用来处理对象流的机制,所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作,也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。
序列化的实现:
将需要被序列化的类实现
Serializable

接口,该接口没有需要实现的方法,implementsSerializable只是为了标注该对象是可被序列化的,然后使用一个输出流(如:FileOutputStream)来构造一个ObjectOutputStream(对象流)对象,接着,作文(https://www.isanxia.com)使用ObjectOutputStream对象的writeObject(Objectobj)方法就可以将参数为obj的对象写出(即保存其状态),要恢复的话则用输入流。

Q:
如何将一个java对象序列化到文件里?
在java中能够被序列化的类必须先实现
Serializable
接口,该接口没有任何抽象方法只是起到一个标记作用。
Q:
如何实现对象克隆?
两种方式:
实现Cloneable接口并重写Object类中的clone()方法;
实现Serializable接口,通过对象的序列化和反序列化实现克隆,可以实现真正的深度克隆。
注意:基于序列化和反序列化实现的克隆不仅仅是深度克隆,更重要的是通过泛型限定,可以检查出要克隆的对象是否支持序列化,这项检查是编译器完成的,不是在运行时抛出异常,这种是方案明显优于使用Object类的clone方法克隆对象。让问题在编译的时候暴露出来总是好过把问题留到运行时。
二、Java面试官写了个双冒号
一:简洁
方法引用分为三种,方法引用通过一对双冒号::来表示,方法引用是一种函数式接口的另一种书写方式
静态方法引用,通过类名::静态方法名,如Integer::parseInt
实例方法引用,通过实例对象::实例方法,如str::substring
构造方法引用,通过类名::new,如User::new
二:方法引用
publicfinalclassInteger{
publicstaticintparseInt(Strings)throwsNumberFormatException{
returnparseInt(s,10);
}
}
通过方法引用,可以将方法的引用赋值给一个变量,通过赋值给Function,说明方法引用也是一种函数式接口的书写方式,Lambda表达式也是一种函数式接口,Lambda表达式一般用于自己提供方法体,而方法引用一般直接引用现成的方法。
publicclassUser{
privateStringusername;
privateIntegerage;
publicUser(){
}
publicUser(Stringusername,Integerage){
this.username=username;
this.age=age;
}
@Override
publicStringtoString(){
return"User{"+
"username='"+username+'\''+
",age="+age+
'}';
}
//Getter&Setter
}
publicstaticvoidmain(String[]args){
//使用双冒号::来构造静态函数引用
Function<String,Integer>fun=Integer::parseInt;
Integervalue=fun.apply("123");
System.out.println(value);
//使用双冒号::来构造非静态函数引用
Stringcontent="HelloJDK8";
Function<Integer,String>func=content::substring;
Stringresult=func.apply(1);
System.out.println(result);
//构造函数引用
BiFunction<String,Integer,User>biFunction=User::new;
Useruser=biFunction.apply("mengday",28);
System.out.println(user.toString());
//函数引用也是一种函数式接口,所以也可以将函数引用作为方法的参数
sayHello(String::toUpperCase,"hello");
}
//方法有两个参数,一个是
privatestaticvoidsayHello(Function<String,String>func,Stringparameter){
Stringresult=func.apply(parameter);
System.out.println(result);
}
三:Optional可选值
在GoogleGuava中就有Optional,在Swift语言中也有这样类似的语法,在Swift中将可选值作为一种数据类型,地位和基本类型平齐平做,地位非常高。
packagejava.util;
importjava.util.function.Consumer;
importjava.util.function.Function;
importjava.util.function.Predicate;
importjava.util.function.Supplier;
/**
*@since1.8
*/
publicfinalclassOptional<T>{
privatestaticfinalOptional<?>EMPTY=newOptional<>();
privatefinalTvalue;
privateOptional(){
this.value=null;
}
//返回一个空的Optional实例
publicstatic<T>Optional<T>empty(){
@SuppressWarnings("unchecked")
Optional<T>t=(Optional<T>)EMPTY;
returnt;
}
privateOptional(Tvalue){
this.value=Objects.requireNonNull(value);
}
//返回具有Optional的当前非空值的Optional
publicstatic<T>Optional<T>of(Tvalue){
returnnewOptional<>(value);
}
//返回一个Optional指定值的Optional,如果非空,则返回一个空的Optional
publicstatic<T>Optional<T>ofNullable(Tvalue){
returnvalue==null?empty():of(value);
}
//如果Optional中有一个值,返回值,否则抛出NoSuchElementException。
publicTget(){
if(value==null){
thrownewNoSuchElementException("Novaluepresent");
}
returnvalue;
}
//返回true如果存在值,否则为false
publicbooleanisPresent(){
returnvalue!=null;
}
//如果存在值,则使用该值调用指定的消费者,否则不执行任何操作。
publicvoidifPresent(Consumer<?superT>consumer){
if(value!=null)
consumer.accept(value);
}
//如果一个值存在,并且该值给定的谓词相匹配时,返回一个Optional描述的值,否则返回一个空的Optional
publicOptional<T>filter(Predicate<?superT>predicate){
Objects.requireNonNull(predicate);
if(!isPresent())
returnthis;
else
returnpredicate.test(value)?this:empty();
}
//如果存在一个值,则应用提供的映射函数,如果结果不为空,则返回一个Optional结果的Optional。
public<U>Optional<U>map(Function<?superT,?extendsU>mapper){
Objects.requireNonNull(mapper);
if(!isPresent())
returnempty();
else{
returnOptional.ofNullable(mapper.apply(value));
}
}
//如果一个值存在,应用提供的Optional映射函数给它,返回该结果,否则返回一个空的Optional。
public<U>Optional<U>flatMap(Function<?superT,Optional<U>>mapper){
Objects.requireNonNull(mapper);
if(!isPresent())
returnempty();
else{
returnObjects.requireNonNull(mapper.apply(value));
}
}
//如果值存在,就返回值,不存在就返回指定的其他值
publicTorElse(Tother){
returnvalue!=null?value:other;
}
publicTorElseGet(Supplier<?extendsT>other){
returnvalue!=null?value:other.get();
}
public<XextendsThrowable>TorElseThrow(Supplier<?extendsX>exceptionSupplier)throwsX{
if(value!=null){
returnvalue;
}else{
throwexceptionSupplier.get();
}
}
}
关于of方法,现在好像很流行,就是提供一个static方法,方法名称叫of,方法的返回值返回当前类,并且把构造函数设置为私有private,用静态of方法来代替构造函数。
publicclassUser{
privateStringusername;
privateIntegerage;
privateUser(){
}
publicstaticUserof(){
returnnewUser();
}
privateUser(Stringusername,Integerage){
this.username=username;
this.age=age;
}
publicstaticUserof(Stringusername,Integerage){
returnnewUser(username,age);
}
}
Main
publicstaticvoidmain(String[]args){
//Optional类已经成为Java8类库的一部分,在Guava中早就有了,可能Oracle是直接拿来使用了
//Optional用来解决空指针异常,使代码更加严谨,防止因为空指针NullPointerException对代码造成影响
Stringmsg="hello";
Optional<String>optional=Optional.of(msg);
//判断是否有值,不为空
booleanpresent=optional.isPresent();
//如果有值,则返回值,如果等于空则抛异常
Stringvalue=optional.get();
//如果为空,返回else指定的值
Stringhi=optional.orElse("hi");
//如果值不为空,就执行Lambda表达式
optional.ifPresent(opt->System.out.println(opt));
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值