//第一个类
public class Card {
public char suit;
public String rank;
    public Card(char suit, String rank) {
      this.suit = suit;
      this.rank = rank;
     }
    
 public String toString() {
  return   suit+rank;
 }
}
//第二个类
public class JLab1201 {
static final char suits[] ={'H','S','D','C'};
static final String ranks[] ={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
static Card[] cards=new Card[52];
/**
 * 初始化扑克牌数组
 */
public static void init(){
for(int i=0;i<suits.length;i++){
for(int j=0;j<ranks.length;j++){
cards[i*ranks.length+j]=new Card(suits[i],ranks[j]);
}
}
}
public static void swap1(Card c1,Card c2){
Card c=c1;
c1=c2;
c2=c;
}
public static void swap1(int i,int j){
Card c=cards[i];
cards[i]=cards[j];
cards[j]=c;
}
public static void swap2(Card c1,Card c2){
char s=c1.suit;
c1.suit=c2.suit;
c2.suit=s;
String r=c1.rank;
c1.rank=c2.rank;
c2.rank=r;
}
/**
 * @param args
 */
public static void main(final String[] args) {
init();
//任取两张牌
Card c1=cards[10];
Card c2=cards[12];
System.out.println("第11张牌是:"+c1+"\t第13张牌是:"+c2);
}
}问题:1) 在main方法中,添加下面几行语句,分析结果
swap1(c1,c2);
System.out.println("执行swap1(c1,c2)后");
System.out.println("c1引用的牌是:"+c1+"\tc2引用的牌是:"+c2);
System.out.println("第11张牌是:"+cards[10]+"\t第13张牌是:"+cards[12]);2) 在main方法中,去掉刚才添加的语句,添加下面几行语句,分析结果
swap1(10,12);
System.out.println("执行swap1(10,12)后");
System.out.println("c1引用的牌是:"+c1+"\tc2引用的牌是:"+c2);
System.out.println("第11张牌是:"+cards[10]+"\t第13张牌是:"+cards[12]);3) 在main方法中,去掉刚才添加的语句,分析结果
swap2(c1,c2);
System.out.println("执行swap2(c1,c2)后");
System.out.println("c1引用的牌是:"+c1+"\tc2引用的牌是:"+c2);
System.out.println("第11张牌是:"+cards[10]+"\t第13张牌是:"+cards[12]);
模拟运行了一下,第二个和第三个的结果出乎我的意料。 求高手详细解释一下!

解决方案 »

  1.   

    public static void swap1(Card c1,Card c2){ 
    //LZ先想想这里的参数的c1,c2和main方法的c1,c2是不是相同的变量?
    //每个方法有自己的栈,每个局部变量属于自己的方法栈,所以这里的c1,c2和main的c1,c2不是相同变量
     Card c=c1;
     c1=c2; //所以这里是让swap1的c1指向了别的对象,但是main方法的c1不变,因为这两个c1不是同一个
     c2=c;
     }
     
    public static void swap1(int i,int j){ //这里传进来的参数i是10,j是12
    //数组就不用解释了,因为main方法的c1就是指向cards[i],c2就是指向cards[j]
    //所以cards[i]变成什么,c1就指向什么,cards[j]变成什么c2就指向什么
     Card c=cards[i];
     cards[i]=cards[j];
     cards[j]=c;
     }public static void swap2(Card c1,Card c2){
    //重点要说的是这个,要说这个和swap1的区别
    //首先上面swap1的说明已经说了,这里的c1,c2和main的c1,c2是两个不同的变量
    //但是这两个不同的变量指向的对象相同,也就是两个c1虽然不是同一个变量,但它们都指向cards[10]对象
     char s=c1.suit;
     c1.suit=c2.suit; //所以这里就是改变cards[10]的suit属性
     c2.suit=s;//这里是改变cards[12]的suit属性
     String r=c1.rank;
     c1.rank=c2.rank; //这里就是改变cards[10]的rank属性
     c2.rank=r;//这里是改变cards[12]的rank属性
    //因为main方法的c1指向cards[10],c2指向cards[12],而cards[10],cards[12]的属性改变了,
    //所以也就是c1,c2所指向的对象改变了,所以打印结果就变了
     }打个比方,我是main方法的c1,LZ是swap1方法的c1,cards[10]我们看作现在浏览的网页,我们一起指向cards[10]这个对象,也就是相当于我们一起浏览这个网页,那么swap1的c1=c2,就相当于LZ你改变了指向,浏览别的网页去了,那么,当然,我的浏览还是没变,我还是在浏览这个网页,也就是main的c1没变。而swap2的方法c1.suit=c2.suit相当于LZ你修改了cards[10]的suit属性,也就是相当于LZ你修改了现在浏览的网页的内容,那么很显然,因为我也在浏览这个网页,所以我浏览的内容也改变了,也就是main方法的c1变了。
    不知道这个说明,LZ能不能理解。  
      

  2.   


    谢啦!不过我还是不明白一点。从我运行的结果来看,第二个数组那个交换,虽然HJ和HK在数组中交换位置,但输出结果是:c1仍然引用的是HJ,c2仍然引用的是HK,这是为什么?c1和c2应该是指向cards[10]和cards[12]这两块空间的地址,既然空间内部的数据变了,为什么它们的引用没有变呢?
      

  3.   

    因为java不像C/C++有那样强大的指针,传一个值进去,就相当于在栈内存中开辟了一块区域,当swap这个方法运行完了之后,栈内存里面开辟的地址就会消失,所以你第2个swap是没有任何作用的,C/C++也一样的swap(int a, int b)你去试试看也没有用,只有swap(int *a, int *b)用指针去交换才有用,当然你第3个swap也是同样的原因因为你没有使用new这个关键字,这个数组其实就是开辟在栈里面的,你交换的无非是栈里面的地址,new这个关键字跟C里面的malloc函数是一样的。楼主好好去看一下指针这个东西,就会明白我说的。
      

  4.   

    c1仍然引用的是HJ,c2仍然引用的是HK,这是为什么?c1和c2应该是指向cards[10]和cards[12]这两块空间的地址,既然空间内部的数据变了,为什么它们的引用没有变呢?
    ----------------------------------------------------------
    执行了swap1(10,12);后,空间内部的数据并没有改变,只是
    cards[10]指向了cards[12],cards[12]指向了cards[10]。
    而c1和c2仍然指向原来的地址。执行了swap2(c1,c2);后,空间内部的数据才改变,原来指向cards[10]和
    cards[12]的c1和c2也跟着输出了改变后的数据。