当前位置:   article > 正文

Java基础------真实大厂面试题汇总(含答案)_值传递和引用传递的区别面试题目

值传递和引用传递的区别面试题目

面试题1. 按值传递和按引用传递的区别?

  • 值传递:方法调用时,实际参数把它的值的副本传递给对应的形式参数,此时形参接收到的其实只是实参值的一个拷贝,所以在方法内对形参做任何操作都不会影响实参
  • 引用传递:当参数是对象的时候,其实传递的对象的地址值,所以实参的地址值传给形参后,在方法内对形参进行操作会直接影响真实内容
  1. 如果传递的参数是八大基本类型的话,是值传递。如果参数传递的是对象实例、数组或者是接口的话,还是按值传递的,千万不要被外表所迷惑
  2. 也就是说,如果当你传递的是对象作为参数的话,首先参数会先进行拷贝一份引用执行原本的实例对象,但是一旦这个调用这个方法的结束之后,那么这个拷贝过来的实例对象的引用就会被肖销毁。
  3. https://blog.csdn.net/u013309870/article/details/75499175
  4. https://blog.csdn.net/javazejian/article/details/51192130

看下面一个例子仔细思考一下吧

public class CallByValue {
	private static User user=null;
	private static User stu=null;
	
	/**
	 * 交换两个对象
	 * @param x
	 * @param y
	 */
	public static void swap(User x,User y){
		User temp =x;
		x=y;
		y=temp;
	}
	
	
	public static void main(String[] args) {
		user = new User("user",26);
		stu = new User("stu",18);
		System.out.println("调用前user的值:"+user.toString());
		System.out.println("调用前stu的值:"+stu.toString());
		swap(user,stu);
		System.out.println("调用后user的值:"+user.toString());
		System.out.println("调用后stu的值:"+stu.toString());
	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

输出结果:

调用前user的值:User [name=user, age=26]

调用前stu的值:User [name=stu, age=18]

调用后user的值:User [name=user, age=26]

调用后stu的值:User [name=stu, age=18]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述
总结:

  • 在传进来的参数是基本类型的时候,用的是值传递
  • 如果传进来的参数类型是对象或者是数组类型的时候,也只是拷贝了引用的值罢了,之所以能修改引用数据是因为它们同时指向了一个对象,但这仍然是按值调用而不是引用调用

面试题2. Java的一个对象到底占用多大内存?以及如何分配对象中属性的内存的?

首先需要知道一个对象的结构:

对象头又包括三部分:MarkWord、元数据指针、数组长度。

  • MarkWord:用于存储对象运行时的数据,好比 HashCode、锁状态标志、GC分代年龄等。这部分在 64 位操作系统下占 8 字节,32 位操作系统下占 4 字节。
  • 指针:对象指向它的类元数据的指针,虚拟机通过这个指针来确定这个对象是哪一个类的实例。
    这部分就涉及到指针压缩的概念,在开启指针压缩的状况下占 4 字节,未开启状况下占 8 字节。
  • 数组长度:这部分只有是数组对象才有,若是是非数组对象就没这部分。这部分占 4 字节。

实例数据就不用说了,

  • 用于存储对象中的各类类型的字段信息(包括从父类继承来的)。

关于对齐填充

  • Java 对象的大小默认是按照 8 字节对齐,也就是说 Java 对象的大小必须是 8 字节的倍数。若是算到最后不够 8 字节的话,那么就会进行对齐填充。

Java 中基础数据类型是在栈上分配还是在堆上分配?

我们继续深究一下,基本数据类占用内存大小是固定的,那具体是在哪分配的呢,是在堆还是栈还是方法区?大家不妨想想看! 要解答这个问题,首先要看这个数据类型在哪里定义的,有以下三种情况。

  • 如果在方法体内定义的,这时候就是在栈上分配的
  • 如果是类的成员变量,这时候就是在堆上分配的
    • 如果是基础类型的话,就严格按照基本类型的占用内存大小进行分配的(默认开启指针压缩的情况下,就算不足4个字节,也会按照4个字节进行填充)
    • 如果是引用类型的话,那占用内存的地方就是引用类型的指针(不开启指针压缩的话是占用8个字节,默认JVM是开启指针压缩的就是占用4个字节)
  • 如果是类的静态成员变量,在方法区上分配的

面试题3. 深拷贝和浅拷贝的区别,怎么实现深拷贝?

他们的区别就是:

  1. 当如果要拷贝一个A对象,而A对象中又有一个B对象,那么如果对A拷贝的时候,重新拷贝出来一个A1对象并且重新分配内存地址,但是对于A中的B对象,仅仅只是把A1中拷贝出来的B1对象的引用指向原来的B对象而已,并没有把拷贝的B1对象也重新进行分配一个新的内存地址。这就是浅拷贝。
  2. 而深拷贝就是在第1的基础上,不仅重新给A1对象分配了新的内存地址,而且还给A1中的B1也重新进行分配了新的内存地址,而不只是仅仅把原本的B的引用给B1。这就是深拷贝。

这里借用一张书中的图片:
在这里插入图片描述

那么如果实现深拷贝呢?

  1. 如果想要深拷贝一个对象,
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/204527?site
推荐阅读
相关标签
  

闽ICP备14008679号