Java面试题汇总 | 基础知识第八章

上一章 : Java面试题汇总 | 基础知识第七章-CSDN博客

值传递

当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,这个过程属于值传递还是引用传递?

        是值传递。 Java 语言的方法调用只支持参数的值传递 。  当一个对象作为参数在方法中被传递时,传递的实际上是该对象的引用。在方法执行期间,对象内部的属性可以发生变化,但传入方法的对象引用本身并不会改变,也不会影响到调用方法的外部环境。然而引用的本质也是一个值,所以为值传递。
        

为什么 Java 中只有值传递

        首先回顾一下在程序设计语言中有关将参数传递给方法(或函数)的一些专业术语。按值调用(call by value)表示方法 接收的是调用者提供的值,而按引用调用(call by reference)表示方法接收的是调用者提供的变量地址。一个方法可 以修改 传递引用所对应的变量值 ,而不能修改 传递值调用所对应的变量值

        Java程序设计语言总是采用按值调用。方法得到的总是参数值的拷贝,也就是说,方法不能修改传递给它的任何参数变量的内容。

下面通过 3 个例子来给大家说明:
example1:
public static void main(String[] args){
    int num1 =10;
    int num2 =20;
    swap(num1, num2); 
    System.out.println("num1 = "+ num1);
    System.out.println("num2 = "+ num2);
}    
public static void swap(int a,int b){
    int temp = a; 
    a = b;
    b = temp;
    System.out.println("a = "+ a); 
    System.out.println("b = "+ b);
}

结果:

a =20;b =10;num1 =10;num2 =20;
解析:
         在swap方法中,a、b的值进行交换,并不会影响到 num1、num2。因为,a、b中的值,只是从 num1、num2 的复制过来的。也就是说,a、b相当于num1、num2 的副本,副本的内容无论怎么修改,都不会影响到原件本身。
        通过上面例子,我们已经知道了一个方法不能修改一个基本数据类型的参数,而对象引用作为参数就不一样,请看:
example2:
public static void main(String[] args){
    int[] arr ={1,2,3,4,5}; 
    System.out.println(arr[0]);
    change(arr);
    System.out.println(arr[0]);
}
public static void change(int[] array){
    // 将数组的第一个元素变为0 
    array[0]=0;
}
结果:
10

解析: 

 

 

         array 被初始化 arr 的拷贝也就是一个对象的引用,也就是说 array 和 arr 指向的时同一个数组对象。 因此,外部对引用对象的改变会反映到所对应的对象上。
        通过 example2 我们已经看到,实现一个改变对象参数状态的方法并不是一件难事。理由很简单,方法得到的是对象引用的拷贝,对象引用及其他的拷贝同时引用同一个对象。
        很多程序设计语言(特别是,C++和Pascal)提供了两种参数传递的方式:值调用和引用调用。有些程序员认为Java程序设计语言对对象采用的是引用调用,实际上,这种理解是不对的。由于这种误解具有一定的普遍性,所以下面给出一个反例来详细地阐述一下这个问题:
example3:
public class Test{
    public static void main(String[] args){
        Student s1 = new Student("小张"); 
        Student s2 = new Student("小李"); 
        Test.swap(s1, s2); 
        System.out.println("s1:"+ s1.getName());
        System.out.println("s2:"+ s2.getName());
    }    

    public static void swap(Student x, Student y){ 
        Student temp = x; 
        x = y; 
        y = temp; 
        System.out.println("x:"+ x.getName()); 
        System.out.println("y:"+ y.getName());
    }
}
结果:
x:小李 y:小张 s1:小张 s2:小李
解析:
交换之前:
交换之后:
        通过上面两张图可以很清晰的看出: 方法并没有改变存储在变量 s1 和 s2 中的对象引用。swap方法的参数x和y被初始化为两个对象引用的拷贝,这个方法交换的是这两个拷贝。
总结

Java程序设计语言对对象采用的不是引用调用,实际上,对象引用是按值传递的。
        Java中方法参数的使用情况:
                 一个方法不能修改一个基本数据类型的参数(即数值型或布尔型)
                一个方法可以改变一个对象参数的状态。
                一个方法不能让对象参数引用一个新的对象。

值传递和引用传递有什么区别?

值传递:指在方法调用时,传递的参数是按值的拷贝传递,传递的是值的拷贝,也就是说传递后原数据和拷贝后的数据之间并没有直接的引用关系,它们在内存中是独立的。
引用传递:指在方法调用时,传递的参数是按引用进行传递,其实传递的是引用的地址,也就是变量所对应的内存空间的地址。传递的是值的引用,也就是说传递前和传递后都指向同一个引用(也就是同一个内存空间)。

