如何使用与C++;Java中的引用参数?
假设我在C++中有这个:如何使用与C++;Java中的引用参数?,java,c++,reference,Java,C++,Reference,假设我在C++中有这个: void test(int &i, int &j) { ++i; ++j; } 这些值在函数内部更改,然后在外部使用。我怎样才能在Java中编写一个同样的代码?我想我可以返回一个封装两个值的类,但看起来确实很麻烦。 java没有C++引用的等价物。实现此功能的唯一方法是将值封装在另一个类中,并在该类中交换值 关于这个问题,这里有一个冗长的讨论:嗯,有两个解决办法。你自己也提到过。另一个是: public void test(int[]
void test(int &i, int &j)
{
++i;
++j;
}
这些值在函数内部更改,然后在外部使用。我怎样才能在Java中编写一个同样的代码?我想我可以返回一个封装两个值的类,但看起来确实很麻烦。
java没有C++引用的等价物。实现此功能的唯一方法是将值封装在另一个类中,并在该类中交换值
关于这个问题,这里有一个冗长的讨论:嗯,有两个解决办法。你自己也提到过。另一个是:
public void test(int[] values) {
++values[0];
++values[1];
}
不过,我会选择自定义对象。这是一种更干净的方式。另外,尝试重新安排您的问题,以便单个方法不需要返回两个值。Java没有按引用传递。您必须封装以实现所需的功能。Jon Skeet简要介绍了为何Java中不包含pass-by-reference。您可以构造装箱对象,即
Integer iObj = new Integer(i);
Integer jObj = new Integer(j);
把你的日常工作写成
public void test(Integer i, Integer j){
i = i.add(1);
j = j.add(1);
}
无论出于何种原因,Java的设计者都觉得按值调用更好;它们故意不包含引用调用的方法。(严格地说,它们将引用的副本传递给对象,对于原语类型,它们的特殊情况是纯粹按值调用。但效果是一样的。)您必须以某种方式将其装箱
整数是不可变的。真没用。
int是可变的,但由于java是按值传递的,所以在这种情况下它也不可用。
有关更多说明,请参见以下页面:和
apachecommons lang有一个MutableInt类。或者你可以自己写
无论如何,它不应该那么糟糕,因为它不应该经常发生。如果确实如此,那么您应该明确地改变用Java编写代码的方式。使用包装器模拟引用。
一种模拟这种行为的方法是创建一个通用包装器
public class _<E> {
E ref;
public _( E e ){
ref = e;
}
public E g() { return ref; }
public void s( E e ){ this.ref = e; }
public String toString() {
return ref.toString();
}
}
公共类\u{
E参考;
公众(E){
ref=e;
}
public E g(){return ref;}
公共空间s(E E){this.ref=E;}
公共字符串toString(){
返回ref.toString();
}
}
我不太相信这段代码的价值,因为我无法控制它,我不得不编写它:)
就是这样
示例用法:
public class Test {
public static void main ( String [] args ) {
_<Integer> iByRef = new _<Integer>( 1 );
addOne( iByRef );
System.out.println( iByRef ); // prints 2
_<String> sByRef = new _<String>( "Hola" );
reverse( sByRef );
System.out.println( sByRef ); // prints aloH
}
// Change the value of ref by adding 1
public static void addOne( _<Integer> ref ) {
int i = ref.g();
ref.s( ++i );
// or
//int i = ref.g();
//ref.s( i + 1 );
}
// Reverse the vale of a string.
public static void reverse( _<String> otherRef ) {
String v = otherRef.g();
String reversed = new StringBuilder( v ).reverse().toString();
otherRef.s( reversed );
}
}
公共类测试{
公共静态void main(字符串[]args){
_iByRef=new u1;
addOne(iByRef);
System.out.println(iByRef);//打印2
_sByRef=新的(Hola);
反向(sByRef);
System.out.println(sByRef);//单独打印
}
//通过添加1更改ref的值
公共静态void addOne(ref){
int i=参考g();
参考s(++i);
//或
//int i=参考g();
//参考s(i+1);
}
//倒转绳子的长度。
公共静态无效反向(otherRef){
字符串v=otherRef.g();
字符串反转=新的StringBuilder(v).reverse().toString();
其他参考(反向);
}
}
这里有趣的是,通用包装器类名是“_”,这是一个有效的类标识符。因此,声明如下:
对于整数:
_<Integer> iByRef = new _<Integer>( 1 );
\uibyref=new(1);
对于字符串:
_<String> sByRef = new _<String>( "Hola" );
\usbyref=new(“Hola”);
任何其他课程
_<Employee> employee = new _<Employee>( Employee.byId(123) );
\uemployee=new(employee.byId(123));
方法“s”和“g”代表set和get:p一个更好的问题:为什么要创建具有这种副作用的方法
通常,这强烈表明您应该将数据提取到一个单独的类中,并使用公共访问器描述操作发生的原因。这两个整数相关吗?比如一对x/y坐标?如果是这样,我将把整数放在一个新类中,并将该类传递到方法中
class A{
public void test(Coord c)
{
c.x++;
c.y++;
}
private class Coord{
public int x, y;
}
}
如果这两个整数不相关,您可能需要考虑一下为什么首先要将它们传递到同一个方法中。尽管这是一种糟糕的设计模式,但另一种可能的解决方案是
static void test(AtomicInteger i, AtomicInteger j)
{
i.incrementAndGet();
j.incrementAndGet();
}
最简单的解决方案是使用不需要自己编写的类。Java按值传递参数,并且没有允许按引用传递的机制。这仍然不会更改方法外的对象,因为整数是不可变的。你从哪里知道Integer有一个add()方法?总之,正如Bombe指出的那样,整数是不可变的,这就给你留下了完全相同的问题(但需要更多的输入);他是添加这些方法的人。你可以改为传入AtomicInteger,这是可变的。这不是它的预期目的,但几乎可以让这个方法工作。这不起作用,因为对象引用是按值传递的,就像java中的一切一样。读这个。Java只传递对象引用。您可以认为它们本质上与boost shared_ptr相同。只需将基本体框入对象中,即可设置。你可能想更正你问题的措辞。对不起,我必须插话。C++中的引用引用参数是邪恶的。不要这样做。@Steve Lacey-为什么他们是邪恶的?