7

I am new to Java. One thing confuses me is to why some of the classes need new to instantiate, and why some others do NOT need new to instantiate.

For example, I am looking at log4j, it does not need new.

// get a logger instance named "com.foo"
Logger  logger = Logger.getLogger("com.foo");
logger.setLevel(Level.INFO);

Why do some other classes need new? For example, an Employee class:

Employee X = new Employee (John);
X.getwork();

etc etc.

Why we did not say , Logger logger = new Logger(...);? and why were we able to use it even without new, like logger.setLevel(), etc.

ivanleoncz
  • 9,070
  • 7
  • 57
  • 49
Jason
  • 71
  • 1
  • 2

8 Answers8

8

The only way to create a new object in Java is with new [1]. However, in some classes, you're not permitted to say new for yourself, you must call a factory method, which might be static (as with your logger example) or not. The author of a class sets this up by making the constructor(s) have access other than public.

Also note that your example may not involve a new object at all. That Logger function might be returning an old object, not a new one.

The following poem by Ogden Nash seems faintly relevant:

This morning I went to the zoo 
In order to look at the gnu. 
But the old gnu was dead,
and the new gnu, they said, 
Was too new a new gnu to view.

[1] Unless you get involved in low-level reflection, or use Object.clone()

bmargulies
  • 97,814
  • 39
  • 186
  • 310
  • There are alternatives to new operator: http://stackoverflow.com/questions/95419/what-are-all-the-different-ways-to-create-an-object-in-java – maba Sep 04 '12 at 06:34
3

In this case, we are dealing with factory methods, as I stated in my comment.

See the relevant API specification on Logger

Retrieve a logger named according to the value of the name parameter. If the named logger already exists, then the existing instance will be returned. Otherwise, a new instance is created.

By default, loggers do not have a set level but inherit it from their neareast ancestor with a set level. This is one of the central features of log4j.

The factory method pattern is a creational design pattern, and, according to Wikipedia, is often useful in the following situations:

The factory pattern can be used when:

  • The creation of an object precludes its reuse without significant duplication of code.
  • The creation of an object requires access to information or resources that should not be contained within the composing class.
  • The lifetime management of the generated objects must be centralized to ensure a consistent behavior within the application.

All three of these are applicable here... who knows what kind of work goes into finding the correct logger? You're not really interested in creating a brand new logger each time you want to use one... instead, your focus is mainly just that -- to use one.

The Creative Commons Wiki also has a relevant article,

Factory methods are sometimes used in place of constructors for any of several reasons:

  • Some languages (such as Java) do not allow constructors to have useful names
  • Some languages (such as Java) do not allow constructors to have different names (which may be necessary if you want to use the same method signature for two constructors)
  • To allow the same instance to be reused instead of recreated each time it is needed (see FlyweightPattern)

I think the third option is probably the most applicable here. Using manual creation of a new Logger, you are unable to adequately share them. Using the getLogger facade enables this to happen transparently.

All in all, the use of factory methods is usually to enable cleaner more straight-forward code without exposing work you don't necessarily care about.

Community
  • 1
  • 1
obataku
  • 29,212
  • 3
  • 44
  • 57
2

For instance, some classes may prevent you from creating more than one object in the application. It that case you need to call some method for instantiate the class, like the Logger.getLogger(). The getLogger() may have the code like this:

if(uniqueInstance == null) {
    uniqueInstance = new Logger();
}

return uniqueInstance;

Where uniqueInstance is an instance of Logger. This is a design pattern called Singleton. In this pattern, you can't instantiate the class because it's constructor is private.

Some other way that you can't instantiate a class is when the class is defined as static.

Classes that have public constructors and aren't static need to be instantiated with the new keyword.

1

because Logger.getLogger() returns a Logger object. new Logger() calls the constructor which also returns a Logger. This also kind of uses new too, because inside the Logger class is probably something like:

public class Logger {
     public static Logger getLogger() {
        return new Logger("foo", "bar");
    }
}
tckmn
  • 57,719
  • 27
  • 114
  • 156
1

Well what you are asking is more related to design patterns. The Logger class is following singleton pattern.

Suppose you want that only a single instance of your class gets created accross the application then you can make your constructor private and provide a static method which creates and stores the object of your class when invoked for the first time.

public class SingletonPattern{

    private static SingletonPattern instance;

    private SingletonPattern(){} 

    public static synchronized SingletonPattern getInstance(){
        if (instance == null){
            instance = new SingletonPattern();
        }
        return instance;
    }
}

In this way you can restrict your class to be instantiated only once.

0

In your example you have to different use cases : the static method that returns an object and the actual constructor call.

The static method is a method that doesn't need to be call on a object, here it's inner mechanism may instantiate an object and return it for futur usage, in this method, there's a call to "new" but the object might be configured, or retrieved from a cache before being return. This is this kind of call

Logger  logger = Logger.getLogger("com.foo");

The actual constructor call (which use new) is the normal way to create new object.

AsTeR
  • 7,247
  • 14
  • 60
  • 99
0

You were not technically using the Logger class, but were using a method. You were not technically instantiating the Logger class, nor keeping a reference to it directly as you would with Logger logger = new Logger(). Instead, what you are doing is accessing a method to get back a returned instance. It would be nice to see the class definition. However, more than likely what you have is a static method inside of the class. And the class is more than likely defined with a private constructor. This allows the methods to be accessed without instantiating the class. You can see a good explanation of this, and of static in java here: https://stackoverflow.com/a/1844388/1026459

Community
  • 1
  • 1
Travis J
  • 81,153
  • 41
  • 202
  • 273
0

Some classes cannot be instantiated outside of themselves (e.g. the Math class, these classes have non-public constructors). Of those classes, some provide methods that return instances of the class (e.g. the InetAddress class). These are called factory methods. They are static methods that return instances of the class they're in, so the new keyword need not be used (it is instead used inside of the factory methods). For example:

public class A {
   private A() {}
   public A createAnA() { return new A(); }
}

Here, createAnA() is the factory method.

arshajii
  • 127,459
  • 24
  • 238
  • 287