Указывая на абстрактный класс - PullRequest
2 голосов
/ 12 марта 2019

У меня есть базовые знания абстрактного класса. Дело в том, что он не может быть реализован сам по себе, но с классом, который его реализовал, или с анонимными классами. Я надеюсь, что это правильно ..!

Но я наткнулся на код ниже.

SAXParserFactory factory = SAXParserFactory.newInstance(); 

А вот код источника newInstance:

public static SAXParserFactory newInstance()
  86:     throws FactoryConfigurationError
  87:   {
  88:     ClassLoader loader = Thread.currentThread().getContextClassLoader();
  89:     if (loader == null)
  90:       {
  91:         loader = SAXParserFactory.class.getClassLoader();
  92:       }
  93:     String className = null;
  94:     int count = 0;
  95:     do
  96:       {
  97:         className = getFactoryClassName(loader, count++);
  98:         if (className != null)
  99:           {
 100:             try
 101:               {
 102:                 Class t = (loader != null) ? loader.loadClass(className) :
 103:                   Class.forName(className);
 104:                 return (SAXParserFactory) t.newInstance();
 105:               }
 106:             catch (ClassNotFoundException e)
 107:               {
 108:                 className = null;
 109:               }
 110:             catch (Exception e)
 111:               {
 112:                 throw new FactoryConfigurationError(e,
 113:                      "error instantiating class " + className);
 114:               }
 115:           }
 116:       }
 117:     while (className == null && count < 3);
 118:     return new gnu.xml.stream.SAXParserFactory();
 119:   }
 120: 
 121:   private static String getFactoryClassName(ClassLoader loader, int attempt)
 122:   {
 123:     final String propertyName = "javax.xml.parsers.SAXParserFactory";
 124:     switch (attempt)
 125:       {
 126:         case 0:
 127:           return System.getProperty(propertyName);
 128:         case 1:
 129:           try
 130:             {
 131:               File file = new File(System.getProperty("java.home"));
 132:               file = new File(file, "lib");
 133:               file = new File(file, "jaxp.properties");
 134:               InputStream in = new FileInputStream(file);
 135:               Properties props = new Properties();
 136:               props.load(in);
 137:               in.close();
 138:               return props.getProperty(propertyName);
 139:             }
 140:           catch (IOException e)
 141:             {
 142:               return null;
 143:             }
 144:         case 2:
 145:           try
 146:             {
 147:               String serviceKey = "/META-INF/services/" + propertyName;
 148:               InputStream in = (loader != null) ?
 149:                  loader.getResourceAsStream(serviceKey) :
 150:                 SAXParserFactory.class.getResourceAsStream(serviceKey);
 151:               if (in != null)
 152:                 {
 153:                   BufferedReader r =
 154:                      new BufferedReader(new InputStreamReader(in));
 155:                   String ret = r.readLine();
 156:                   r.close();
 157:                   return ret;
 158:                 }
 159:             }
 160:           catch (IOException e)
 161:             {
 162:             }
 163:           return null;
 164:         default:
 165:           return null;
 166:       }
 167:   }
 168: 

Если вы видите код, есть возможность вернуть тип ссылки SAXParserFactory по номерам строк 104 и 118.

В строке 104 создается динамический класс. Я хочу знать, как вновь созданный класс может быть преобразован в абстрактный тип класса SAXParserFactory? Я запутался здесь ..!

И после создания SAXParserFactory, код ниже работает

SAXParser saxParser = factory.newSAXParser();

Таким образом, как только SAXParserFactory будет создан, перед его использованием должен быть реализован метод newSAXParser () абстрактного класса SAXParserFactory класса. Но откуда он вызывается? Потому что класс, который реализует класс SAXParserFactory, является классом, который создается во время выполнения!

1 Ответ

4 голосов
/ 12 марта 2019
97: className = getFactoryClassName(loader, count++);

Эта строка возвращает полное имя класса, который расширяется SAXParserFactory.
Примером может быть

oracle.xml.jaxp.JXSAXParserFactory

Тогда

102: Class t = (loader != null) ? loader.loadClass(className)
103:                            : Class.forName(className);

Запрашивает Classloader для объекта JXSAXParserFactory Class (Class<JXSAXParserFactory>).

104: return (SAXParserFactory) t.newInstance();

Class#newInstance, что в данном случае означает отсутствиевызывается конструктор args JXSAXParserFactory.

Будучи JXSAXParserFactory extends SAXParserFactory, он может быть преобразован .Это правильный термин.

Расширение означает наследование отцом подписи .Очевидно, что при обновлении вы потеряете дополнительных открытых членов подкласса.


SAXParserFactory#newSAXParser всегда будет ограничено при возврате SAXParser, но базовая реализация (в основном, логика) будетбыть другим.

https://en.wikipedia.org/wiki/Polymorphism_(computer_science)

...