「java不变类」java某个类不编译

博主:adminadmin 2023-03-22 16:32:09 787

本篇文章给大家谈谈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某个类不编译的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。