java - 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++;
}
}
}
我现在的问题是:
- 当我不专门使用引用时,PHP 是否会复制每个方法参数?如果是,这不是很昂贵(就计算时间和空间而言)?
- 为什么 Java 和 PHP 使用不同的“默认”方法来传递方法参数?一种或另一种方式有明显的优势吗?
解决方案
@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 这样做的方式有一个明显的优势。
推荐阅读
- reactjs - Firebase Google 身份验证未显示电子邮件地址
- java - 在Java中计算一个标准差中的数据百分比?
- c# - PlayerPrefs 无法在 Android 设备上运行
- html - 下一页按钮未显示在页面 css/html 的右侧
- algorithm - Quicksort Hoare 的分区
- python - 用出现次数替换连续元素
- python - 将 Series 添加到 DataFrame 会导致奇怪的行为
- java - Springboot - 验证@RequestBody
- python - 如何在python中保存网站中的所有图像
- flutter - 将字符串实时传递给另一个类