Java参数分析
程序员文章站
2022-05-09 20:35:27
...
1.Java的数据类型
1)基本数据类型
int,char,float,byte,long,short,double,boolean
2)引用数据类型(对象类型,类类型)
数组,类,接口,抽象类都属于引用数据类型。
要讨论参数传递方式,就得从内存模型说起,主要是我个人觉得从内存模型来说参数传递更为直观一些。
内存模型涉及到两种类型的内存:栈内存(stack)和堆内存(heap)。
2.什么是值传递?
基本类型作为参数传递时,传递的是这个值的拷贝。无论你怎么改变这个拷贝,原值是不会改变的。方法括号中的就是形参,传入进去的是实参。
实例:
public class TestDemo {
public static void main(String[] args) {
int score = 5;
Student stu = new Student();
stu.setScore(score);
System.out.println("stuScore = "+stu.getScore());
System.out.println("TestDemo= "+score);
}
}
public class Student {
private int score;
public void setScore(int score){
score++;
this.score = score;
}
public int getScore(){
return score;
}
}
程序运行结果是:
stuScore=6
TestDemo=5
程序运行的结果也说明这一点,无论你在setScore()方法中怎么改变参数score的值,原值Score都不会改变。
下边通过内存模型来分析一下
当执行了int score=5;这句代码后,程序在栈内存中开辟了一块地址为@123的内存,里边放的值是5,内存模型如下图:
栈内存
score(@123)
5
执行到Student stu = new Student()时,程序在栈内存中又开辟了一块地址为@456的内存,创建stu对象,程序在堆内存中又开辟了一块地址为@789的内存,存放score属性以及setScore()方法,此时这块stu内存里边放的值是score属性与setScore()方法的地址,执行到setScore()方法时,将score的值5传递进来,此时这块内存里边放的值是5,执行score++;后,score中的值变成了6。内存模型如下图:
栈内存 堆内存
score(@123)
5
stu(@456) @789
@789 core=null-->6
ssetScore(int score){}
3、只要形式参数类型是基本数据类型或者String时,都属于值传递 int,char,float,byte,long,short,double,boolean,String
一定要注意String的特殊性,在Java中,String是一个引用类型,但是在作为参数传递的时候表现出来的却是基本类型的特性,即在方法中改变了String类型的变量的值后,不会影响方法外的String变量的值。
实例:
public class TestDemo {
public static void main(String[] args) {
String score = "5";
Student stu = new Student();
stu.setScore(score);
Student stu1 = new Student();
stu1.setScore("6");
System.out.println("stu1 = "+stu1.getScore());
System.out.println("stu = "+stu.getScore());
}
}
public class Student {
private String score;
public Student(){}
public void setScore(String score){
this.score = score;
}
public String getScore(){
return score;
}
}
程序运行结果:
stu1 =6
stu =5
内存模型分析与上述是一样的。
4、什么是引用传递(地址传递)
创建对象时,对象名存储的是对象在内存中的首地址。
将对象名A存储的内容赋给另一个对象名B,实际上就是把A地址赋给一个新对象名B;
这样两个对象名A、B就存储了同一个对象在内存中的地址;
使用其中一个对象名B将对象的属性值修改后,那么另一个对象名A的也会改变。
实例:
public class TestDemo {
public static void main(String[] args) {
String score = "5";
Student stu = new Student();
stu.setScore(score);
Student stu1 = new Student();
Stu1=stu;
stu1.setScore("6");
System.out.println("stu1 = "+stu1.getScore());
System.out.println("stu = "+stu.getScore());
}
}
public class Student {
private String score;
public Student(){}
public void setScore(String score){
this.score = score;
}
public String getScore(){
return score;
}
}
程序运行结果:
stu1 = 6
stu =6
当对象作为参数传递时,传递的是对象的引用,也就是对象的地址。下边用内存模型图来说明:
当程序执行Student stu = new Student();后,程序在栈内存中开辟了一块地址编号为@456内存空间,用于存放stu的引用地址,里边放的值是堆内存中的一个地址,示例中的值为@789,可以理解为有一个指针指向了堆内存中的编号为@789的地址。堆内存中编号为@789的这个地址中存放的才是stu的值.
栈内存 堆内存
score(@123)
5
stu(@456) @789
@789 score=null
Student(){}
setScore(String score){}
getScore(){}
当程序进入Student stu1 = new Student();Stu1=stu;后,将stu的值,也就是对象的引用@789传了进来。这时,程序在栈内存中又开辟了一块编号为@112的内存空间,里边放的值是传递过来的值。可以理解为栈内存中的编号为@112的内存中有一个指针,也指向了堆内存中编号为@789的内存地址,在setScore()方法中将score的值修改为6,如图所示:
栈内存 堆内存
score(@123)
5
stu(@456) @789
@789 score=null-->6
Student(){}
setScore(String score){}
getScore(){}
Stu1(@112)
@789
无论是基本类型作为参数传递,还是对象作为参数传递,实际上传递的都是值,只是值的的形式不用而已。第一个示例中用基本类型作为参数传递时,将栈内存中的值5传递到了setScore()方法中。第二个示例中用对象作为参数传递时,将栈内存中的值@789传递到了setScore()方法中。当用对象作为参数传递时,真正的值是放在堆内存中的,传递的是栈内存中的值,而栈内存中存放的是堆内存的地址,所以传递的就是堆内存的地址。这就是它们的区别。
5、在程序中通过什么方法传递参数
set方法传递参数
构造方法传递参数
行为方法传递参数
补充:如果是重写方法,那么一定不能增加参数。
1)基本数据类型
int,char,float,byte,long,short,double,boolean
2)引用数据类型(对象类型,类类型)
数组,类,接口,抽象类都属于引用数据类型。
要讨论参数传递方式,就得从内存模型说起,主要是我个人觉得从内存模型来说参数传递更为直观一些。
内存模型涉及到两种类型的内存:栈内存(stack)和堆内存(heap)。
2.什么是值传递?
基本类型作为参数传递时,传递的是这个值的拷贝。无论你怎么改变这个拷贝,原值是不会改变的。方法括号中的就是形参,传入进去的是实参。
实例:
public class TestDemo {
public static void main(String[] args) {
int score = 5;
Student stu = new Student();
stu.setScore(score);
System.out.println("stuScore = "+stu.getScore());
System.out.println("TestDemo= "+score);
}
}
public class Student {
private int score;
public void setScore(int score){
score++;
this.score = score;
}
public int getScore(){
return score;
}
}
程序运行结果是:
stuScore=6
TestDemo=5
程序运行的结果也说明这一点,无论你在setScore()方法中怎么改变参数score的值,原值Score都不会改变。
下边通过内存模型来分析一下
当执行了int score=5;这句代码后,程序在栈内存中开辟了一块地址为@123的内存,里边放的值是5,内存模型如下图:
栈内存
score(@123)
5
执行到Student stu = new Student()时,程序在栈内存中又开辟了一块地址为@456的内存,创建stu对象,程序在堆内存中又开辟了一块地址为@789的内存,存放score属性以及setScore()方法,此时这块stu内存里边放的值是score属性与setScore()方法的地址,执行到setScore()方法时,将score的值5传递进来,此时这块内存里边放的值是5,执行score++;后,score中的值变成了6。内存模型如下图:
栈内存 堆内存
score(@123)
5
stu(@456) @789
@789 core=null-->6
ssetScore(int score){}
3、只要形式参数类型是基本数据类型或者String时,都属于值传递 int,char,float,byte,long,short,double,boolean,String
一定要注意String的特殊性,在Java中,String是一个引用类型,但是在作为参数传递的时候表现出来的却是基本类型的特性,即在方法中改变了String类型的变量的值后,不会影响方法外的String变量的值。
实例:
public class TestDemo {
public static void main(String[] args) {
String score = "5";
Student stu = new Student();
stu.setScore(score);
Student stu1 = new Student();
stu1.setScore("6");
System.out.println("stu1 = "+stu1.getScore());
System.out.println("stu = "+stu.getScore());
}
}
public class Student {
private String score;
public Student(){}
public void setScore(String score){
this.score = score;
}
public String getScore(){
return score;
}
}
程序运行结果:
stu1 =6
stu =5
内存模型分析与上述是一样的。
4、什么是引用传递(地址传递)
创建对象时,对象名存储的是对象在内存中的首地址。
将对象名A存储的内容赋给另一个对象名B,实际上就是把A地址赋给一个新对象名B;
这样两个对象名A、B就存储了同一个对象在内存中的地址;
使用其中一个对象名B将对象的属性值修改后,那么另一个对象名A的也会改变。
实例:
public class TestDemo {
public static void main(String[] args) {
String score = "5";
Student stu = new Student();
stu.setScore(score);
Student stu1 = new Student();
Stu1=stu;
stu1.setScore("6");
System.out.println("stu1 = "+stu1.getScore());
System.out.println("stu = "+stu.getScore());
}
}
public class Student {
private String score;
public Student(){}
public void setScore(String score){
this.score = score;
}
public String getScore(){
return score;
}
}
程序运行结果:
stu1 = 6
stu =6
当对象作为参数传递时,传递的是对象的引用,也就是对象的地址。下边用内存模型图来说明:
当程序执行Student stu = new Student();后,程序在栈内存中开辟了一块地址编号为@456内存空间,用于存放stu的引用地址,里边放的值是堆内存中的一个地址,示例中的值为@789,可以理解为有一个指针指向了堆内存中的编号为@789的地址。堆内存中编号为@789的这个地址中存放的才是stu的值.
栈内存 堆内存
score(@123)
5
stu(@456) @789
@789 score=null
Student(){}
setScore(String score){}
getScore(){}
当程序进入Student stu1 = new Student();Stu1=stu;后,将stu的值,也就是对象的引用@789传了进来。这时,程序在栈内存中又开辟了一块编号为@112的内存空间,里边放的值是传递过来的值。可以理解为栈内存中的编号为@112的内存中有一个指针,也指向了堆内存中编号为@789的内存地址,在setScore()方法中将score的值修改为6,如图所示:
栈内存 堆内存
score(@123)
5
stu(@456) @789
@789 score=null-->6
Student(){}
setScore(String score){}
getScore(){}
Stu1(@112)
@789
无论是基本类型作为参数传递,还是对象作为参数传递,实际上传递的都是值,只是值的的形式不用而已。第一个示例中用基本类型作为参数传递时,将栈内存中的值5传递到了setScore()方法中。第二个示例中用对象作为参数传递时,将栈内存中的值@789传递到了setScore()方法中。当用对象作为参数传递时,真正的值是放在堆内存中的,传递的是栈内存中的值,而栈内存中存放的是堆内存的地址,所以传递的就是堆内存的地址。这就是它们的区别。
5、在程序中通过什么方法传递参数
set方法传递参数
构造方法传递参数
行为方法传递参数
补充:如果是重写方法,那么一定不能增加参数。
上一篇: java参数传递的基本原理