#java #abstract-class
#java #абстрактный класс
Вопрос:
У меня есть базовые знания об абстрактном классе. Это то, что он не может быть создан сам по себе, но с классом, который его реализовал, или анонимными классами. Я надеюсь, что это правильно ..!
Но я наткнулся на приведенный ниже код.
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 amp;amp; 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
is в строках с номерами 104 и 118.
В строке 104 создается динамический класс. Я хочу знать, как вновь созданный класс может быть приведен к типу абстрактного класса SAXParserFactory
? Я здесь в замешательстве ..!
И после создания экземпляра SAXParserFactory
выполняется приведенный ниже код
SAXParser saxParser = factory.newSAXParser();
Итак, после SAXParserFactory
создания экземпляра метод newSAXParser() абстрактного класса SAXParserFactory
class должен быть реализован перед его использованием, но откуда он вызывается? Потому что класс, который реализует SAXParserFactory
class, — это класс, который создается во время выполнения!
Комментарии:
1. Это сложная смесь отражения и загрузки класса, есть ли у вас опыт работы с любым из них?
2. любой экземпляр может быть приведен к одному из его суперклассов или к любому из реализуемых им интерфейсов (например, вы можете привести любой экземпляр
Integer
кNumber
илиObject
) Класс, представленныйt
, должен быть подклассомSAXParserFactory
3.Строка 104:
t
является объектом класса для класса, который реализует (подклассы)SAXParserFactory
, поэтому фактический класс не является абстрактным, и его можно привести без проблем.
Ответ №1:
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
вызывается, что в данном случае означает, что вызывается конструктор без аргументов JXSAXParserFactory
.
Будучи JXSAXParserFactory extends SAXParserFactory
, он может быть повышен. Это правильный термин.
Расширение означает наследование отцовской подписи. Очевидно, что при повышении производительности вы теряете дополнительные доступные члены подкласса.
SAXParserFactory#newSAXParser
всегда будет ограничено при возврате SAXParser
, но базовая реализация (в основном, логика) будет другой.
https://en.wikipedia.org/wiki/Polymorphism_ (computer_science)
Комментарии:
1. это действительно преобразование вверх: от
Object
кSAXParseFactory
? Я считаю, что это приведение вниз (приведение вверх всегда разрешено; приведение вниз включает проверку типа, что, безусловно, имеет место здесь — вы получите исключение приведения, еслиt
это не класс, расширяющийSAXParseFactory
) {JLS использует эти термины вообще, он использует преобразование ссылок сужения / расширения}2. @CarlosHeuberger поскольку это старый код, да, он выполняется с понижением. Более новая версия этого, я полагаю, будет использовать универсальный класс<T> . Однако мое утверждение относилось в целом (JXSAXParserFactory расширяет SAXParserFactory), на самом деле не к этой строке кода
3. @LppEdd «Эта строка возвращает полное имя класса, который расширяет SAXParserFactory», Откуда мы знаем, что SAXParserFactory реализован объектом класса Class ?
4. @Trisha mmh Я тебя не понимаю. Что вы имеете в виду? Попробуйте использовать какие-нибудь другие слова.
5. @LppEdd, В приведенном выше коде
className
возвращает имя (oracle.xml.jaxp.JXSAXParserFactory
) экземпляра нового класса. И этот класс будет классом, который будет реализовыватьSAXParserFactory
класс abstact. Но где выполняется эта реализация? Какая часть кода, по его словам, сейчасSAXParserFactory
реализованаoracle.xml.jaxp.JXSAXParserFactory
?