Java ArrayList修改由";返回的值;获得;方法

Java ArrayList修改由";返回的值;获得;方法,java,android,arraylist,Java,Android,Arraylist,我有以下两种情况与ArrayListget方法相关,一种是自定义类,另一种是字符串类: 1。下面是修改自定义类ArrayList元素的示例: ArrayList<MyClass> mTmpArray1 = new ArrayList<MyClass>(); MyClass myObj1 = new MyClass(10); mTmpArray1.add(myObj1); MyClass myObj2 = mTmpArray1.get(0); myObj2.myI

我有以下两种情况与ArrayList
get
方法相关,一种是自定义类,另一种是字符串类:

1。下面是修改自定义类ArrayList元素的示例:

ArrayList<MyClass> mTmpArray1 = new ArrayList<MyClass>();
MyClass myObj1 = new MyClass(10);  
mTmpArray1.add(myObj1);

MyClass myObj2 = mTmpArray1.get(0);  
myObj2.myInt = 20;

MyClass myObj3 = mTmpArray1.get(0);  
Log.d(TAG, "Int Value:"+myObj3.myInt);    // Prints "20" 
ArrayList<String> mTmpArray2 = new ArrayList<String>();  
mTmpArray2.add("Test_10");

String myStr1 = mTmpArray2.get(0);
myStr1 = "Test_20";

String myStr2 = mTmpArray2.get(0);
Log.d(TAG, "Str Value:"+myStr2);  // Prints "Test_10" 
ArrayList mTmpArray1=新的ArrayList();
MyClass myObj1=新的MyClass(10);
mTmpArray1.add(myObj1);
MyClass myObj2=mTmpArray1.get(0);
myObj2.myInt=20;
MyClass myObj3=mTmpArray1.get(0);
Log.d(标记,“Int值:”+myObj3.myInt);//打印“20”
2。下面是修改字符串ArrayList元素的示例:

ArrayList<MyClass> mTmpArray1 = new ArrayList<MyClass>();
MyClass myObj1 = new MyClass(10);  
mTmpArray1.add(myObj1);

MyClass myObj2 = mTmpArray1.get(0);  
myObj2.myInt = 20;

MyClass myObj3 = mTmpArray1.get(0);  
Log.d(TAG, "Int Value:"+myObj3.myInt);    // Prints "20" 
ArrayList<String> mTmpArray2 = new ArrayList<String>();  
mTmpArray2.add("Test_10");

String myStr1 = mTmpArray2.get(0);
myStr1 = "Test_20";

String myStr2 = mTmpArray2.get(0);
Log.d(TAG, "Str Value:"+myStr2);  // Prints "Test_10" 
ArrayList mTmpArray2=新的ArrayList();
mTmpArray2.添加(“试验10”);
字符串myStr1=mTmpArray2.get(0);
myStr1=“测试20”;
字符串myStr2=mTmpArray2.get(0);
Log.d(标签,“Str值:”+myStr2);//打印“测试10”
因此,在MyClass ArrayList的情况下,当我调用
get
并修改值时,当我再次执行
get
时,我看到更改正在反映出来

但当我修改字符串ArrayList时,同样的方式,那个么更改并没有反映出来

两种情况下的
get
方法有什么不同?

对于String,String类创建深度复制并返回新对象,对于自定义类创建浅层复制吗


在适用于“LinkedHashMap”的第一个场景中,“HashMap”和“List”?

字符串是不可变的。您没有将新字符串插入数组列表

当您执行
String myStr2=mTmpArray2.get(0)时,即使您指向ArrayList中的引用,任何更改该值的尝试都将(由于字符串不变性)创建一个不再引用ArrayList的新字符串(myStr2)

当您执行
myStr1=“xxx”
操作时,实际上并不是在更改ArrayList引用,而是在更改从ArrayList抓取的一个新(副本)(现在称为myStr1),它具有本地作用域

