首页编程java编程什么事java中不可变的类 java中一个类是不可变类的条件是什么求详细解答。

什么事java中不可变的类 java中一个类是不可变类的条件是什么求详细解答。

编程之家2023-10-10125次浏览

大家好,感谢邀请,今天来为大家分享一下什么事java中不可变的类的问题,以及和java中一个类是不可变类的条件是什么求详细解答。的一些困惑,大家要是还不太明白的话,也没有关系,因为接下来将为大家分享,希望可以帮助到大家,解决大家的问题,下面就开始吧!

什么事java中不可变的类 java中一个类是不可变类的条件是什么求详细解答。

java中一个类是不可变类的条件是什么求详细解答。

不可变类的唯一判断条件是:

“不可变类的实例在实例的整个生命周期中永远保持初始化的状态”

比如一个类里面有个属性是private List list,然后只提供了getList()方法,但是你还是可以通过getList().add(XXX)来修改list的内容。即是,它没有保持“初始化”状态,它是个可变类。

什么事java中不可变的类 java中一个类是不可变类的条件是什么求详细解答。

来自百度:

可变类和不可变类(Mutable and Immutable Objects)的初步定义:

可变类:当你获得这个类的一个实例引用时,你可以改变这个实例的内容。

什么事java中不可变的类 java中一个类是不可变类的条件是什么求详细解答。

不可变类:当你获得这个类的一个实例引用时,你不可以改变这个实例的内容。不可变类的实例一但创建,其内在成员变量的值就不能被修改。

如何创建一个自己的不可变类:

.所有成员都是private

.不提供对成员的改变方法,例如:setXXXX

.确保所有的方法不会被重载。手段有两种:使用final Class(强不可变类),或者将所有类方法加上final(弱不可变类)。

.如果某一个类成员不是原始变量(primitive)或者不可变类,必须通过在成员初始化(in)或者get方法(out)时通过深度clone方法,来确保类的不可变。

如何创建不可变的Java类或对象

immutable Objects就是那些一旦被创建,它们的状态就不能被改变的Objects,每次对他们的改变都是产生了新的immutable的对象,而mutable Objects就是那些创建后,状态可以被改变的Objects.

举个例子:String和StringBuilder,String是immutable的,每次对于String对象的修改都将产生一个新的String对象,而原来的对象保持不变,而StringBuilder是mutable,因为每次对于它的对象的修改都作用于该对象本身,并没有产生新的对象。

但有的时候String的immutable特性也会引起安全问题,这就是密码应该存放在字符数组中而不是String中的原因!

immutable objects比传统的mutable对象在多线程应用中更具有优势,它不仅能够保证对象的状态不被改变,而且还可以不使用锁机制就能被其他线程共享。

实际上JDK本身就自带了一些immutable类,比如String,Integer以及其他包装类。为什么说String是immutable的呢?比如:java.lang.String的trim,uppercase,substring等方法,它们返回的都是新的String对象,而并不是直接修改原来的对象。

如何在Java中写出Immutable的类?

要写出这样的类,需要遵循以下几个原则:

1)immutable对象的状态在创建之后就不能发生改变,任何对它的改变都应该产生一个新的对象。

2)Immutable类的所有的属性都应该是final的。

3)对象必须被正确的创建,比如:对象引用在对象创建过程中不能泄露(leak)。

4)对象应该是final的,以此来限制子类继承父类,以避免子类改变了父类的immutable特性。

5)如果类中包含mutable类对象,那么返回给客户端的时候,返回该对象的一个拷贝,而不是该对象本身(该条可以归为第一条中的一个特例)

当然不完全遵守上面的原则也能够创建immutable的类,比如String的hashcode就不是final的,但它能保证每次调用它的值都是一致的,无论你多少次计算这个值,它都是一致的,因为这些值的是通过计算final的属性得来的!

Java如何创建不可变类

class:java中class确切的表示为一个类

object:java中object确切的表示为一个对象,也称为类的实例

其实,如果一个类被设计成不可变的类,那么这个类的实例化对象也是不可变的。

不可变类:当你获得这个类的一个实例引用时,你不可以改变这个实例的内容。

那么,什么是不可变对象?

一旦一个类的实例化对象被创建并初始化,那么它就不可以被改变。我们可以调用访问器方法(getter),复制对象,或者传递对象,但是不允许任何方法改变这个对象的状态。包装类(e.g.Integer或Float)和String类是不可变类的代表。

访问器方法(accessormethod):对成员变量做出访问的方法,e.g.getter()方法。

修改器方法(mutatormethod):对成员变量做出修改的方法,e.g.setter()方法。

定义一个不可变类

