V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
buptlee
V2EX  ›  程序员

关于 java 的传址和传值

  •  1
     
  •   buptlee ·
    Xiaoxin2009 · 2014-09-02 10:02:04 +08:00 · 4083 次点击
    这是一个创建于 3736 天前的主题,其中的信息可能已经有所发展或是发生改变。
    我写了一个函数:
    public void updateDistMatrix(HashMap<Integer ,LinkedList<Node> > dist_matrix,ArrayList<Integer> nearestNodePair,HashMap<Integer,ArrayList<Integer>> clusterSet)
    {
    doSomething(dist_matrix);
    doSomething(clusterSet);
    }
    函数是要对传进去的两个参数dist_matrix和clusterSet进行更新,外层是一个循环,不断的调用updateDistMatrix()这个函数,以达到不断更新dist_matrix,clusterSet这两个变量的目的。
    但是,我发现,函数里对这两个变量的修改并不能保留到下次迭代,也就是说,下次迭代时,这两个变量的值依然是它们的初始值,我想问下大家,如果我想实现类似于c++的传址(参数)的效果,应该怎么做呢,将dist_matrix,clusterSet在main()前面声明成public static 类型的可以吗?
    大神们,教教我。
    第 1 条附言  ·  2014-09-02 11:33:48 +08:00
    public void updateDistMatrix(HashMap<Integer ,LinkedList<Node> > dist_matrix,ArrayList<Integer> nearestNodePair,HashMap<Integer,ArrayList<Integer>> clusterSet){
    Integer user1 = nearestNodePair.get(0);
    Integer user2 = nearestNodePair.get(1);
    ArrayList<Integer> set1 = clusterSet.get(user1);
    ArrayList<Integer> set2 = clusterSet.get(user2);
    set1.addAll(set2);
    clusterSet.remove(user2);
    clusterSet.put(user1, set1);

    LinkedList<Node> list1 = dist_matrix.get(user1);
    LinkedList<Node> list2 = dist_matrix.get(user2);
    LinkedList<Node> newList = mergeSort(list1,list2,nearestNodePair);

    dist_matrix.remove(user1);
    dist_matrix.remove(user2);
    dist_matrix.put(user1, newList);

    Iterator<Integer> iter = dist_matrix.keySet().iterator();
    while (iter.hasNext()) {
    Integer key = iter.next();
    LinkedList<Node> value = dist_matrix.get(key);
    ArrayList<Node> occurence = new ArrayList<Node>();
    int occurIndex = 0;
    for(Node node : value){
    if(nearestNodePair.get(0)==node.getImsi() || nearestNodePair.get(1)==node.getImsi()){
    occurence.add(occurIndex,node);
    occurIndex++;

    }
    }
    if(occurence.size() == 0){
    continue;
    }
    if(occurence.size() == 1){
    Node node = occurence.get(0);
    if(node.getImsi()==user1){
    continue;
    }
    else{
    value.remove(node);
    node.setImsi(user1);
    int mid = findIndex(value,node.getDist());
    value.add(mid, node);
    dist_matrix.put(key, value);
    }
    }
    if(occurence.size() == 2){
    value.remove(occurence.get(1));
    Node node = occurence.get(0);
    if(node.getImsi()==user1){
    continue;
    }
    else{
    value.remove(node);
    node.setImsi(user1);
    int mid = findIndex(value,node.getDist());
    value.add(mid, node);
    dist_matrix.put(key, value);
    }
    }
    }
    }
    }
    class Node{
    Integer imsi;
    Integer dist;
    }
    15 条回复    2014-09-02 11:37:29 +08:00
    jinyang656
        1
    jinyang656  
       2014-09-02 10:14:33 +08:00   ❤️ 1
    不知道你方法体里怎么操作的,java中除了几种基本数据类型之外都是传引用的。
    buptlee
        2
    buptlee  
    OP
       2014-09-02 10:21:18 +08:00
    @jinyang656
    程序里面就是对dist_matrix和clusterSet进行一些修改。
    传递引用的意思是不是,传递实参的一个副本,因此对实参的修改不会反应到传进去的参数上?
    那如果我希望这种修改能保留,应该怎么做?就像c++的传址那样。thanks.
    chocotan
        3
    chocotan  
       2014-09-02 10:42:59 +08:00   ❤️ 1
    难道楼主在doSomething里这样了.... dist_matrix=new XXX...
    shuson
        4
    shuson  
       2014-09-02 10:46:07 +08:00   ❤️ 1
    main() 声明static没用吧。
    试试update后return一下?
    Aegwynn
        5
    Aegwynn  
       2014-09-02 10:55:14 +08:00   ❤️ 1
    java根本没有传址的说法,这个是人们从C那边搬过来的概念。

    java里面只有传值,不同在于:对基本数据类型,值就是它自身的值;其他是传引用的值。

    想要改变对象的值,就不要去改变它的引用即可。
    defaultuser
        6
    defaultuser  
       2014-09-02 10:57:28 +08:00   ❤️ 1
    @Aegwynn 说的对
    buptlee
        7
    buptlee  
    OP
       2014-09-02 11:08:40 +08:00
    @chocotan 没有,就是拿出dist_matrix里面的某些键值对做了修改,然后重新插入到dist_matrix里面。
    buptlee
        8
    buptlee  
    OP
       2014-09-02 11:12:52 +08:00
    @shuson 可是我有两个实参变量啊。两个都要改变,不能return两个变量吧,毕竟不是Python。
    buptlee
        9
    buptlee  
    OP
       2014-09-02 11:16:09 +08:00
    @Aegwynn 能解释一下,“想要改变对象的值,就不要去改变它的引用即可。”这句话的意思吗,thanks。我的逻辑是这样的:
    while(clusterSet.size()>3){
    updateDistMatrix(dist_matrix,clusterSet);
    }
    当然,每次循环,updateDistMatrix()函数体里面有减少clusterSet项数的逻辑。
    jamiesun
        10
    jamiesun  
       2014-09-02 11:18:15 +08:00   ❤️ 1
    试试不要用函数包裹,直接在循环里顺序执行

    doSomething(dist_matrix);
    doSomething(clusterSet);


    八成是方法里改变了引用。
    buptlee
        11
    buptlee  
    OP
       2014-09-02 11:22:51 +08:00
    @jamiesun 好的,我试试不要函数包裹。
    能不能解释一下,改变了引用具体是指什么呢,刚刚用java不久,好多概念也是边做边学,见笑啦。
    Aegwynn
        12
    Aegwynn  
       2014-09-02 11:23:40 +08:00   ❤️ 1
    @buptlee updateDistMatrix这个方法的源代码都贴出来看看,主要是对clusterSet的操作部分。

    另外建议public void updateDistMatrix(HashMap<Integer ,LinkedList<Node> > dist_matrix,ArrayList<Integer> nearestNodePair,HashMap<Integer,ArrayList<Integer>> clusterSet)
    的方法签名改成
    public void updateDistMatrix(Map<Integer ,List<Node> > dist_matrix,List<Integer> nearestNodePair,Map<Integer,List<Integer>> clusterSet)
    shuson
        13
    shuson  
       2014-09-02 11:34:14 +08:00   ❤️ 1
    @buptlee 对,如果要返回两个值,就不值当再封装后返回了。
    看了回复们,我也是觉得doSomething函数中可能改变了参数的引用,类似重新创建了新的引用并update的是这个新引用,导致原来传入的参数的引用没有被方法执行操作。
    buptlee
        14
    buptlee  
    OP
       2014-09-02 11:35:13 +08:00
    已经贴出来啦,方法签名改成map和list之后有啥好处呢,是不是为了多态?效率上能有所提高吗?thanks
    gangsta
        15
    gangsta  
       2014-09-02 11:37:29 +08:00   ❤️ 2
    sof上的经典问题:
    Is Java “pass-by-reference” or “pass-by-value”?

    http://stackoverflow.com/q/40480/1299675
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2729 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 15:14 · PVG 23:14 · LAX 07:14 · JFK 10:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.