当前位置:首页 » 编程语言 » java不可变对象

java不可变对象

发布时间: 2022-12-11 02:31:28

❶ 为什么String对象称为不可变的

java里面对它的这么设定的,final修饰的。
不可变是创建后的对象不可以改变的意思。
好处:
1 不可变对象可以提高String Pool(字符串常量池)的效率和安全性。
2 对于多线程是安全的,因为在多线程同时进行的情况下,一个可变对象的值很可能被其他线程改变这样会造成不可预期的结果,使用不可变对象就可以避免这种情况出现。
java将String设成不可变最大的原因是效率和安全。

但是当你需要向字符串插入或修改的时候,Sting不可变类型就显得足襟见肘,这时候就需要一个可变的字符串类型:StringBuffer。
所以String和StringBuffer都存在。

❷ JAVA中为什么说Double类是不可变类呢

对象本身,内部并没有提供可以修改他本身的值的方法,因此这是一个不可变的类,比如他占用了一块内存,赋值了2,那么你通过Double类本身的API是不能修改2这个值的,他这块内存保存的就是2
再告诉你一个知识点,实际上,如果你用反射来修改Double的话,是可以做到修改这块内存对应的值的

❸ 云南java培训学校告诉你java一些能降低竞争锁的方法

本文介绍一下提升并发可伸缩性的一些方式:减少锁的持有时间,降低锁的粒度,锁分段、避免热点域以及采用非独占的锁或非阻塞锁来代替独占锁。



减少锁的持有时间

降低发生竞争可能性的一种有效方式就是尽可能缩短锁的持有时间。例如,可以将一些与锁无关的代码移出同步代码块,尤其是那些开销较大的操作,以及可能被阻塞的操作,例如I/O操作。


降低锁的粒度

另一种减小锁的持有时间的方式是降低线程请求锁的频率(从而减小发生竞争的可能性)。这可以通过锁分解和锁分段等技术来实现,在这些技术中将采用多个相互独立的锁来保护独立的状态变量,从而改变这些变量在之前由单个锁来保护的情况。这些技术能减小锁操作的粒度,并能实现更高的可伸缩性,然而,使用的锁越多,那么发生死锁的风险也就越高。


锁分段

在某些情况下,可以将锁分解技术进一步扩展为对一组独立对象上的锁进行分解,这种情况被称为锁分段。例如,在ConcurrentHashMap的实现中使用了一个包含16个锁的数组,每个锁保护所有散列桶的1/16,其中第N个散列桶由第(Nmod16)个锁来保护。假设散列函数具有合理的分布性,并且关键字能够实现均匀分布,那么这大约能把对于锁的请求减少到原来的1/16。正是这项技术使得ConcurrentHashMap能够支持多达16个并发的写入器。(要使得拥有大量处理器的系统在高访问量的情况下实现更高的并发性,还可以进一步增加锁的数量,但仅当你能证明并发写入线程的竞争足够激烈并需要突破这个限制时,才能将锁分段的数量超过默认的16个。)


避免热点域

如果一个锁保护两个独立变量X和Y,并且线程A想要访问X,而线程B想要访问Y(这类似于在ServerStatus中,一个线程调用addUser,而另一个线程调用addQuery),那么这两个线程不会在任何数据上发生竞争,即使它们会在同一个锁上发生竞争。当每个操作都请求多个变量时,锁的粒度将很难降低。这是在性能与可伸缩性之间相互制衡的另一个方面,一些常见的优化措施,例如将一些反复计算的结果缓存起来,都会引入一些“热点域(HotField)”,而这些热点域往往会限制可伸缩性。当实现HashMap时,你需要考虑如何在size方法中计算Map中的元素数量。最简单的方法就是,在每次调用时都统计一次元素的数量。一种常见的优化措施是,在插入和移除元素时更新一个计数器,虽然这在put和remove等方法中略微增加了一些开销,以确保计数器是最新的值,但这将把size方法的开销从O(n)降低到O(l)。


代替独占锁

第三种降低竞争锁的影响的技术就是放弃使用独占锁,从而有助于使用一种友好并发的方式来管理共享状态。例如,使用并发容器、读-写锁、不可变对象以及原子变量。昆明北大青鸟http://www.kmbdqn.cn/发现ReadWriteLock能提供比独占锁更高的并发性。而对于只读的数据结构,其中包含的不变性可以完全不需要加锁操作。


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

