How come an abstract class “DocumentBuilderFactory

2020-04-07 05:29发布

问题:

Recently, I have been working with XML parsers. This is just beginning for me and I managed to understand how to use DOM parser classes in java i.e. DocumentBuilderFactory and DocumentBuilder to parse an XML document.

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();  
DocumentBuilder db = dbf.newDocumentBuilder();            

What I am asking myself is how come an abstract classes, such as DocumentBuilderFactory and DocumentBuilder, are allowed to instantiate new instances? And then in another example I see:

Calendar calendar = Calendar.getInstance();  
System.out.println(calendar.get(Calendar.DATE)); 
  1. As far as I know, you can not instantiate (in other words, create an object) for abstract and interface classes. Am I correct?
  2. Do getInstance() and newInstancce() methods create instances of the above abstract classes?

Am I missing something about using an abstract class and its new Objects?

回答1:

That method is an abstract factory method, which returns a subclass of DocumentBuilder, which is a (concrete) implementation.

The exact class of the object is not important to know, you only need to know that it's a DocumentBuilder. The method may return an instance decided at runtime, or predetermined as it sees fit.

If you are curious to know, you can print out the actual class like this:

 System.out.println(dbf.getClass());

Note that the method newInstance() is not to be confused with the method of the same name of Class, ie these two are different:

 // a static method of this class
 DocumentBuilderFactory.newInstance(); 

// an instance method of Class
 DocumentBuilderFactory.class.newInstance();

An unfortunate choice of name sure to have caused confusion.



回答2:

That is a static abstract factory method , which will return a subtype of DocumentBuilderFactory not the actual instance of DocumentBuilderFactory itself.It is not like what I presume, you understand :

DocumentBuilderFactory dbf = new DocumentBuilderFactory();

DocumentBuilderFactory#newInstance() , Obtain a new instance of a DocumentBuilderFactory. This static method creates a new factory instance. This method uses the following ordered lookup procedure to determine the DocumentBuilderFactory implementation class to load.

newInstance() will return an instance of the implementing class(subtype) of DocumentBuilderFactory, which is not abstract and will assign reference to that object to DocumentBuilderFactory reference variable.



回答3:

It's a static method. You can call static methods of abstract(or any class for that matter) classes without a reference to an instance..



回答4:

Thanks for everyone, after trying below code my doubt got cleared.

Calendar cls = Calendar.getInstance();
Date dt = new Date();
System.out.println(cls.getClass()); //<------ 1
DocumentBuilderFactory dbls = DocumentBuilderFactory.newInstance(); System.out.println(dbls.getClass()); //<------2
DocumentBuilder db = dbls.newDocumentBuilder();
System.out.println(db.getClass()); //<--------3

And I see the follwoing output:

 ********Output******
   class java.util.GregorianCalendar
   class com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl
   class com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl

a) static method "DocumentBuilderFactory.newInstance()" returns subtype class instance called "DocumentBuilderFactoryImpl" .

b) "DocumentBuilderFactoryImpl" is a subclass of abstract "DocumentBuilderFacotory" class ,hence there is no problem if I give :

DocumentBuilderFacotryImpl dbls = DocumentBuilderFactory.newInstance();
//-----Instead of giving DocumentBuilderFactory dbls = DocumentBuilderFactory.newInstance();

and same applies to DocumentBuilderImpl db = dbls.newDocumentBuilder();
//---- Instead of DocumentBuilder db = dbls.bewDocumentBuilder();

Conclusion: newInstance(), newDocumentBuilder(), getInstance() returns subclass object. Although abstract class can not create new Object , we can assign subclass object to abstract class (i.e.parent) reference variable. ex:

Abstract class A{ }
class B extends A{ }

we can say:

 A a = new B();   

but not

 A a = new A();