public static factory method

血红的双手。 提交于 2019-11-30 04:57:02

class of an object returned by static factory method is nonpublic - what exactly does it mean?

It means that the actual class of the objects returned by a static factory method can be a subclass of the declared type, and this subclass does not have to be public. It's just another implementation detail that client code should not care about.

unlike constructors static factory methods are not required to create a new object each > time they are invoked - How does this happen? I am invoking factory method only to obtain a new object and do we put a check in factory method for checking if object already exists?

Yes, that's one way this could be done. But really, anything is possible.

First off, kudos to you for your choice in Java-lit: Bloch's book is an excellent primer.

To answer your 2nd question ('unlike constructors static factory methods are not required to create a new object each time they are invoked'), it's important to realize that what Bloch is saying here is that with a static factory you have the option of either: returning a new object or returning a pre-existing one. It all depends on what you want to do.

For example, let's suppose you have a really simple value class of type Money. Your static factory method probably should return a new instance -- that is, a new object with a specific value for Money. So, like this:

public class Money { 

    private Money(String amount) { ... } /* Note the 'private'-constructor */

    public static Money newInstance(String amount) {
        return new Money(amount);
    }

}

But let's say you have some object that manages some resource and you want to synchronize access to that resource through some ResourceManager class. In that case you probably want your static factory method to return the same instance of itself to everyone -- forcing everyone to go through that same instance, so that that 1 instance can control the process. This follows the singleton-pattern. Something like this:

public ResourceManager {

    private final static ResourceManager me = new ResourceManager();

    private ResourceManager() { ... } /* Note the 'private'-constructor */

    public static ResourceManager getSingleton() {
        return ResourceManager.me;
    }
}

The above method forces your user to only ever be able to use a single instance, allowing you to precisely control who(and when) has access to whatever it is you are managing.


To answer your first question, consider this (admittedly not the best example, it's pretty ad-hoc):

public class Money {

    private Money(String amount) { ... }


    public static Money getLocalizedMoney( MoneyType localizedMoneyType, String amount ) { 
        switch( localizedMoneyType ) {
            case MoneyType.US:
                return new Money_US( amount );
            case MoneyType.BR:
                return new Money_BR( amount );
            default:
                return new Money_US( amount );
        }
    }
}

public class Money_US extends Money { ... }

public class Money_BR extends Money { ... }

Note how I can now do this:

Money money = Money.getLocalizedMoney( user_selected_money_type );
saveLocalizedMoney( money );

Again, a really contrived-example but hopefully it helps you see more or less what Bloch was getting at with that point.

The other answers were good -- I just think that, as a beginner, sometimes it helps to see some actual code.

When you use the new keyword then you as the developer know that the JDK will create a new instace of that object. What the author is saying, when you use a static method, the developer no longer knows if the method is creating a new instance or possibly doing something else. Something else can be, reusing cached data, object pooling, creating a private implementation and returning a subclass of the class.

class of an object returned by static factory method is nonpublic

Frequently a static factory method will return either an an object typed as an interface (most common), or sometimes some base class (less common). In either case, you don't know the exact class of the returned object.

The advantage of this is getting an object whose behaviour you know without worrying about the messy details of what class it instantiates.

unlike constructors static factory methods are not required to create a new object each time they are invoked

To understand this, consider the case of working with a singleton. You may call .getInstance() on some factory classes to get the singleton instance of an certain object. Typically, what this does is create an instance of the object if it doesn't already exist, or give you the existing instance if it already does. In either case, you get back a copy of the object. But you don't (and won't) know if this singleton had to be created, or if one had already been constructed previously.

The advantage of this is that the lifecycle of the object and when it is created is managed for you.

Both of your questions can be answered by looking at some code that makes use of both of these properties of static factory methods. I suggest looking at Guava's ImmutableList.

Note how the no-arg factory method of() always returns the same instance (it doesn't create a new instance each time). If you look carefully, you'll also notice that its copyOf(Iterable) factory method actually returns the object that is passed to it if that object is itself an ImmutableList. Both of these are taking advantage of the fact that an ImmutableList is guaranteed to never change.

Notice also how various factory methods in it return different subclasses, such as EmptyImmutableList, SingletonImmutableList and RegularImmutableList, without exposing the types of those objects. The method signatures just show that they return ImmutableList, and all subclasses of ImmutableList have package-private (default) visibility, making them invisible to library users. This gives all the advantages of multiple implementation classes without adding any complexity from the user's perspective, since they are only allowed to view ImmutableList as a single type.

In addition to ImmutableList, most instantiable classes in Guava utilize static factory methods. Guava also exemplifies a lot of the principles set forth in Effective Java (not surprising, given that it was designed by those principles and with guidance from Josh Bloch himself), so you may find it useful to take a look at it more as you're working through the book.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!