Java的增強for循環(huán)修改數(shù)組元素的問題小結
曾經沒怎么多想過for each有什么特殊的地方,以為就是for循環(huán)的簡便寫法,直到今天寫力扣發(fā)現(xiàn)了不對勁,使用for each就是過不了,而用正規(guī)for循環(huán)就過了,決定來好好了解一下for each。
而有時候寫增強for循環(huán)又可以修改屬性
最后發(fā)現(xiàn),是否能理解for each的修改與是否理解Java是值傳遞有很大的關系。
(完整代碼放在最后)
決定從基本數(shù)據(jù)類型和引用數(shù)據(jù)類型兩種類型來看。
首先簡單看一下for each的遍歷:
自定義了一個Person類,有name(String)和age(int)兩個屬性。
用int數(shù)組代表基本數(shù)據(jù)類型的數(shù)組,用String類和Person類代表引用數(shù)據(jù)類型的數(shù)組
輸出結果都放在了注釋里面:
public class Main {
public static void main(String[] args) {
// 1.能成功遍歷基本數(shù)據(jù)類型的數(shù)組元素
int[] nums = { 1, 2, 3, 4, 5 };
for (int i : nums) {
System.out.print(i + "\t");
}
// 輸出:1 2 3 4 5
System.out.println();
// 2.能成功遍歷引用數(shù)據(jù)類型的數(shù)組元素
String[] strs = { "acd", "qwe", "oiu" };
for (String string : strs) {
System.out.print(string + "\t");
}
// 輸出:acd qwe oiu
System.out.println();
Person[] persons = { new Person("張三", 12), new Person("李四", 33), new Person("王五", 90) };
for (Person person : persons) {
System.out.print(person + "\t");
}
// 輸出:Person [name=張三, age=12] Person [name=李四, age=33] Person [name=王五, age=90]
System.out.println("-----------------------------------------------------------");
}
class Person {
String name;
int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.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;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}再來看看使用for each來修改數(shù)據(jù):(和上面代碼重復的內容不再寫)
public class Main {
public static void main(String[] args) {
//這些數(shù)據(jù)沒有變
int[] nums = { 1, 2, 3, 4, 5 };
String[] strs = { "acd", "qwe", "oiu" };
Person[] persons = { new Person("張三", 12), new Person("李四", 33), new Person("王五", 90) };
// 3.修改基本數(shù)據(jù)類型的數(shù)組元素的值
for (int i : nums) {
if (i == 4) {
i = 233;
System.out.println("已修改");
}
}
for (int i : nums) {
System.out.print(i + "\t");
}
// 輸出:1 2 3 4 5
// 說明nums數(shù)組并未修改
System.out.println();
// 4.修改引用數(shù)據(jù)類型的數(shù)組元素的值
for (String string : strs) {
if (string.equals("acd")) {
string = "hello world";
System.out.println("已修改");
}
}
for (String string : strs) {
System.out.print(string + "\t");
}
// 輸出:acd qwe oiu
// 說明str數(shù)組并未修改
System.out.println();
for (Person person : persons) {
if (person.name.equals("張三")) {
person.age = 100;
System.out.println("已修改");
}
}
for (Person person : persons) {
System.out.print(person + "\t");
}
// 輸出:Person [name=張三,age=100] Person [name=李四,age=33] Person [name=王五,age=90]
// 說明persons數(shù)組有修改
System.out.println();
}
}結果:int數(shù)組和String數(shù)組多沒能成功修改,而只有Person數(shù)組成功修改了
為什么Person數(shù)組能修改成功呢?因為Java是值傳遞。能理解這個非常重要!
(理解的朋友可以跳過下面這一段)
理解Java是值傳遞:
首先什么是值傳遞,什么是引用傳遞呢?
- 值傳遞是指在調用函數(shù)時將實際參數(shù)復制一份傳遞到函數(shù)中,這樣在函數(shù)中如果對參數(shù)進行修改,將不會影響到實際參數(shù)。
- 引用傳遞是指在調用函數(shù)時將實際參數(shù)的地址直接傳遞到函數(shù)中,那么在函數(shù)中對參數(shù)所進行的修改,將影響到實際參數(shù)。
主要區(qū)別就在于是否將實際參數(shù)復制
那為什么說Java是值傳遞呢?按照這么說,Java其實是將實際參數(shù)復制過傳遞到函數(shù)中的呀!
有人舉例說把int等基本數(shù)據(jù)類型作為參數(shù),并不能修改實參的值,能說明Java是值傳遞,而傳遞Person這種自定義的類,在函數(shù)中修改屬性之后,在主函數(shù)中調用卻能成功修改,這并不能說明Java是值傳遞,反而像引用傳遞呀?
曾經看到一個例子:
- 你的朋友借給你一把鑰匙,你朋友就相當于主函數(shù),你相當于主函數(shù)中調用的另一個函數(shù),鑰匙就是實參,你這個函數(shù)就相當于進入朋友家中,干一些事情之后離開。你拿著這把鑰匙,能打開他們家的大門,于是你進了他們家,砸壞了他們家的電視機(相當于修改Person類的屬性)。當這個函數(shù)結束的時候,就相當于你已經離開了你朋友的家中。你朋友拿著鑰匙打開了自家的門,發(fā)現(xiàn)電視機被砸壞了(相當于你在輸出端看到在主屬性Print的Person的屬性值被修改了),
于是朋友把你揍了一頓。
所以說在子函數(shù)中修改屬性,這個屬性并非是傳遞進來的參數(shù)。傳遞進來的參數(shù)是鑰匙!而不是會被砸的電視機!
Java是值傳遞可以理解為,你拿著你朋友家的鑰匙又復刻了一把,所以現(xiàn)在有兩把鑰匙。你和你朋友都能用兩把鑰匙打開朋友家的門!
意思就是有兩個引用同時指向了同一個地址,第二個復制的引用正是子函數(shù)中的局部變量。無論是用哪一個引用對屬性修改,都能直接在內存中修改,于是會出現(xiàn)傳遞Person類修改屬性會看到成功修改的結果。
如何體現(xiàn)值傳遞的特征呢——修改傳遞過來的值,并不會影響原來的對象:
就好比,你在復刻的鑰匙上寫下自己的名字,你朋友的鑰匙上并不會出現(xiàn)你的名字。
就意味著你用子函數(shù)中的引用去指向一個新對象,而主函數(shù)中的引用并不會去指向那個新對象一樣,還是指向原來的對象。
所以說Java是值傳遞,而并發(fā)引用傳遞!
回到增強for循環(huán):
for(元素類型t 元素變量x : 遍歷對象obj){
引用了x的java語句;
} 增強for循環(huán)的元素變量x,就是一個局部變量,它是引用數(shù)組當前元素引用的副本(就相當于上文所說的你復刻朋友的鑰匙),或者是基本數(shù)據(jù)類型的值的副本。
可以這么理解:
int[] nums = { 1, 2, 3, 4, 5 };
for (int i : nums) {
if (i == 4) {
i = 233;
}
}
//相當于:
for(int j=0;j<nums.length;j++){
int i=nums[j];
if(i==4){
i=233;
}
//所以說修改對于原數(shù)組根本沒有任何影響
}對于String數(shù)組相當于:
for (int j = 0; j < strs.length; j++) {
String i = strs[j];
if (i.equals("acd")) {
i = "hello world";
}
}
//String類是不可變對象,所以這里也沒有任何影響
//輸出:acd qwe oiu對于Person類相當于:
for(int j=0;j<persons.length;j++) {
Person i=persons[j];
if (i.name.equals("張三")) {
i.age = 100; //這里改變的是persons[j].age,而不是persons[j]本身,所以能成功改變
}
}如果是這樣:
for (int j = 0; j < persons.length; j++) {
Person i = persons[j];
if (i.name.equals("李四")) {
i = new Person("A", 80); //i指向一個新對象,輸出結果也毫無變化,不會輸出(A,80)
}
}總而言之:如果想要修改元素就用正規(guī)for循環(huán),不要使用增強for循環(huán)。
所有的代碼:
public class Main {
public static void main(String[] args) {
// 1.能成功遍歷基本數(shù)據(jù)類型的數(shù)組元素
int[] nums = { 1, 2, 3, 4, 5 };
for (int i : nums) {
System.out.print(i + "\t");
}
// 輸出:1 2 3 4 5
System.out.println();
// 2.能成功遍歷引用數(shù)據(jù)類型的數(shù)組元素
String[] strs = { "acd", "qwe", "oiu" };
for (String string : strs) {
System.out.print(string + "\t");
}
// 輸出:acd qwe oiu
System.out.println();
Person[] persons = { new Person("張三", 12), new Person("李四", 33), new Person("王五", 90) };
for (Person person : persons) {
System.out.print(person + "\t");
}
// 輸出:Person [name=張三, age=12] Person [name=李四, age=33] Person [name=王五, age=90]
System.out.println();
System.out.println("-----------------------------------------------------------");
// 3.修改基本數(shù)據(jù)類型的數(shù)組元素的值
for (int i : nums) {
if (i == 4) {
i = 233;
System.out.println("已修改");
}
}
for (int i : nums) {
System.out.print(i + "\t");
}
// 輸出:1 2 3 4 5
// 說明nums數(shù)組并未修改
System.out.println();
// 4.修改引用數(shù)據(jù)類型的數(shù)組元素的值
for (String string : strs) {
if (string.equals("acd")) {
string = "hello world";
System.out.println("已修改");
}
}
for (String string : strs) {
System.out.print(string + "\t");
}
// 輸出:acd qwe oiu
// 說明str數(shù)組并未修改
System.out.println();
for (Person person : persons) {
if (person.name.equals("張三")) {
person.age = 100;
System.out.println("已修改");
}
}
for (Person person : persons) {
System.out.print(person + "\t");
}
// 輸出:Person [name=張三,age=100] Person [name=李四,age=33] Person [name=王五,age=90]
// 說明persons數(shù)組有修改
System.out.println();
System.out.println("-----------------------------------------------------------");
// int數(shù)組相當于:
for (int j = 0; j < nums.length; j++) {
int i = nums[j];
if (i == 4) {
i = 233;
}
// 所以說修改對于原數(shù)組根本沒有任何影響
}
for (int i : nums) {
System.out.print(i + "\t");
}
System.out.println();
// String類相當于
for (int j = 0; j < strs.length; j++) {
String i = strs[j];
if (i.equals("acd")) {
i = "hello world";
}
}
for (String string : strs) {
System.out.print(string + "\t");
}
System.out.println();
// Person類相當于:
persons = { new Person("張三", 12), new Person("李四", 33), new Person("王五", 90) };
for (int j = 0; j < persons.length; j++) {
Person i = persons[j];
if (i.name.equals("張三")) {
i.age = 100; // 這里改變的是persons[j].age,而不是persons[j]本身,所以能成功改變
}
if (i.name.equals("李四")) {
i = new Person("A", 80); // i指向一個新對象,輸出結果也毫無變化,不會輸出(A,80)
}
}
for (Person person : persons) {
System.out.print(person + "\t");
}
}
}
class Person {
String name;
int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.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;
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + "]";
}
}到此這篇關于關于Java的增強for循環(huán)修改數(shù)組元素的問題的文章就介紹到這了,更多相關Java增強for循環(huán)內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
java 獲取HttpRequest Header的幾種方法(必看篇)
下面小編就為大家?guī)硪黄猨ava 獲取HttpRequest Header的幾種方法(必看篇)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09
詳解使用Spring快速創(chuàng)建web應用的兩種方式
這篇文章主要介紹了詳解使用Spring快速創(chuàng)建web應用的兩種方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-11-11
IntelliJ IDEA(或者JetBrains PyCharm)中彈出"IntelliJ IDEA License
今天小編就為大家分享一篇關于IntelliJ IDEA(或者JetBrains PyCharm)中彈出"IntelliJ IDEA License Activation"的解決辦法,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-10-10