阅读有关字符串的更多信息:

现在在第一个示例中,您指向一个可变对象(您的自定义类),因此您实际上通过引用更改了直接值。欢迎来到Java

不相关的:此代码:
MyClass myObj1=新的MyClass(10)被(可以说)认为是坏的。最好使用更易于阅读的工厂模式。换句话说,带有参数的公共构造函数很难阅读(例如,当我阅读您的代码时,我不知道我在构造什么)

(也许)更好的方法是:
MyClass myObj=MyClass.createInstanceWithCapacity(10);//我发明这个名字是因为我不知道你的10是什么,但看看这两个,你认为哪一个乍一看更容易理解?


免责声明:上述无关评论是我个人的意见,并非所有开发者都会同意。;)

您的客户在这两种情况下做的事情不同

在此更新对象的状态,因此更改会影响列表中存储的对象:

myObj2.myInt = 20;
myStr1.setSomething(...);
在这里,您将为局部变量指定一个新对象,因此列表不受影响:

myStr1 = "Test_20";
myObj2 = new MyClass (...);
如果
String
是可变的,您可以通过调用某个方法来修改字符串,并且更改会反映在列表中存储的对象中:

myObj2.myInt = 20;
myStr1.setSomething(...);
另一方面,如果在第一种情况下更改了局部变量的值,则存储在列表中的对象不会受到影响:

myStr1 = "Test_20";
myObj2 = new MyClass (...);

这两个“get”调用之间没有区别。区别在于ArrayList所持有的类型和“get”方法返回的引用之间的区别

在第一个示例中,您可以执行以下操作:

MyClass myObj2 = mTmpArray1.get(0);  
myObj2.myInt = 20;
String myStr1 = mTmpArray2.get(0);
myStr1 = "Test_20";
在这里,您将在位置0的ArrayList中获得对MyClass实例的引用,并且您正在修改此实例中的一个字段

在第二个示例中,您可以执行以下操作:

MyClass myObj2 = mTmpArray1.get(0);  
myObj2.myInt = 20;
String myStr1 = mTmpArray2.get(0);
myStr1 = "Test_20";
在这里,您将获得对数组列表中字符串实例的引用,然后您将向myStr1提供对您创建的另一个字符串的引用(“Test_20”)。就好像你写了
myObj2=newmyclass(20)在第一个示例的第二行中

简言之,在第一个示例中,您可以通过从抓取的引用更改对象内的字段来访问该字段。在第二个示例中,您只是将引用更改为指向不同的字符串


我还应该提到,在Java中,字符串是不可变的,这意味着一旦创建了字符串,就不能对其进行更改。

String是一个不可变的类。线条

myStr1 = "Test_20";
不会更改myStr1
所指向的字符串对象的值。相反,将创建一个新字符串,并修改
myStr1
以指向新字符串。原始字符串保持不变,可以从ArrayList中检索

您的
MyClass
对象显然是可变的。仅创建一个实例,其状态由赋值更改

myObj2.myInt = 20;

因此,当从ArrayList中检索此对象时,将看到其新状态。

在第二个示例中,您只需不更改列表即可

在第一个示例中,您正在执行以下操作:

  • 从列表中获取第一个对象,并将其存储在名为“myObj2”的变量中
  • 通过设置此对象的int值,修改存储在变量“myObj2”中的对象
  • 但你的第二个例子完全不同:

    String myStr1 = mTmpArray2.get(0);
    myStr1 = "Test_20";
    
    让我来翻译一下:

  • 从列表中获取第一个元素,并将其存储在名为“myStr1”的变量中
  • 将变量“myStr1”的值设置为“Test\u 20”
  • 因此,在第一种情况下,您正在修改列表中存储的对象的变量。在第二种情况下,您正在检索列表中存储的对象,然后重新使用存储该检索对象的变量并将其用于新的内容,但这当然不会改变原始列表

    修改您的列表