一个关于内存变量地址转换的有关问题

一个关于内存变量地址转换的问题
先把代码贴上
public class ArrayTest2 {

public static void swap(int[] arg0) {
arg0[3] = 88;
}

public static void swap(int arg1){
arg1 = 2; 
}

public static void main(String[] args) {

int[] a = { 1, 2, 3, 4, 5, 6 };

int b = 5;

System.out.println(a[3]);

swap(a);

swap(b);

System.out.println(a[3]);

System.out.println(b);
}
}

打印的值为  4  88  5
想问下,为什么数组在经过变换后 ,改变了其中的一个的值。而变量却不可以。好像听老师讲过,要想修改一个变量的值,只能修改变量的地址。我记得java里的变量传递不是值传递吗?

这其中的具体原因不是很明白 ,求解答一下。
另外我附上c 改变变量值的做法 。大神顺便一块解答了吧。
# include <stdio.h>

void f(int * p)
{
*p = 10; // i = 10;
}

int main(void)
{
int i = 5;

f(&i);
printf("i = %d\n", i);

return 0;
}

------解决方案--------------------
java中int 是基本数据类型, int[] 是数组,为引用数据类型。
java中引用数据类型作为参数传递是传递的是堆内存中的地址
而基本数据类型作为参数传递是传递的数值,传递后与原来的变量已没有关系,所以不会改变
------解决方案--------------------
在C中有指针类型,而且你可以通过&获取一个变量的地址,所以你可以把一个变量的地址作为参数传进函数,从而通过指针改变变量的值
比如上例中的f(&i),就是取i的地址,然后传递给void f(int * p)中的指针参数p,这样通过指针解引用*p=10你就可以改变原来那个变量的值。

但是Java第一没有指针类型,第二不能轻易获取一个变量的地址,所以比如int b = 5; swap(b),你传进去的只是b变量的值,而不是b的地址,而由于没有指针类型,就算你得到了地址,你也无法通过地址改变变量的值。

而Java中的引用类型,实际上是被弱化的指针类型,比如int[] a,那么a相当于C中的int *a,就是指向int的一个指针,既然是指针,那么你作为参数传递给函数,就可以达到修改原来变量的值的目的,比如arg0[3] = 88相当于C中*(arg0+3)=88。