Java 为什么在方法调用期间将变量置为null会使传递给方法的值也为null?
我对一些java行为感到非常困惑,特别是因为我以前对java的理解是,它严格按照值传递 如果我将一个对象传递给一个方法,然后在调用线程中将该对象设为null,我希望该对象仍然存在并且能够在该方法中操作,但事实并非如此 以下是一些示例代码:Java 为什么在方法调用期间将变量置为null会使传递给方法的值也为null?,java,methods,concurrency,parameters,Java,Methods,Concurrency,Parameters,我对一些java行为感到非常困惑,特别是因为我以前对java的理解是,它严格按照值传递 如果我将一个对象传递给一个方法,然后在调用线程中将该对象设为null,我希望该对象仍然存在并且能够在该方法中操作,但事实并非如此 以下是一些示例代码: 公共类方法测试{ 布尔布尔; 布尔二次布尔; 测试列表; 公共静态void main(字符串[]args){ 新建methodTest().run(); } 公开募捐{ 列表=新测试(); 新线程(()->{ func(列表); }).start(); 列表=
公共类方法测试{
布尔布尔;
布尔二次布尔;
测试列表;
公共静态void main(字符串[]args){
新建methodTest().run();
}
公开募捐{
列表=新测试();
新线程(()->{
func(列表);
}).start();
列表=空;
布尔=真;
而(!secondBool){
//挡块
}
gc();
}
公共无效函数(大测试){
而(!bool){
//挡块
}
System.out.println(大);
secondBool=true;
}
课堂测试{
@凌驾
受保护的void finalize()抛出可丢弃的{
System.out.println(“我正在清理!”;
}
@凌驾
公共字符串toString(){
返回“Test!”;
}
}
}
此代码打印
null
I'm getting cleaned up!
当我希望它打印时:
Test!
I'm getting cleaned up!
最后,我在类中包含了垃圾收集调用和finalize方法,以确保在函数打印变量list
之前,gc不会到达该变量,但没有它也会产生同样的效果
这种行为的解释是什么
编辑:
另一个例子是,如果您将run方法中的
list=null
行更改为list=new Test()
,然后稍微修改toString
,以计算Test
实例的数量。程序将打印“Test2”而不是“Test1”,因为func
中的参数值在调用线程中被重写,即使在我对java的传递值系统的理解中,这不应该发生。如果我正确记住java,它会更改用户定义类的值。因此,如果您使用基本数据类型和已定义的类,如int、string等,则不会导致此问题。但这里您使用的是您自己的类,因此出于某种原因,它是通过引用传递的 它打印空值,因为存在争用条件,并且新线程会丢失大部分时间
时间是这样的:
methodTest.run()
)创建一个新的thread
对象并启动新线程(意味着它创建一个新的linux/windows线程并通知它可以开始运行)list
设置为null()->{func(list);}
func(列表)时代码>它将读取实例变量列表
big
传递到func
的内容完全取决于
- 主线程需要多少时间执行
list=null代码>
- 操作系统开始执行第二个线程以及第二个线程到达调用
func(列表)的点所需的时间代码>
根据您的观察,第二个线程需要更多的时间才能到达
func(列表)的点代码>的执行超过了主线程需要执行的list=null
之所以发生这种情况,是因为线程尚未调用func()
,而此时您已将列表设置为null,因此它在运行时收到了null
。这里真正的问题是为什么要将列表
置零?简单回答:不要。我甚至没有想到调用函数和将list
设置为null之间的竞争。我会做些测试,然后再打给你。