在学习编程的过程中,我觉得不止要获得课本的知识,更多的是通过学习技术知识提高解决问题的能力,这样我们才能走在最前方,本文主要讲述如何创建不可变的Java类或对象,更多Java专业知识,广州疯狂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)对象应该是fianl的,以此来限制子类继承父类,以避免子类改变了父类的immutable特性。
5)如果类中包含mutable类对象,那么返回给客户端的时候,返回该对象的一个拷贝,而不是该对象本身(该条可以归为第一条中的一个特例)
当然不完全遵守上面的原则也能够创建immutable的类,比如String的hashcode就不是final的,但它能保证每次调用它的值都是一致的,无论你多少次计算这个值,它都是一致的,因为这些值的是通过计算final的属性得来的!
另外,如果你的Java类中存在很多可选的和强制性的字段,你也可以使用建造者模式来创建一个immutable的类。
下面是一个例子:
public final class Contacts { private final String name; private final String mobile; public Contacts(String name, String mobile) { this.name = name; this.mobile = mobile; } public String getName(){ return name; } public String getMobile(){ return mobile; } }
我们为类添加了final修饰,从而避免因为继承和多态引起的immutable风险。
上面是最简单的一种实现immutable类的方式,可以看到它的所有属性都是final的。
有时候你要实现的immutable类中可能包含mutable的类,比如java.util.Date,尽管你将其设置成了final的,但是它的值还是可以被修改的,为了避免这个问题,我们建议返回给用户该对象的一个拷贝,这也是Java的最佳实践之一。下面是一个创建包含mutable类对象的immutable类的例子:
public final class ImmutableReminder{ private final Date remindingDate; public ImmutableReminder (Date remindingDate) { if(remindingDate.getTime() < System.currentTimeMillis()){ throw new IllegalArgumentException("Can not set reminder” + “ for past time: " + remindingDate); } this.remindingDate = new Date(remindingDate.getTime()); } public Date getRemindingDate() { return (Date) remindingDate.clone(); } }
上面的getRemindingDate()方法可以看到,返回给用户的是类中的remindingDate属性的一个拷贝,这样的话如果别人通过getRemindingDate()方法获得了一个Date对象,然后修改了这个Date对象的值,那么这个值的修改将不会导致ImmutableReminder类对象中remindingDate值的修改。
使用Immutable类的好处:
1)Immutable对象是线程安全的,可以不用被synchronize就在并发环境中共享
2)Immutable对象简化了程序开发,因为它无需使用额外的锁机制就可以在线程间共享
3)Immutable对象提高了程序的性能,因为它减少了synchroinzed的使用
4)Immutable对象是可以被重复使用的,你可以将它们缓存起来重复使用,就像字符串字面量和整型数字一样。你可以使用静态工厂方法来提供类似于valueOf()这样的方法,它可以从缓存中返回一个已经存在的Immutable对象,而不是重新创建一个。
immutable也有一个缺点就是会制造大量垃圾,由于他们不能被重用而且对于它们的使用就是”用“然后”扔“,字符串就是一个典型的例子,它会创造很多的垃圾,给垃圾收集带来很大的麻烦。
当然这只是个极端的例子,合理的使用immutable对象会创造很大的价值。
参考另一个不可变例子:
Here is an example of a mutable object.
import java.util.ArrayList; import java.util.LinkedList; import java.util.List; class Cart { private final List items; public Cart(List items) { this.items = items; } public List getItems() { return items; } public static void main(String[] args) { List list = new ArrayList(); list.add("element1"); Cart cart = new Cart(list); cart.getItems().add("element2"); // 下面的代码能运行吗?为什么 // list=new LinkedList(); // cart.items=list; } }
The following change partially solves this problem. In the ImmutableCart
class, the list is immutable: you cannot add or remove items.
import java.util.ArrayList; import java.util.Collections; import java.util.List; class ImmutableCart { private final List items; public ImmutableCart(List items) { this.items = Collections.unmodifiableList(new ArrayList(items)); } public List getItems() { return items; } public static void main(String[] args) { List list = new ArrayList(); list.add("element1"); ImmutableCart cart = new ImmutableCart(list); cart.getItems().add("element2"); } }
运行抛出异常:
Exception in thread "main" java.lang.UnsupportedOperationException
相关推荐
"java类与对象实例" 在 Java 中,类和对象是两个紧密...理解 Java 语言的类和对象概念对于编写高效、可维护的 Java 程序非常重要。这些概念是学习 Java 语言的基础,理解这些概念可以帮助开发者更好地编写 Java 程序。
在Java编程中,不可变对象是指一旦创建后其状态不能被修改的对象。这种对象模式在多线程环境和频繁对象创建的场景下,提供了线程安全保证,减少了内存开销,并提高了代码的可维护性。本文将详细介绍如何在Java中创建...
在Java中,对象重构可能涉及重命名变量、方法或类,提取方法,或者将相关属性和行为组合到一个新类中。这有助于提高代码的可读性、可维护性和性能。 2. **this关键字**: `this`关键字在Java中代表当前对象的引用...
在Java中,创建对象通常使用new关键字,后面跟着类的名称和括号。例如,要创建一个名为Person的类的对象,可以使用如下代码: ```java Person person = new Person(); ``` 这里,person是对象的引用,指向新创建的...
### Java对象创建过程详解 在Java编程语言中,对象是程序的基本单元,一切皆对象这一概念使得Java在面向对象编程领域具有重要的地位。本文将详细阐述Java对象的创建过程,帮助读者深入理解Java基础。 #### 一、类...
因为Java的代理机制是基于接口的,它不能直接创建继承自抽象类的代理对象。但如果你想要创建一个与抽象类有关的代理对象,可以借助第三方库如Javassist或ByteBuddy等字节码工具。这些库允许你在运行时动态生成类,...
然而,不可变性也带来了挑战,比如在需要频繁修改字符串内容时,需要使用StringBuilder或StringBuffer类,它们提供了可变的方法来拼接字符串,以避免频繁创建新对象。 例如: ```java StringBuilder sb = new ...
不可变对象是指创建后状态不能被修改的对象,这类对象天生就是线程安全的。它们的常量(变量)是在构造函数中创建的,既然它们的状态无法被修改,那么这些常量永远不会被改变。 不可变对象的定义并不是将域简单地...
在Java编程语言中,"类"与"对象"是核心概念,它们构成了...通过定义类、创建对象、利用继承和接口,以及实践封装和多态,你可以在软件开发中构建出高效、可维护的代码。不断练习和探索,你将在Java编程世界中游刃有余。
- **对象创建**:创建类的实例是通过`new`关键字: ```java ClassName myInstance = new ClassName(); ``` 5. **使用现有类** - **同一包内**:直接使用类名创建对象。 - **不同包内**:需要导入相应包,然后...
总之,XML文件自动转成Java对象工具是Java开发中不可或缺的一部分,它极大地简化了XML数据处理,提高了开发效率。通过理解和利用这类工具,开发者可以更专注于业务逻辑,而非基础的数据转换工作。
- **常量与字符串**:final关键字用于声明常量,String类在Java中的特殊地位及其不可变性。 3. **第3章:运算符、表达式和语句** - **运算符**:包括算术运算符、比较运算符、逻辑运算符、位运算符、赋值运算符等...
class:java中class确切的表示为一个类 object:java中object确切的表示为一个对象,也称为类的实例 其实,如果一个类被设计...包装类(e.g.Integer或Float)和String类是不可变类的代表。 访问器方法(accesso
在Java面向对象编程中,理解抽象、封装和类的设计是构建清晰、可维护和可扩展程序的基础。本文将详细探讨这些概念以及它们在Java语言中的实现。 首先,抽象是从具体的实例中提炼出共性,形成一般化概念的过程。在...
在 Java 编程中,创建对象是不可或缺的一步,但是随着程序的复杂度和可维护性的要求的提高,使用这些基本的对象创建方法已经不能满足需求了。因此,我们需要引入更多的设计模式和技术来满足这些需求,例如工厂设计...
以上所述,都是Java面向对象高级阶段的关键知识点,它们是构建复杂、可扩展和可维护的Java应用程序的基础。通过学习和掌握这些概念,开发者能够更好地理解和运用面向对象编程的思想,提升软件开发的效率和质量。
本资源摘要信息涵盖了 Java 面向对象编程的基础知识点,包括类和对象之间的关系、类的声明、方法的声明和使用、构造方法、面向对象编程的基本概念等。 1. 类和对象之间的关系:类和对象之间存在抽象和具体的关系,...
- **不可变性**:Java中的`String`对象是不可变的,这意味着一旦创建了`String`对象,就不能更改它的值。这是因为字符串被存储在常量池中,修改字符串会生成新的`String`对象。 - **构造方法**:可以通过传递字符...
面向对象编程(Object-Oriented Programming,简称OOP)是一种重要的编程范式,它基于“对象”的概念,...实际操作过程中,他们将面临问题解决,调试代码,优化算法等挑战,这些都是成为专业程序员不可或缺的经验积累。
在Java编程语言中,"对象"、"类对象"和"类"是核心...以上只是对Java对象、类对象和类的初步介绍,实际编程中,我们需要结合这些概念去设计和实现复杂的应用。不断学习和实践,才能更好地掌握Java面向对象编程的精髓。