伪命题:Java传递的值还是引用?

Java参数传值还是传引用?
Java按值传递与引用传递?
JAVA值传递还是引用传递?

初学者经常被这个问题搞得头晕脑胀,甚至它还成为程序员面试的经典试题,但是在我个人看来,这个问题本身存在误导,如同妈和老婆落水你先救哪个一样,这个问题能够成立的条件并不是在Java语言这个边界内。

实际上这个问题是:
Java(或其他语言)能否提供值传递或引用传递?
语言平台除了这两种传递方式之外,是否需要其他传递方式?

要回答这两个问题,我们需要从OO松耦合和DDD分析设计这个高度来回答。

之前我写了两篇文章:
1. 松耦合角度:依赖注入和事件编程,提出了如果因为两个类因为方法调用,而必须将这两个类实现引用关联,这是一种因为局部利益造成整体依赖紧耦合的短视做法。

2.聚合根与Bounded Context角度:使用依赖注入实现聚合根之间调用的逻辑悖论,DDD提供了一套统一语言和方法,让我们对需求领域切分成一个个Bounded context,这些上下文场景孕育了聚合根,有名乃万物之母,不能有超越有界上下文边界的聚合存在,而如果将两个聚合根(聚合群的头)使用引用聚合在一起,这本身实则是混淆了上下文边界,Evans认为在上下文之间重用代码是一件非常冒险的,更何况我们通过引用表达这种紧耦合关系。

既然引用是把双刃剑,如此简单却又是造成紧耦合的元凶,那么是不是应该慎重使用呢?每次用Java编程时,该使用引用+依赖注入,还是考虑使用别的方式替代呢?

值+ 事件消息 可以替代引用+依赖注入。

比如原来引用+依赖注入的代码:


public class BacklogItem{
Product product;

}

如果BacklogItem和Product两个类之间只是一种方法依赖,也就是说,BacklogItem需要调用Product方法,那么我们就没有必要使用设计模式这种结构模式(组合模式),而应该考虑行为模式(观察者模式等),因为这种引用实现的组合模式导致两个类结构上的依赖,正好误用了结构型模式。


通过值+ 事件消息(观察者模式)可以替代如下:


public class ProductVO {
private long productId;
private long name;
private String description;
}

public class BacklogItem{
private ProductVO productVO;
void dosth(){
//向Product聚合根发事件消息实现调用
domainevents.send(new
ProductUpdatedEvent(productVO.getProductId));
}
}

既然我们的设计意图是使用事件消息,那么我们就要拷问作为设计工具的Java,你能实现这样的事件消息吗?

Java只能说:不能直接实现。

Scala或Erlang说:I can, 用Actor即可

如果下次再有人问你:Java传递的是值还是引用。
你可以反问:传你个妹啊,你怎么不问Java能够传递消息吗?

[该贴被banq于2013-04-17 10:30修改过]
[该贴被admin于2013-04-17 12:32修改过]

之所以认为这是个伪问题,是因为弄清楚这个问题对于是否能使用好Java没有任何帮助。

正如弄清楚“母亲和老婆掉入水里先救哪个”对你生活有帮助吗?

如果一个问题没有任何利处,反而可能浪费时间精力,干脆就否定问题本身。被应试教育驯化的我们要敢于说“不”。

没法回复?
[该贴被2102于2013-04-18 01:22修改过]

有个疑问:
public class ProductVO {
private long productId;
private long name;
private String description;
}

public class BacklogItem{
private ProductVO productVO;
void dosth(){
//向Product聚合根发事件消息实现调用
domainevents.send(new
ProductUpdatedEvent(productVO.getProductId));
}
}

板桥的这种设计方式不也同样耦合了BacklogItem和ProductVO两个类吗?我觉得,只要是面向对象,一个类关联了另一个类的话,除了组合、实现某个接口,没有其他方式了吧?

其实这个问题对于java初学者是有帮助的,在java里传递的参数一律都是实参的副本,引用也是一个值(某个对象的地址的值),传递引用被有些人误以为传递的是对象的地址(其实是对象地址的一个副本)

Banq老师解析得很精辟

面试确实遇到了,但是原理还是不明白,对于学习了半年Java的菜鸟这解释有点儿高深,能不能简单一点儿?