首页 > 解决方案 > Java vs PHP - 方法参数中的引用

问题描述

当在 Java 中使用复杂/非原始/引用数据类型作为方法参数时,对象的引用被传递给方法:

public class Test {

    public static void main(String[] args) {
        String[] array = {"a", "b", "c", "d", "e"};

        System.out.println(Arrays.toString(array)); // [a, b, c, d, e]
        reverseArray(array);
        System.out.println(Arrays.toString(array)); // [e, d, c, b, a]
    }

    private static void reverseArray(String[] array) {
        int startIndex = 0;
        int endIndex = array.length - 1;
        String tmp;
        while (endIndex > startIndex) {
            tmp = array[endIndex];
            array[endIndex] = array[startIndex];
            array[startIndex] = tmp;
            endIndex--;
            startIndex++;
        }
    }
}

相比之下 PHP 似乎“复制”了方法参数:

<?php

Test::main();

class Test {
    
    public static function main() {
        $array = ["a", "b", "c", "d", "e"];
        
        print_r($array); // [a, b, c, d, e]
        self::reverseArray($array);
        print_r($array); // [a, b, c, d, e]
    }
    
    private static function reverseArray($array) {
        $startIndex = 0;
        $endIndex = count($array) - 1;
        $tmp;
        while ($endIndex > $startIndex) {
            $tmp = $array[$endIndex];
            $array[$endIndex] = $array[$startIndex];
            $array[$startIndex] = $tmp;
            $endIndex--;
            $startIndex++;
        }
    }
}

只有在方法参数中添加 & 时,PHP 才会传递对对象的引用:

<?php

Test::main();

class Test {
    
    public static function main() {
        $array = ["a", "b", "c", "d", "e"];
        
        print_r($array);  // [a, b, c, d, e]
        self::reverseArray($array);
        print_r($array);  // [e, d, c, b, a]
    }
    
    private static function reverseArray(&$array) {
        $startIndex = 0;
        $endIndex = count($array) - 1;
        $tmp;
        while ($endIndex > $startIndex) {
            $tmp = $array[$endIndex];
            $array[$endIndex] = $array[$startIndex];
            $array[$startIndex] = $tmp;
            $endIndex--;
            $startIndex++;
        }
    }
}

如果我想在 Java 中模拟 PHP 的“默认”行为(没有 &),我必须复制数组:

public class Test {

    public static void main(String[] args) {
        String[] array = {"a", "b", "c", "d", "e"};

        System.out.println(Arrays.toString(array)); // [a, b, c, d, e]
        reverseArray(Arrays.copyOf(array, array.length));
        System.out.println(Arrays.toString(array)); // [a, b, c, d, e]
    }

    private static void reverseArray(String[] array) {
        int startIndex = 0;
        int endIndex = array.length - 1;
        String tmp;
        while (endIndex > startIndex) {
            tmp = array[endIndex];
            array[endIndex] = array[startIndex];
            array[startIndex] = tmp;
            endIndex--;
            startIndex++;
        }
    }
}

我现在的问题是:

  1. 当我不专门使用引用时,PHP 是否会复制每个方法参数?如果是,这不是很昂贵(就计算时间和空间而言)?
  2. 为什么 Java 和 PHP 使用不同的“默认”方法来传递方法参数?一种或另一种方式有明显的优势吗?

标签: javaphpmethodsparametersreference

解决方案


@AterLux 的回答很好地解释了 PHP 方面。

但是,关于您的后续问题的一些见解:

为什么 Java 和 PHP 使用不同的“默认”方法来传递方法参数?一种或另一种方式有明显的优势吗?

“简单”是旁观者眼中的一个术语。例如,采用标识符命名(方法的名称)的方法。在 java 中,标识符正是它们的本质(例如,区分大小写)。在 PHP 中,它们不区分大小写。

在一个“心态”中,PHP 的选择是“更简单”:作为一名脚本编写者,我不必担心复制大小写。有关于“为什么这不起作用”的问题,问题是他们将他们的方法命名为“checkFoo”并调用“checkfoo”。

在另一种“思维方式”中,Java 的选择“更简单”:在土耳其语言环境中,带点的 i 和不带点的 i 是有区别的。因此,在土耳其语中,"i".toUpperCase()实际上是"İ""I".toLowerCase()实际上是"ı"。PHP 做“不区分大小写”的方式是在内部将所有内容大写并将其扔进一个大哈希映射中(我有点过于简单化了),这导致了一个众所周知的问题,在土耳其语言环境中,大多数 PHP 脚本只是直接向上不工作,因为混合 'i' 和 'I' 现在将不再转换为相同的大写字符序列。这样一来,PHP 解决方案比 java 解决方案复杂得多。看?它在旁观者的眼中。

但是这里有一个趋势:如果你完全了解它的底层是如何工作的,java 几乎总是比 PHP 简单得多。如果您只是在做首先想到的事情,那么 PHP 往往会“更简单”。PHP 试图“帮助”你,第二次猜测,试图预测你的意图并采取相应的行动。例如,让我们以其他“试图猜测”的语言为例:javascript,1是“真实的”——如果用作布尔值,javascript 会看着它的水晶球,并猜测你打算让它成为真的。Java 不这样做。true是真的,就是这样。if (1) {}在java中甚至不编译。

在这种情况下,java 在 java 方式中是“简单的”:原语是它们本身,所有非原语都是参考。这些引用是按值传递的。没有 C 风格&*- 这就是你得到的。

PHP 在 PHP 方式中是“简单的”:它试图兜售一切都是按值传递的概念,并在不低效的情况下使其工作,数组被打包传递,因此不需要实际的副本,但是如果您传递数组的函数对其进行了更改,则它会进行复制。除了这对对象来说太棘手了,所以那些总是通过引用传递的。

我想说 PHP 随意的一致性方法导致了一种令人难以置信的不一致语言

这也意味着 java 乍一看往往有点奇怪,因为“一旦你完全理解它是如何工作的,就有意义”通常与“当你在没有太多理解的情况下做你想做的事情”是不一致的。然而,鉴于我们还没有发明一种可以围绕愚蠢的程序员工作的语言,作为一项规则,我会提倡 java 学派关于“简单”的含义,而不是 PHP 学派。因此,我会回答你的问题:

Java 试图让模型变得简单,PHP 试图让体验变得简单,这就解释了不同之处。然而,java 这样做的方式有一个明显的优势。


推荐阅读