当前位置: 首页 > 面试题库 >

java不可变对象问题

干永丰
2023-03-14
问题内容

String abc[]={“abc”};
String def[]={};

def=abc;
def[0]=def[0]+"changed";
System.out.println(abc[0]);

通过更改“ def”对象,我的abc对象也被更改。在String
[]数组旁边有这个特性还有什么其他的Java对象有类似的特性?能解释更多吗?为了防止在更改def时更改abc,我必须执行def =
abc.clone();。


问题答案:

您将对象的可变性/不可变性与引用值的复制混淆了。

在这些图中,[var/index]是参考变量,{{an Object}}是对象。

String abc[]={"abc"};
String def[]={};

   [abc] ------> {{a String[1]}}
                 [0] --------------> {{a String "abc"}}

   [def] ------> {{a String[0]}}

现在,您将def参考变量指向与参考变量相同的对象abc

def=abc;

   [abc] ------> {{a String[1]}}
              /  [0] --------------> {{a String "abc"}}
             /
   [def] ---/    {{a String[0]}}

在这一点上,长度为零的数组是未引用的,应该是垃圾回收的。我们可以将讨论范围缩小到长度为1的数组。请注意,a
String[]是引用数组。在下一行中,您更改了一个数组指向的长度中唯一的元素。

def[0]=def[0]+"changed";

   [abc] ------> {{a String[1]}}
              /  [0] ---------\      {{a String "abc"}}
             /                 \
   [def] ---/                   \--> {{a String "abcchanged"}}

请注意,{{a String "abc"}}它本身并未突变。[abc][def]现在指向相同的{{a String[1]}},这是可变的(例如,你可以让数组的元素,这是引用String对象,以点到任何东西)。

为了防止abc改变我改变def,我必须做def = abc.clone();

实际上,这不是很准确。让我们看看如果您clone()对可变类型的引用的数组StringBuilder

    StringBuilder[] abc = new StringBuilder[] { new StringBuilder("Hello") };
    StringBuilder[] def = abc.clone();
    def[0].append(" world!");
    System.out.println(abc[0]); // prints "Hello world!"

这次我不会为您绘制图表,但是您可以轻松地将其绘制在纸上。这里发生的是,即使使用它自己的元素(即)clone()创建了第二个{{a StringBuilder[1]}}对象def != abc,该元素仍指向同一{{a StringBuilder}}对象(即def[0] == abc[0])。

简而言之:

  • 不变性意味着某种类型的对象不能以任何有意义的方式改变给外部观察者
    • IntegerString等是不可变的
    • 通常,所有值类型应为
  • 数组对象是可变的
    • 它可能是对不可变类型的引用的数组,但是数组本身是可变的
    • 意味着您可以将这些引用设置为所需的任何内容
    • 对于基本数组也是如此
    • 一成不变的数组将不切实际
  • 可以共享对对象的引用
    • 如果对象是可变的,则通过所有这些引用都可以看到突变


 类似资料:
  • 我的目标是让Java对象不可变。我有一个班级< code >学生。为了实现不变性,我用以下方式对它进行了编码: 我的问题是,实现班级不变性的最佳方法是什么?

  • 问题内容: 我正在努力使可变对象与不可变对象有关。使用可变对象会带来很多负面影响(例如,从方法中返回字符串数组),但是我很难理解它的负面影响。使用可变对象的最佳实践是什么?您是否应尽可能避免使用它们? 问题答案: 好吧,这有几个方面。 没有参考身份的可变对象会在奇数时间导致错误。例如,考虑使用基于值的方法的 : 当实例用作键时,实例在映射中“丢失”,因为实例和相等性基于可变值。这些值在映射之外更改

  • 问题内容: Java中不变对象的优点显而易见: 一致状态 自动线程安全 简单 您可以通过使用私有final字段和构造函数注入来支持不变性。 但是,在Java中偏爱不可变对象有哪些弊端? 即 与ORM或Web演示工具不兼容? 不灵活的设计? 实施的复杂性? 是否可以设计一个主要使用不可变对象的大规模系统(深层对象图)? 问题答案: 但是,在Java中偏爱不可变对象有哪些弊端?与ORM或Web演示工具

  • 问题内容: 代码段-1 代码段-2 我在第一个代码段中遇到了竞争。我知道这是因为我正在获得对不可变对象(类型为Integer)的锁定。 我已经写了第二个代码片段,这再次使“布尔”不变。但这有效(输出运行中不显示竞争条件)。如果我正确理解了上一个问题的解决方案,则以下是出现问题的一种可能方法 线程1锁定由指向的对象(例如A) 线程2现在试图获取由指向的对象的锁,并进入A的等待队列。 线程1进入同步块

  • 本文向大家介绍浅谈Python中的可变对象和不可变对象,包括了浅谈Python中的可变对象和不可变对象的使用技巧和注意事项,需要的朋友参考一下 什么是可变/不可变对象 不可变对象,该对象所指向的内存中的值不能被改变。当改变某个变量时候,由于其所指的值不能被改变,相当于把原来的值复制一份后再改变,这会开辟一个新的地址,变量再指向这个新的地址。 可变对象,该对象所指向的内存中的值可以被改变。变量(准确

  • 问题内容: 代码段-1 代码段-2 尽管第二个代码段在不引起任何竞争条件的情况下运行良好,但第一个代码段未能成功同步同一类的不同实例(RequestObject)之间对静态数据成员的访问。有人可以对此进行更多说明。我想了解为什么第一种方法不起作用。 问题答案: 您将不断创建新的对象,然后对其进行同步,这至少使考虑它变得非常混乱。这样就可以得到以下情况: 线程A保持当前值(假设为0) 线程B排队等待