「java不变类」java某个类不编译
本篇文章给大家谈谈java不变类,以及java某个类不编译对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
不可变类
不可变类是指实例不能被修改的类。每个实例中包含的信息都必须在创建该实例的时候就提供,并在对象的整个生命周期内固定不变。你也许时常听说,String就是一个典型的不可变类。
让我们思考一下,如果一个类的实例从创建后就不能再修改,它有什么好处?
最容易想到的是,它用起来 简单 。它不会提供过多的方法,大概只会提供一些访问方法,这对于用户是件非常愉快的事情。
其次,当一个类不可变的时候,我们就可以 复用 它。就像String对象池那样,相同的对象只需要创建一个,这样可以极大地节省空间。
不仅可以复用,还可以 共享 。不可变对象本质上是线程安全的,多个线程并发访问同一个对象不会造成任何线程安全性问题。
最后,不可变类可以很方便地作为其它不可变类的成员。这将在后面的叙述中给出原因。
不可变类唯一的 缺点 是,对于每个不同的值都需要一个单独的对象。如果对象很大,对它做一点点的修改就重新生成另一个对象,在性能上是无法接受的。即使是String类也存在这样的问题,但好在Java平台给出了解决方案,当频繁改变字符串时使用StringBuilder代替String,可以获得较好的性能。
要想使一个类成为不可变类,需要遵循下面五条规则:
让我们根据这些规则实现一个Period类,该类用来表示一段不可变的时间周期。
在Period中,我们只提供了一个构造方法和两个访问方法,并没有提供任何会修改对象状态的方法,因此满足第一条规则。
通过在类名称前添加 final 关键字,保证了该类不会被扩展,满足第二条规则。
所有的域都是final并且私有的,满足三四条规则。
最关键的地方在于我们是如何满足第五条规则的。由于 Date 是一个可变类,因此在构造方法中,并没有直接把用户传入的 Date 对象赋值给私有域,而是各拷贝了一份相同的对象再赋值给私有域。同样的,在访问方法 start 和 end 中,也没有直接把私有域指向的对象返回给客户端,而是各拷贝了一份副本返回。这种做法就叫做 保护性拷贝 ,客户端永远无法拿到不可变对象私有域的引用,而只能拿到相应的副本,因此也就无法改变不可变对象。
这段程序还有几处需要注意的地方:
其实,Java API的设计者早已把这些规则应用到了String等不可变类上,大家可以查看String类的源码,它的构造方法、静态工厂方法以及其它很多方法都使用了保护性拷贝技术。
关注 作者 或 文集《Effective Java》 ,第一时间获取最新发布文章。
java不可变类有哪些
java不可变类是fina的,常用的有以下几种:
String
public final class Stringextends Object implements Serializable, ComparableString, CharSequence
Integer (以及其它基本类型的包装类)
public final class Integer extends Numberimplements ComparableInteger
java调用class类时如何不会改变类中的变量值
不可变类指当类被实例化后,该类的成员变量均不可被改变。如JDK内部自带的很多不可变类:Interger、Long和String等。
优点
1.线程安全 2.易于构造、使用和测试 3.可以被自由地共享
缺点
对于每一个不同的值都需要对应一个单独的对象
类设计原则
1.class要用final修饰,保证类不能被继承;
2.成员变量需要用private String来修饰,保证成员变量均为私有变量;
3.类中不允许提供setter方法,保证成员变量不会被改变;
4.成员变量的getter方法中返回该对象的复制对象,保证原对象的引用不被改变;
String对象的不可变性
string对象在内存创建后就不可改变,不可变对象的创建一般满足以上4个原则,我们看看String代码是如何实现的。
public final class String
implements java.io.Serializable, Comparable, CharSequence
{
/** The value is used for character storage. */
private final char value[];
/** The offset is the first index of the storage that is used. */
private final int offset;
/** The count is the number of characters in the String. */
private final int count;
/** Cache the hash code for the string */
private int hash; // Default to 0
....
public String(char value[]) {
this.value = Arrays.copyOf(value, value.length); // deep copy操作
}
...
public char[] toCharArray() {
// Cannot use Arrays.copyOf because of class initialization order issues
char result[] = new char[value.length];
System.arraycopy(value, 0, result, 0, value.length);
return result;
}
...
}
如上代码所示,可以观察到以下设计细节:
String类被final修饰,不可继承
string内部所有成员都设置为私有变量
不存在value的setter
并将value和offset设置为final。
获取value时不是直接返回对象引用,而是返回对象的copy.
这都符合上面总结的不变类型的特性,也保证了String类型是不可变的类。
java不变类是在创建该类实列后它的属性不可被改变,那只把它的属性全部用final修饰不就行了
如果使用final修改的话,它的初始值只能在第一次创建时被赋上值,比如构造函数。一但使用new创建实例后就不能再赋值了。但是有时候我们在使用的过程中,并不是一开始就给所有的属性赋值的,而且有时候属性非常多,做一个多属性的构造函数也不利于维护。所以,一般要用到不变类的时候,我们使用builder类,它只有get方法,没有set方法:例如:
public class DoDoContact {
private final int age;
private final int safeID;
private final String name;
private final String address;
public int getAge() {
return age;
}
public int getSafeID() {
return safeID;
}
public String getName() {
return name;
}
public String getAddress() {
return address;
}
public static class Builder {
private int age = 0;
private int safeID = 0;
private String name = null;
private String address = null;
// 构建的步骤
public Builder(String name) {
this.name = name;
}
public Builder age(int val) {
age = val;
return this;
}
public Builder safeID(int val) {
safeID = val;
return this;
}
public Builder address(String val) {
address = val;
return this;
}
public DoDoContact build() { // 构建,返回一个新对象
return new DoDoContact(this);
}
}
private DoDoContact(Builder b) {
age = b.age;
safeID = b.safeID;
name = b.name;
address = b.address;
}
}
最终,客户程序可以很灵活的去构建这个对象。
1
2
3
4
DoDoContact ddc = new DoDoContact.Builder("Ace").age(10)
.address("beijing").build();
System.out.println("name=" + ddc.getName() + "age =" + ddc.getAge()
+ "address" + ddc.getAddress());
关于java不变类和java某个类不编译的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。