如果我们要自己创建一个不可变类,需要遵守下面的规则:

将成员变量(field:在一些书中也翻译为域)声明成final并在构造器中初始化。

对于基本类型的成员变量,用final修饰,一旦它被初始化,就不能被改变了。而对于引用类型的成员变量,不能够改变它的引用。

成员变量如果被声明称final,那么构建对象时,必须要初始化这样的域

引用类型是可变的,我们需要采取一些措施来保证它的不可变性。

为什么?如果我们只是声明了一个final的可变引用类型,那么这个引用可以去引用外部的类,或者被其他外部类引用。在这种情况下,我们要做到:

1.这些方法不会改变这些可变对象中的内容

2.不要将这些引用分享到外部供其他类使用,例如,如果对成员变量的引用是可以被其他类改变的,那么这些外部类就可以改变这个类中的内容。

3.如果必须要返回一个引用,那么就返回一个对象的深度拷贝,这样尽管返回的对象内容改变了,但也保存着原始的内容。

只提供访问器方法(i.e.getter方法)不提供修改器方法(i.e.setter方法)

如果一定要改变这个对象的内容,那就创建一个新的不可变对象内容做相应的修改,返回修改后的对象的引用声明类是final的。如果一个类可以被继承,那么它子类就可以重载它的方法,并且修改成员变量

JavaAPI中不可变类的例子

让我们来回顾一下String类,用它来理解上述的几个方面在String类实现中的体现:

所有在Stirng类中成员变量都被声明成private,这些成员变量都在构造器中在构建对象时被初始化。

trimconcatsubstring都可以改变String的对象,为了保证String的不可变性,这些方法都返回的是一个改变相应内容后新的对象。

string类被声明称final,所以任何类都不能继承,重载它的方法。

自己实现一个不可变类

接下来我们自己实现一个不可变类ImmutableCircle。

//ImmutableCircle.java

//Pointisamutableclass

classPoint{

privateintxPos,yPos;

publicPoint(intx,inty){

xPos=x;

yPos=y;

}

publicStringtoString(){

return"x="+xPos+",y="+yPos;

}

intgetX(){returnxPos;}

intgetY(){returnyPos;}

}

//ImmutableCircleisanimmutableclass_thestateofitsobjects

//cannotbemodifiedoncetheobjectiscreated

publicfinalclassImmutableCircle{

privatefinalPointcenter;

privatefinalintradius;

publicImmutableCircle(intx,inty,intr){

center=newPoint(x,y);

radius=r;

}

publicStringtoString(){

return"center:"+center+"andradius="+radius;

}

publicintgetRadius(){

returnradius;

}

publicPointgetCenter(){

//returnacopyoftheobjecttoavoid

//thevalueofcenterchangedfromcodeoutsidetheclass

returnnewPoint(center.getX(),center.getY());

}

publicstaticvoidmain(String[]s){

System.out.println(newImmutableCircle(10,10,20));

}

//othermembersareelided...

}

上面的程序运行之后,打印:

center:x=10,y=10andradius=20

上面的程序体现了不可变类的以下几点:

·这个类被声明成final,不可以被继承,也不可以重载它的方法

·这个类的成员变量都是final并且是私有的

·因为成员变量center是一个引用类型,是可变的,所以在他的getter方法中,返回的是对point对象的拷贝

设计一个不可变的类最关键的一点:

要注意引用类型的成员变量,如果成员变量的类型是可变的引用类型,就必须要采取必要的措施来保护这个成员变量不会被修改

不可变类不足的地方

不可变对象同样也有不足的地方。为了保证不可变性,不可变类中的方法会创建出一定量的对象的拷贝。例如,在上面的代码中,每次调用getcenter方法都会新建并返回一个point对象的拷贝。而假如我们只需要调用一次,返回一个point对象,就没必要费尽心神的去设计一个不可变类,仅仅只需要一个可变的immutablecircle类就可以了。

String类在很多应用场景中都会用到,如果我们调用String类中trim,concat,或者是在循环中调用substring方法,都会创建一个新的临时String对象。同时,java也提供了Stringbuffer和Stringbuilder的可变类。他们同String一样,但是却可以改变这个对象的内容。所以,我们可以根据不同的场景使用String类或者Stringbuffer/Stringbuilder类。

总结,文章的最后还是那句话,要根据自己的实际需要,去设计代码,而不要过度设计。

什么事java中不可变的类的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于java中一个类是不可变类的条件是什么求详细解答。、什么事java中不可变的类的信息别忘了在本站进行查找哦。

java中为什么要实现序列化?Java中为什么要序列化什么时候用到序列化中国石化加油卡积分兑换(中国石化加油卡积分卡)