//java.lang.System#arraycopy
/**
* @param src 被拷贝的数组
* @param srcPos 从数组那里开始
* @param dest 目标数组
* @param destPos 从目标数组那个索引位置开始拷贝
* @param length 拷贝的长度
* 此方法是没有返回值的,通过 dest 的引用进行传值
*/
public static native void arraycopy(Object src, int srcPos,Object dest, int destPos, int length);
- src:源数组
- srcPos:源数组要复制的起始位置
- dest:目标数组
- destPos:目的数组放置的起始位置
- length:要复制的长度
注意:src and dest都必须是同类型或者可以进行转换类型的数组
int[] srcArr = {1, 4, 6, 8, 6};
int[] destArr = new int[srcArr.length];
//全部复制
System.arraycopy(srcArr,0, destArr, 0, srcArr.length);
//[1, 4, 6, 8, 6]
System.out.println(Arrays.toString(destArr));
int[] srcArr = {1, 4, 6, 8, 6};
int[] destArr = new int[srcArr.length];
//srcArr中下标3开始,复制两个元素,重destArr开头开始填充
System.arraycopy(srcArr,3, destArr, 0, 2);
//[8, 6, 0, 0, 0]
System.out.println(Arrays.toString(destArr));
int[] srcArr = {1, 4, 6, 8, 6};
int[] destArr = new int[srcArr.length];
//srcArr中下标3开始,复制两个元素,重destArr小标2开头开始填充
System.arraycopy(srcArr,3, destArr, 2, 2);
//[0, 0, 8, 6, 0]
System.out.println(Arrays.toString(destArr));
int[] srcArr = {1, 4, 6, 8, 6};
int[] destArr = new int[srcArr.length];
//全部复制
System.arraycopy(srcArr, 0, destArr, 0, srcArr.length);
//[1, 4, 6, 8, 6]
System.out.println(Arrays.toString(destArr));
srcArr[2] = 666;
//基本值类型的数组,复制的是值,复制出来的数组跟原数组没有任何关系
//[1, 4, 6, 8, 6]
System.out.println(Arrays.toString(destArr));
//只有原数组才被修改了的
//[1, 4, 666, 8, 6]
System.out.println(Arrays.toString(srcArr));
class User {
private String userName;
private Integer userAge;
public User(String userName, Integer userAge) {
this.userName = userName;
this.userAge = userAge;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getUserAge() {
return userAge;
}
public void setUserAge(Integer userAge) {
this.userAge = userAge;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", userAge=" + userAge +
'}';
}
}
User[] srcUser = {new User("蔡徐坤", 18), new User("乔陛萝", 58)};
User[] destUser = new User[srcUser.length];
System.arraycopy(srcUser, 0, destUser, 0, srcUser.length);
System.out.println(Arrays.toString(destUser));
浅拷贝拷贝的是对象的引用,如果对象里面是基本类型也没有影响,应为我们拷贝的是对象的引用
User[] srcUser = {new User("蔡徐坤", 18), new User("乔陛萝", 58)};
User[] destUser = new User[srcUser.length];
System.arraycopy(srcUser, 0, destUser, 0, srcUser.length);
//[User{userName='蔡徐坤', userAge=18}, User{userName='乔陛萝', userAge=58}]
System.out.println(Arrays.toString(destUser));
//修改原数组的数据
srcUser[1].setUserName("我不能露脸");
//打印目的数组,可以发现拷贝的只是引用(浅拷贝)
//[User{userName='蔡徐坤', userAge=18}, User{userName='我不能露脸', userAge=58}]
System.out.println(Arrays.toString(destUser));
User[] srcUser = {new User("蔡徐坤", 18), new User("乔陛萝", 58)};
User[] destUser = new User[srcUser.length];
System.arraycopy(srcUser, 0, destUser, 0, srcUser.length);
//同一个对象
//true
//true
for(int i = 0; i < srcUser.length; i++){
System.out.println(srcUser[i] == destUser[i]);
}
class User {
String userName;
int userAge;
public User(String userName, Integer userAge) {
this.userName = userName;
this.userAge = userAge;
}
@Override
public String toString() {
return "User{" +
"userName='" + userName + '\'' +
", userAge=" + userAge +
'}';
}
}
User[] srcUser = {new User("蔡徐坤", 18), new User("乔陛萝", 58)};
User[] destUser = new User[srcUser.length];
System.arraycopy(srcUser, 0, destUser, 0, srcUser.length);
//[User{userName='蔡徐坤', userAge=18}, User{userName='乔陛萝', userAge=58}]
System.out.println(Arrays.toString(destUser));
//修改原数组的数据
srcUser[1].userName = "我不能露脸";
srcUser[1].userAge = 66;
//打印目的数组,可以发现拷贝的只是引用(浅拷贝)
//[User{userName='蔡徐坤', userAge=18}, User{userName='我不能露脸', userAge=66}]
System.out.println(Arrays.toString(destUser));
BufferedReader源码中的fill()函数用到了System.arraycopy(cb, markedChar, cb, 0, delta)方法,用来进行标记内容拷贝
//java.io.BufferedReader#fill
if (readAheadLimit <= cb.length) {
// 若“当前标记的长度”没有超过了“标记上限(readAheadLimit)”,
// 并且“标记上限(readAheadLimit)”小于/等于“缓冲的长度”;
// 则先将“下一个要被读取的位置,距离我们标记的置符的距离”间的字符保存到cb中。
System.arraycopy(cb, markedChar, cb, 0, delta);
markedChar = 0;
dst = delta;
} else {
// 若“当前标记的长度”没有超过了“标记上限(readAheadLimit)”,
// 并且“标记上限(readAheadLimit)”大于“缓冲的长度”;
// 则重新设置缓冲区大小,并将“下一个要被读取的位置,距离我们标记的置符的距离”间的字符保存到cb中。
char ncb[] = new char[readAheadLimit];
System.arraycopy(cb, markedChar, ncb, 0, delta);
cb = ncb;
markedChar = 0;
dst = delta;
}
class Student implements Cloneable {
private String name;
private int age;
public Student() {}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public int getAge() {return age;}
public void setAge(int age) {this.age = age;}
}
Student s1 = new Student("蔡徐坤", 18);
//s1: Student{name='蔡徐坤', age=18}
System.out.println("s1:\t" + s1);
//使用clone方法实现克隆
Object obj = s1.clone();
Student s2 = (Student) obj;
//s2: Student{name='蔡徐坤', age=18}
System.out.println("s2:\t" + s2);
//s1 == s2: false
System.out.println("s1 == s2:\t" + (s1 == s2));
//此处也可以实现复制,但是此种方法是将s1的地址给了s3,这是如果改变s3里面的东西s1也会跟着变化,但是由于s2是克隆的s1,所以s2并不会被改变
Student s3 = s1;
//s3: Student{name='蔡徐坤', age=18}
System.out.println("s3:\t" + s3);
s3.setAge(68);
s3.setName("乔陛萝");
//s1: Student{name='乔陛萝', age=68}
System.out.println("s1:\t" + s1);
//s2: Student{name='蔡徐坤', age=18}
System.out.println("s2:\t" + s2);
//s3: Student{name='乔陛萝', age=68}
System.out.println("s3:\t" + s3);