为什么java只有值传递?
什么是值传递
程序设计语言分为按值调用和按引用调用两种,按值调用指的是方法接收调用者提供的值,按引用调用指的是方法接收调用者提供的变量的地址。
一个方法可以修改按引用调用传递的变量本身的值,但是按值调用则不能修改变量本身的值,只能取到这个变量的值。
java语言是按值传递的,也就是说java中的方法不能修改变量本身的值。
重载和重写的区别
什么是重载
重载就是在一个类中,可以存在多个方法,他们具有相同的函数名,不同的参数(不同数量,不同类型,不同顺序....)
编译器通过给出的参数类型以及特殊方法调用的值进行匹配来挑选出特定的方法,如果编译器找不到对应的方法,就会编译出错,这个过程叫重载解析
java允许重载任何方法,不仅仅局限于构造器。要完整地描述一个方法,需要给出方法的签名,即方法的名称和参数的信息。
注意:返回值不是方法的签名,也就是说不允许存在两个方法,函数名相等,参数相等,但是返回值不等。
什么是重写
重写发生在运行期,是子类对父类方法进行重新编写
有以下三点:
1.方法名称,参数列表必须相等,返回类型更小或者相等,抛出的异常范围更小或者相等,访问修饰符大于等于父类
2.如果父类方法访问修饰符为 private/final/static
则子类就不能重写该方法,但是被 static 修饰的方法能够被再次声明。
3.构造方法不能被重写(也没有重写的必要,二者都不是同一个名字的类)
注意:返回类型如果是基本数据类型,那么不允许改变,如果是一个类,那么返回值可以是这个类的子类
区别总结
方法的四种类型
1.无参数无返回值
1 // 无参数无返回值的方法(如果方法没有返回值,不能不写,必须写void,表示没有返回值)
2 public void f1() {
3 System.out.println("无参数无返回值的方法");
4 }
2.有参数无返回值
1 /**
2 * 有参数无返回值的方法
3 * 参数列表由零组到多组“参数类型+形参名”组合而成,多组参数之间以英文逗号(,)隔开,形参类型和形参名之间以英文空格隔开
4 */
5 public void f2(int a, String b, int c) {
6 System.out.println(a + "-->" + b + "-->" + c);
7 }
3.无参数有返回值
1 // 有返回值无参数的方法(返回值可以是任意的类型,在函数里面必须有return关键字返回对应的类型)
2 public int f3() {
3 System.out.println("有返回值无参数的方法");
4 return 2;
5 }
4.有参数有返回值
1 // 有返回值有参数的方法
2 public int f4(int a, int b) {
3 return a * b;
4 }
浅拷贝和深拷贝
简述
在java中,=这个赋值符号,对于基本数据类型而言,就是把数值赋给变量。而对于一个对象而言,使用=,不是新建一个对象,而是把原对象的引用传递过去,等号两边的对象指的依旧是同一个对象,对于浅拷贝和深拷贝,就在这个背景条件下展开讨论。
在拷贝过程中,对于基本数据类型进行了拷贝,对于对象而言,没有新建一个对象,只是进行了引用的传递,这就叫浅拷贝。
反之,在拷贝过程中,对于对象的拷贝是创建了一个新的对象,并且复制了其中的成员变量,那么这就叫深拷贝。
所以浅拷贝和深拷贝的区别就在于拷贝类的实例对象时出现的差别。
实现
在Object类中有一个clone()方法,意味着所有的类都可以实现这个方法
对于浅拷贝和深拷贝,都需要调用这个clone()方法,一个类要实现clone()方法,必须实现Cloneable接口
1 package test1;
2
3 public class Father implements Cloneable{
4 public String name;
5 public Father(String n) {
6 name=n;
7 }
8 @Override
9 public Object clone() {
10 try {
11 return super.clone();
12 } catch (CloneNotSupportedException e) {
13 e.printStackTrace();
14 }
15 return null;
16 }
17
18 }
1 package test1;
2 public class test {
3 public static void main(String[] args) {
4 Father a=new Father("张三");
5 Father b=(Father) a.clone();
6 System.out.println(a==b);
7 System.out.println(a.hashCode());
8 System.out.println(b.hashCode());
9 }
10 }
通过结果可以看出这是一次深拷贝,但是如果在这个类中放置一个对象,是什么情况呢?
1 package test1;
2 public class test {
3 public static void main(String[] args) {
4 Father a=new Father("张三");
5 a.c=new Child("张小三");
6 Father b=(Father) a.clone();
7 System.out.println(a==b);
8 System.out.println(a.hashCode());
9 System.out.println(b.hashCode());
10 System.out.println(a.c==b.c);
11 System.out.println(a.c.hashCode());
12 System.out.println(b.c.hashCode());
13 }
14 }
1 package test1;
2
3 public class Father implements Cloneable{
4 public String name;
5 public Father(String n) {
6 name=n;
7 }
8 public Child c;
9 @Override
10 public Object clone() {
11 try {
12 return super.clone();
13 } catch (CloneNotSupportedException e) {
14 e.printStackTrace();
15 }
16 return null;
17 }
18
19 }
1 package test1;
2
3 public class Child implements Cloneable{
4 public String name;
5 public Child(String n) {
6 name=n;
7 }
8 }
我们发现,对于类内部的对象,并没有新建,所以是一个相对该类而言,对于这个类中的对象是一次浅拷贝。
那么我们如果实现类中对象的深拷贝呢?我们可以选择改写类本身以及类中对象对应的类的clone函数。
1 package test1;
2 public class test {
3 public static void main(String[] args) {
4 Father a=new Father("张三");
5 a.c=new Child("张小三");
6 Father b=(Father) a.clone();
7 System.out.println(a==b);
8 System.out.println(a.hashCode());
9 System.out.println(b.hashCode());
10 System.out.println(a.c==b.c);
11 System.out.println(a.c.hashCode());
12 System.out.println(b.c.hashCode());
13 }
14 }
1 package test1;
2
3 public class Father implements Cloneable{
4 public String name;
5 public Father(String n) {
6 name=n;
7 }
8 public Child c;
9 @Override
10 public Object clone() {
11 Father clonefather;
12 try {
13 clonefather = (Father)super.clone();
14 clonefather.c=(Child)this.c.clone();
15 return clonefather;
16 } catch (CloneNotSupportedException e) {
17 e.printStackTrace();
18 }
19 return null;
20 }
21
22 }
1 package test1;
2
3 public class Child implements Cloneable{
4 public String name;
5 public Child(String n) {
6 name=n;
7 }
8 @Override
9 public Object clone() {
10 try {
11 return super.clone();
12 } catch (CloneNotSupportedException e) {
13 e.printStackTrace();
14 }
15 return null;
16 }
17 }
这样,类中对象也进行了一次深拷贝
总结
浅拷贝:对基本数据类型进行值传递,对引用数据类型进行引用传递般的拷贝,此为浅拷贝。
深拷贝:对基本数据类型进行值传递,对引用数据类型,创建一个新的对象,并复制其内容,此为深拷贝。
深浅拷贝是相对而言的,我们可以通过改写clone()函数来实现深浅拷贝的转化