不可变类的唯一判断条件是:
“ 不可变类的实例在实例的整个生命周期中永远保持初始化的状态”

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

来自网络:

可变类和不可变类(Mutable and Immutable Objects)的初步定义:
可变类:当你获得这个类的一个实例引用时,你可以改变这个实例的内容。
不可变类:当你获得这个类的一个实例引用时,你不可以改变这个实例的内容。不可变类的实例一但创建,其内在成员变量的值就不能被修改。
如何创建一个自己的不可变类:
.所有成员都是private
.不提供对成员的改变方法,例如:setXXXX
.确保所有的方法不会被重载。手段有两种:使用final Class(强不可变类),或者将所有类方法加上final(弱不可变类)。
.如果某一个类成员不是原始变量(primitive)或者不可变类,必须通过在成员初始化(in)或者get方法(out)时通过深度clone方法,来确保类的不可变。

❺ java函数式编程是炫技编程吗

函数式编程(Functional Programming)是一种编程风格,它是相对于指令式编程风格而言的,常见的面向对象编程就是指令式编程风格。

指令式编程是面向计算机硬件的抽象,有变量(对应着存储单元),赋值语句(获取、存储指令),表达式(内存引用和算术运算)和控制语句(跳转语句)。

而函数式编程是面向数学的抽象,将计算描述为一种表达式求值。这里的函数实际就是数学中的函数,即自变量到因变量的映射。也就是说,一个函数的值仅决定于函数参数的值,不依赖其他状态。

函数式编程是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。而允许使用变量的程序设计语言,由于函数内部的变量状态不确定,同样的输入,可能得到不同的输出,因此,这种函数是有副作用的。

在函数式语言当中,函数作为一等公民,可以在任何地方定义,在函数内或函数外,可以作为函数的参数或返回值,可以对函数进行组合,也可以将函数赋值给变量。严格意义上的函数式编程意味着不适用可变的变量,赋值,循环和其他命令式控制结构进行编程。

函数式编程风格带来的好处是:

函数式编程使用不可变对象作为变量,不会修改变量的值,而是返回一个新的值,如此这样,更容易理清头绪,使得单元测试和调试更加容易;
可以很自由地传递不可变对象,但对于可变对象来说,传递给其他代码之前,需要先建造一个以防万一的副本;
一旦不可变对象完成构造以后,就不会有线程因为并发访问而破坏对象内部状态,因为根本没有线程可以改变不可变对象的状态;
不可变对象让哈希表键值更安全,所以哈希表键要求必须是不可变对象,否则使用可变对象,如果对象状态发生变化,那么在哈希表中就找不到这个对象了;
具体到编程语言,Scala(静态语言)和Python(动态语言)都能比较的支持函数式编程风格,但是它们都不是纯函数式的,也就是说它们同时支持指令式风格和函数式风格。而Java基本是指令式风格,但自从Java8引入lambda表达式以后也开始部分支持函数式风格。函数式编程最典型的是诸如map, flatMap, rece, filter等函数,它们的特点是支持某个函数作为上面这些函数的参数

❻ 为什么Java字符串是不可变对象

从代码层面 , 看String类的源码你会发现 , 一个字符串对象, 其元素是一个final 修饰的byte数组 , 那么就意味着这个字符串对象初始化之后 , 其元素(byte数组)就无法重新赋值了 , 而且String类中并没有getValue 获取这个数组元素的方法 , 所以就无法从数组内更改字符串对象的值 , 另外 , 字符串是放在字符串常量池的 , 既然是常量 , 自然应该是无法更改的 .
通常代码中 对 String 的重新赋值 , 都是更改对象引用 ,就是说重新赋值之后的字符串对象 , 指向了另外一个字符串的内存地址 , 而原本字符串初始值的内存地址 , 并没有发生改变 , 值也没有发生改变 , 改变的是对象的引用地址 .

❼ 为什么 java 中的 string 是不可变的

