forEach
总结
forEach对于基本数据类型,是直接赋值,对于引用数据类型,是引用地址值。
- 对于基本数据类型,forEach不能修改原数组的值。
- .对于引用数据类型:String,forEach也不能修改原数组的值,因为String是不可变的。
- 对于其他引用类型(不被final修饰),forEach能修改具体的属性,因为forEach是地址引用。
forEach遍历时,是创建的临时变量,引用的数据地址。
对于基本数据类型,int,char,double等,这些值在forEach中进行遍历操作时,是不能修改的。
@Test
public void testInt(){
int[] arr = new int[]{1,2,3,4,5};
//使用foreach遍历arr数组
for(int i : arr){
//如果i=2,那么就将i值变为0
if(i == 2){
i = 0;
}
}
//遍历数组
for(int i : arr){
System.out.print(i + " ");
}
对于以上代码,我们预期输出是1 0 3 4 5,但是实际输出是1 2 3 4 5
forEach在遍历基本数据类型是,相当于是创建了一个临时变量i,我们相对数组元素的修改,实际上都是修改的i值,并不会影响原数据
对于引用数据类型:
特殊:String类:
对于String类,也是不能修改的,因为String是被final修饰,是不可变的。
@Test
public void testString(){
String[] strAll = new String[]{"aa","bb","cc"};
for(String str : strAll){
if("bb".equals(str)){
str = "xx";
}
}
for(String str : strAll){
System.out.print(str + " ");
}
}
对于以上代码,我们预期输出是 aa xx cc ,但是实际输出确实 aa bb cc
开始时内存空间解析:
后面str依次指向aa bb cc
当指向bb时,他想修改其中的值,但是String是不能被修改的,所以他只能重新去创建一个1,但是原数组的指向并没变。,所以最后遍历踹的原数组值也是不会改变的。
对于其他引用类:
例如StringBuilder:
需要注意的是,StringBuilder并没有重写equals()方法,所以在进行equals比较时,只能转化成String来比较。
@Test
public void testStringBuilder(){
StringBuilder[] strBul = new StringBuilder[]{new StringBuilder("111"), new StringBuilder("222"), new StringBuilder("333")};
for(StringBuilder s : strBul){
//StringBuilder并没有重写equals,所以如果直接调用的话,它是比较的地址值。
if("222".equals(s.toString())){
s.append("aaa");
}
}
for(StringBuilder s : strBul){
System.out.println(s);
}
预期输出和实际输出都是 111 222aaa 333
我们自己定义的类:
public class TestForeach {
Person[] pArr = new Person[]{new Person("张三",18),new Person("李四",20),new Person("王六",10)};
public void foreachTestPerson(){
for(Person p : pArr){
if("王六".equals(p.name)){
p.age = 100;
}
}
for(Person p : pArr){
System.out.println(p);
}
}
public static void main(String[] args) {
new TestForeach().foreachTestPerson();
}
}
class Person{
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", id=" + age +
'}';
}
}
特别需要注意:StringBuilder和StringBuffer都是没有重写equals()方法的,不要直接用equals比较!
内存解析:
开始时:
修改后,原数组的地址时没有变的,所以能修改成功。