Java包

JDK 中常用的包有哪些?

        java.lang:系统基础类;
        java.io:所有输入输出有关的类,比如文件操作等;
        java.nio:为了完善 io 包中的功能,提高 io 包中性能而写的一个新包;
        java.net:与网络有关的类;
        java.util:系统辅助类,特别是集合类;
        java.sql:这数据库操作的类。

import java和javax有什么区别?

         Java API 在初始阶段,必要的包是以 "java" 开头的,而 "javax" 仅仅是作为扩展 API 包来使用。然而,随着时间的发展,"javax" 逐渐扩展并成为了 Java API 的一部分。尽管如此,将扩展部分从 "javax" 包转移到 "java" 包会非常繁琐,并且可能会破坏大量现有的代码。因此,为了保持现有代码的稳定性,决定将 "javax" 包加入 Java API 的标准部分。
        所以目前看来,二者只是类库名称不同,都是Java API的标准库,没有本质上的区别。
       

IO流

java 中 IO 流分为几种?

         按照流的流向分,可以分为输入流和输出流;
        按照操作单元划分,可以划分为字节流和字符流;
        按照流的角色划分为节点流和处理流。
        Java Io流共涉及40多个类,这些类看上去很杂乱,但实际上很有规则,而且彼此之间存在非常紧密的联系, Java I0流的40多个类都是从如下4个抽象类基类中派生出来的:
        InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
        OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。
按操作方式分类结构图:
按操作对象分类结构图:

 BIO,NIO,AIO 有什么区别?

简答:
BIO:Block IO 同步阻塞式 IO,就是我们平常使用的传统 IO,它的特点是模式简单使用方便,并发处理能力低。
NIO:Non IO 同步非阻塞 IO,是传统 IO 的升级,客户端和服务器端通过 Channel(通道)通讯,实现了多路复用。
AIO:Asynchronous IO 是 NIO 的升级,也叫 NIO2,实现了异步非堵塞 IO ,异步 IO 的操作基于事件和回调机制。
详细回答:
BIO (Blocking I/O): 同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。在活动连接数不是特别高(小于单机1000)的情况下,这种模型是比较不错的,可以让每一个连接专注于自己的 I/O 并且编程模型简单,也不用过多考虑系统的过载、限流等问题。线程池本身就是一个天然的漏斗,可以缓冲一些系统处理不了的连接或请求。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。
NIO (New I/O): NIO是一种同步非阻塞的I/O模型,在Java 1.4 中引入了NIO框架,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。 NIO中的N可以理解为Non-blocking(即非阻塞),不单纯是New。 它是面向缓冲的,基于通道的I/O操作方法。NIO提供了与传统BIO模型中的 Socket ServerSocket 相对应的 SocketChannel ServerSocketChannel 两种不同的套接字通道实现,两种通道都支持阻塞和非阻塞两种模式。阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用 NIO 的非阻塞模式来开发。
AIO (Asynchronous I/O): AIO 也就是 NIO 2。在 Java 7 中引入了 NIO 的改进版 NIO 2,它是异步非阻塞的IO模型。异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。AIO 是异步IO的缩写,虽然 NIO 在网络操作中,提供了非阻塞的方法,但是 NIO 的 IO 行为还是同步的。对于 NIO 来说,业务线程是在 IO 操作准备好时,得到通知,接着就由这个线程自行进行 IO 操作,IO操作本身是同步的。
加餐小tips:
         如何理解上文中:“NIO中的N可以理解为Non-blocking(即非阻塞),不单纯是New”呢?
“N”在NIO中代表的是“Non-blocking”,强调了它的非阻塞特性。这也是NIO与传统IO操作最大的不同点:NIO的选择器允许一个线程管理多个通道,实现了I/O操作的多路复用。所以,一个线程可以监控多个通道的状态,而当某个通道准备好执行I/O操作时,线程可以立即进行处理,其他通道则在后台继续准备。
        NIO模型的引入改善了Java在处理大量并发I/O请求时的性能,减少了线程的阻塞,提高了资源利用率,并能够更好地支持高并发处理。

Files的常用方法都有哪些?

        Files. exists():检测文件路径是否存在。
        Files. createFile():创建文件。
        Files. createDirectory():创建文件夹。
        Files. delete():删除一个文件或目录。
        Files. copy():复制文件。
        Files. move():移动文件。
        Files. size():查看文件个数。
        Files. read():读取文件。
        Files. write():写入文件。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值