java引⽤类型参数_Java中的参数传递和引⽤类型本⽂主要分三部分介绍 Java 中的值、指针与引⽤的概念。
第⼀部分从编程语⾔的三种参数传递⽅式⼊⼿,阐释“为什么 Java 中只有值传递”。
第⼆部分排除⾃动装箱和⾃动拆箱的⼲扰,理解 Integer 等封装类作为参数传值的情形。
第三部分通过简单的⽰例,展⽰强引⽤、软引⽤、弱引⽤和虚引⽤之间的区别。
⼀、参数传递⽅式
1.1 值传递
形参是实参的拷贝,改变形参的值并不会影响外部实参的值。
从被调⽤函数的⾓度来说,值传递是单向的(实参->形参),参数的值只能传⼊,不能传出。
public class IntegerTest01 {
private static void changeInt(int value) {
++value;
}
public static void main(String[] args) {
int a = 1;
changeInt(a);
System.out.println("a = " + a);
}
}
执⾏结果为a = 1
1.2 指针传递
Java 中没有指针,为了直观展⽰指针传递,这⾥使⽤了 C++ 的例⼦。
指针从本质上讲是⼀个变量,变量的值是另⼀个变量的地址。因此可以说指针传递属于值传递。
#include
using namespace std;
void fun(int *x) {// 声明指针
*x += 5; // *x 是取得指针所指向的内存单元,即指针解引⽤
// x += 5; 则对实参没有影响
}
int main() {
int y = 0;
fun(&y);// 取地址
cout<< "y = "<< y <
return 0;
void fun(int &x){// 声明⼀个别名
x += 5; // 修改的是 x 引⽤的对象值 &x = y;
}
int main()
{
int y = 0;
fun(y);
cout<< "y = "<< y <
return 0;
}
执⾏结果y = 5
C++ 中的引⽤就是某⼀变量(⽬标)的⼀个别名,对引⽤的操作与对变量直接操作完全⼀样。
声明⼀个引⽤,不是新定义了⼀个变量,它只表⽰该引⽤名是⽬标变量名的⼀个别名,它本⾝不是⼀种数据类型,因此引⽤本⾝不占存储单元,系统也不给引⽤分配存储单元。
Java 中的引⽤
Java 中的引⽤是 reference 类型,类似于 C/C++ 中指针的概念,⽽跟 C/C++ 中引⽤的概念完全不同。
在 JDK 1.2 以前,Java 中的引⽤的定义:如果 reference 类型的数据中存储的数值代表的是另外⼀块内存的起始地址,就称这块内存代表着⼀个引⽤。
在JDK 1.2之后,Java对引⽤的概念进⾏了扩充,将引⽤分为强引⽤(Strong Reference)、软引⽤(Soft Reference)、弱引⽤(Weak Reference)、虚引⽤(Phantom Reference)4种,这4种引⽤强度依次逐渐减弱。
⼆、Integer 参数传递问题
回到开篇值传递的例⼦:
public class IntegerTest01 {
private static void changeInt(int value) {
++value;
}
public static void main(String[] args) {
int a = 1;
changeInt(a);
System.out.println("a = " + a);
}
}
如果把代码中的 int 类型换成 Integer 对象,结果会怎么样?
public class IntegerTest02 {
private static void changeInteger(Integer value) {
++value;
}
public static void main(String[] args) {
Integer a = 1;
changeInteger(a);
System.out.println("a = " + a);
}
}
⾸先需要排除⾃动装箱和⾃动拆箱的⼲扰。
2.1 ⾃动装箱和⾃动拆箱
package com.sumkor.jdk7.integer02;
public class IntegerTest {
public static void main(String[] args) {
Integer a = 1;
int b = a;
}
}
使⽤命令javap -c IntegerTest.class进⾏反编译:
Compiled from "IntegerTest.java"
public class com.sumkor.jdk7.integer02.IntegerTest {
java valueof
public com.sumkor.jdk7.integer02.IntegerTest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."":()V
4: return
public static void main(java.lang.String[]);
Code:
0: iconst_1
1: invokestatic #2 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer; 4: astore_1
5: aload_1
6: invokevirtual #3 // Method java/lang/Integer.intValue:()I
9: istore_2
10: return
}
由此可知:
⾃动装箱实际调⽤的是Integer.valueOf
⾃动拆箱实际调⽤的是Integer.intValue
因此,排除⾃动装箱、⾃动拆箱,例⼦ IntegerTest02 等价于以下写法:public class IntegerTest03 {
private static void changeInteger(Integer value) {
value = Integer.valueOf(value.intValue() + 1);
}
public static void main(String[] args) {
Integer a = Integer.valueOf(1);
changeInteger(a);
}
}
查看 Integer 源码,可知valueOf()会将形参指向不同的 Integer 对象实例。/**
* Returns an {@code Integer} instance representing the specified
* {@code int} value. If a new {@code Integer} instance is not
* required, this method should generally be used in preference to
* the constructor {@link #Integer(int)}, as this method is likely
* to yield significantly better space and time performance by
* caching frequently requested values.
*
* This method will always cache values in the range -128 to 127,
* inclusive, and may cache other values outside of this range.
*
* @param i an {@code int} value.
* @return an {@code Integer} instance representing {@code i}.
* @since 1.5
*/
public static Integer valueOf(int i) {
assert IntegerCache.high >= 127;
if (i >= IntegerCache.low && i <= IntegerCache.high)
return IntegerCache.cache[i + (-IntegerCache.low)];
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论