个人理解:因为string在java的编程当中比较普遍,以下的回答比较全面一些:
Java中String为什么是不可变的
1、在Java中,String类是不可变类,一个不可变类是一个简单的类,并且这个的实例也不能被修改,
这个类的实例创建的时候初始化所有的信息,并且这些信息不能够被修改
2、字符串常量池
字符串常量池是方法区中一块特殊的存储区域,当创建一个字符串常量的时候,判断该字符串字在符串字符串常量池中是否已经存在
如果存在,返回已经存在的字符串的引用;如果不存在,则创建一个新的字符串常量,并返回其引用
String string1 = "abcd";
String string2 = "abcd";
变量string1,string2指向常量池中的同一个字符串常量对象;如果String是可变的,给一个变量重新赋值一个引用,将会指向错误的值
3、缓存哈希值
在Java中字符串的哈希值会经常被使用到。例如在HashMap中,String的不可变总能保证哈希值总是相等的,并且缓存起来,不用担心会改变,
那意味着不需要每次都计算哈希值,这样会提高效率。在String类中有以下的代码:
private int hash; //用来缓存哈希值
3、促进其他对象的使用
HahSet<String> set = new HashSet<String>();
set.add(new String("a"));
set.add(new String("b"));
set.add(new String("c"));

❽ java中string为什么不可变

为什么不可变,回答这个问题,你就要理解把它设计为不可变的好处,String作为java中最常用的一种类,提供了很多操作方法。把它设计为final有以下好处:
1:稳定性和节省内存开销
final型会在jvm进行类加载的时候就直接进行实例化,这样就节省以后去不断new带来的内存开辟成本了。实例化后固定不可变了,这样它就是很稳定的。java程序员每天都在使用String,如果String不稳定,你想java最基本的操作还能实现吗?
2:防篡改
final是无法被继承的,这样它是独立存在的,自身封装的很好,就不会有子类去修改它本身的方法,不会有外界来打扰它,自身结构也不会被篡改了。
3:安全性:
这和它不能被继承这个息息相关,没有任何类可以继承它,就不会暴露给外部访问它内部方法的机会,这样它自身就比较安全了。
4:方便jvm优化
比如:String str1=“a"+"b"+1; String str2="ab1";为final的话,jvm就可以很方便的把str1的内容优化为str2,并指向同一个引用。这样就不用再去内存中new了。
当然还有很多好处了,java设计者这样做的根本目的就是为了保证java体系基本类的稳固和安全。

❾ java中是什么是不可变对象和可变对象

可变对象(mutable Objects),不可变对象(Immutable ojbects)
不可变对象意味着这个对象是final的,对象中所有的公共属性是final的。同时说明这个对象是线程安全的,这意味着他们可以在多线程中使用,而不需要使用synchronization。
可变对象和不可变对象相反,Java中大部分都是可变对象。
不可变对象有哪些
String,Integer以及其他的封装类型都是不可变对象。

❿ 昆明Java培训: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//{privateintxPos,yPos;publicPoint(intx,inty){xPos=x;yPos=y;}publicStringtoString(){return"x="+xPos+",y="+yPos;}intgetX(){returnxPos;}intgetY(){returnyPos;}}//_thestateofitsobjects//{privatefinalPointcenter;privatefinalintradius;publicImmutableCircle(intx,inty,intr){center=newPoint(x,y);radius=r;}publicStringtoString(){return"center:"+center+"andradius="+radius;}publicintgetRadius(){returnradius;}publicPointgetCenter(){//returnaoftheobjecttoavoid//(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类。
总结,文章的最后还是那句话,要根据自己的实际需要,去设计代码,而不要过度设计。

热点内容
做解压橡皮 发布:2025-01-21 15:03:06 浏览:991
双系统win访问mac 发布:2025-01-21 14:53:52 浏览:485
安卓车机系统如何安装carplay 发布:2025-01-21 14:52:24 浏览:590
sql操作手册 发布:2025-01-21 14:46:08 浏览:312
青橙脚本 发布:2025-01-21 14:44:05 浏览:219
东风本田crv时尚版是什么配置 发布:2025-01-21 14:20:04 浏览:219
安卓如何多开软件每个机型不一样 发布:2025-01-21 14:15:29 浏览:501
iis配置php5 发布:2025-01-21 14:08:19 浏览:274
凯叔讲故事为什么联系不到服务器 发布:2025-01-21 13:56:50 浏览:387
linux镜像文件下载 发布:2025-01-21 13:34:36 浏览:218