package com.cantellow.test;
import java.util.Vector;
public class Test {
public static void main(final String[] args) {
final String a = "2";
String b = a;
b = "7";
System.out.println(a);
System.out.println(b);
final JavaClass jc = new JavaClass("qqqqqq");
JavaClass jc2 = jc;
jc2 = new JavaClass("wwwwwwwwww");
System.out.println(jc);
System.out.println(jc2);
final JavaClass jc3 = new JavaClass("rrrrrrrrr");
final JavaClass jc4 = jc3;
jc4.setS("tttttt");
System.out.println(jc3);
System.out.println(jc4);
final JavaClass jc5 = new JavaClass("test vector");
System.out.println(jc5.getVs());
jc5.setVs(new Vector<String>());
jc5.getVs().add("v1");
System.out.println(jc5.getVs());
}
}
class JavaClass {
private String s;
private Vector<String> vs;
public JavaClass(final String s) {
this.s = s;
}
public synchronized String getS() {
return s;
}
public synchronized void setS(final String s) {
this.s = s;
}
public synchronized Vector<String> getVs() {
return vs;
}
public synchronized void setVs(final Vector<String> vs) {
this.vs = vs;
}
@Override
public String toString() {
return s;
}
}
java的类型系统,java除了几个基本类型之外,并没有引用和指针的区分,并不像C++一样,加上&和*就是一种新的类型,而且java的基本类型都是值传递和赋值,非基本类型则是引用传递,但string比较特殊,因为其本身的实现,看起来它的行为基本类型表现一样。
java很简单,所有的对象都必须在堆上new(而不是C++还要区分栈对象和堆对象),我们不能直接操作这些对象,必须通过引用来达到目的,我记得think in java把对象比作电视机,把引用比作遥控器,我觉得很恰当:
上面的程序中,jc和jc2某一时刻都指向统一个对象,但随后jc2指向了新的一个对象,所以输出不一样;
jc3和jc4都指向同一个对象,而且通过jc4作为桥梁修改了这个对象的值,当然jc3所指向的对象也就变了,所以输出一样;
通过jc5我们可以知道两件事,第一件是对象初始类型为null(C++对象没有null概念,只有指针有),第二件就是java中的参数传递确实是引用传递。
#ifndef CPP_CLASS_H
#define CPP_CLASS_H
#include <string>
#include <vector>
#include <iostream>
using std::string;
using std::cout;
using std::endl;
class Object{
public:
int i;
Object(int i){
this->i = i;
}
/*Object& operator=(const Object& t1){
i = t1.i;
return *this;
}
Object(const Object& o){
this->i = o.i;
}*/
};
class CPPClass{
public:
CPPClass():o(1),s("ss"),vs(){
}
Object GetO() const { return o; }
void SetO(Object val) { o = val; }
string GetS() const { return s; }
void SetS(string val) { s = val; }
std::vector<string> GetVs() const { return vs; }
void SetVs(std::vector<string> val) { vs = val; }
Object o;
string s;
std::vector<string> vs;
private:
};
#endif
main函数中:
#include "CPPClass.h"
int main(){
CPPClass cpp;
cout << &cpp.s << " " << &cpp.GetS() << endl;
cout << &cpp.o << " " << &cpp.GetO() << endl;
cout << &cpp.vs << " " << &cpp.GetVs() << endl;
}
输出:
0018FEE8 0018FEC0
0018FEE4 0018FEBC
0018FF08 0018FEA8
要是在返回的类型前面加&,如下:
Object& GetO() { return o; }
string& GetS() { return s; }
std::vector<string>& GetVs() { return vs; }
输出:
0018FEE8 0018FEE8
0018FEE4 0018FEE4
0018FF08 0018FF08
这表明加上&才是真正的返回对象里面的成员,那如果不加&就返回了一个新的对象,那这到底发生什么了呢?
实际上程序临时生成了一个对象,这个对象是通过拷贝构造函数生成的,我们再来看一下参数传递会发生什么事情:
string s2;
Object o2(7);
std::vector<string> vs2;
cpp.SetS(s2);
cpp.SetO(o2);
cpp.SetVs(vs2);
cout << &s2 << " " << &cpp.s << endl;
cout << &o2 << " " << &cpp.o << endl;
cout << &vs2 << " " << &cpp.vs << endl;
输出:
0018FEBC 0018FEE8
0018FEB0 0018FEE4
0018FE94 0018FF08
如果我们同样按照上次的方法将参数传递加一个&,会发生什么呢?
void SetO(Object& val) { o = val; }
void SetS(string& val) { s = val; }
void SetVs(std::vector<string>& val) { vs = val; }
输出:
0018FEBC 0018FEE8
0018FEB0 0018FEE4
0018FE94 0018FF08
并不像我们想的那样是一个地址,也就是他们不是同一个对象,那到底问题出在哪?
所有的这一切,牵涉除了两个概念:拷贝构造函数和操作符重载。