Java Immutable类,带有静态工厂而不是构造函数

时间:2018-01-10 21:02:38

标签: java

创建可变类而不使用

中的final
namespace getPostgeocode
{
    class Program
    {
           /*private static string geos = "geographies";
           private static string addresses = "addressbatch";
            private static string benchmark = "Public_AR_Current";
            private static string vintage = "Current_Current";
            private static string returntype = "locations";
            private static string returntype = "locations";*/



        static void Main(string[] args)
        {


            //StringBuilder paramURI = new StringBuilder();
            // Create a request instance.  
            // paramURI.AppendFormat(format: @"{0}?benchmark={1}&vintage={2}&returntype={3}"
            //, arg0: benchmark, arg1: vintage, arg2: returntype);


            string baseURI = "http://geocoding.geo.census.gov/geocoder/";
            var uriBuilder = new UriBuilder(baseURI);
            var query = HttpUtility.ParseQueryString(uriBuilder.Query);
            query["benchmark"] = "Public_AR_Current";
            query["vintage"] = "Current_Current";
            query["returntype"] = "locations";
            query["geo"] = "geographies";
            query["addressbatch"] = "addressbatch";
            uriBuilder.Query = query.ToString();
            baseURI = uriBuilder.ToString();

            WebRequest myRequest = WebRequest.Create(baseURI);
            myRequest.Method = "POST";
            string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
            myRequest.ContentType = "multipart/form-data; boundary=" + boundary;
            //myRequest.KeepAlive = true;
            myRequest.Credentials = CredentialCache.DefaultCredentials;

            Console.WriteLine(baseURI);
            Console.ReadLine();

            WebResponse geoResponse = myRequest.GetResponse();
            Stream dataStream = geoResponse.GetResponseStream();
            StreamReader geoReader = new StreamReader(dataStream);
            string addString = geoReader.ReadToEnd();

            dataStream.Close();
            geoResponse.Close();


        }

    }
}

而是仅使用没有final的常规类声明,如

public final class X {...}

然后使用静态工厂构造函数,私有构造函数,其中所有字段都是私有的,那么我的问题是 - 不足以声明没有最终字段的私有字段,例如< / p>

public class X {...}

或/为什么我还要说

private double d;

我唯一的答案就是我不会在课堂上错误地改变任何非最终字段,但是有人可以从外面改变吗?

2 个答案:

答案 0 :(得分:-1)

无论您是否添加final,都无法触及该类代码之外的值。

如果你最好能够将它们声明为final,那么它会给编译器提供更多关于这些行为的线索,以便它可以更积极地优化代码。最后一个字段也是线程安全的,而你可能会在延迟初始化时弄乱非私有字段的状态。

我的建议是,除非有明显的性能提升,否则您总是尽可能地宣布最终版并且不进行延迟/延迟初始化。

同样非常重要的是要记住,对数组或非免疫对象的final引用不保证如果您共享参考值,其内容不会被更改(例如,返回它直接通过吸气剂)。对于裸阵列没有解决方法,但对于java.util.*个集合,您总是可以共享对您的集合的不可修改的包装引用(请参阅Collections.unmodifiableXXXX方法)。

最后请注意,尽管使用private声明某个字段为final,但仍可使用某些时髦的低级别工具更改这些值(例如,请参阅this)。然而,在编程时,没有人应该真正担心这一点。

答案 1 :(得分:-1)

Immutable 的类意味着在该类的实例具有该类 state 和/或 value(s)之后无法更改已创建。使类不可变可以通过多种方式实现;使用final变量可以提供帮助,并且使类本身final可以通过阻止子类可以打破不变性规则的子类来提供帮助。

在类上使用final关键字而在变量上使用它意味着两个完全不同的东西。

将类设置为final意味着类不能被子类化;也就是说,如果你有

public final class X {...}

你不能扩展它

public class Y extends X {...} // Illegal!

类是否为final是否与类成员变量无关。

将变量设置为final,无论是static,类成员变量还是本地(对方法或块)变量都意味着变量无法更改后它已被赋值。

您的代码还需要通过任何可用的执行路径为最终变量设置一个值,所以这没关系,因为它始终将“max”设置为:

...
final int max;
if (parameter) {
    max = 100;
} else {
    max = 1000;
}

但这会给你一个错误:

...
final int max;
if (parameter) {
    max = 100;
}

因为如果“参数”评估为true,则设置为“max”,否则不设置“max”。
这通常在不可变对象的构造函数中完成:

public final class X
{
    final int value;
    public X(int v)
    {
        this.value = v;   // Now that `value` has been set
                          // it can never be changed
    }
}

将某个类声明为final并不意味着它的类成员是最终的,所以你的问题“为什么我还要说”是因为{{em>的这两种用法1}}是不相关的。

请注意,您还可以将方法声明为最终方法:

final

这意味着不允许子类使用新实现覆盖此方法。如果类已经是public final int getMax() {...} ,那么方法上的final没有意义,因为没有任何子类试图覆盖该方法。)