Выполнить Java-класс?
Относительно новый Java-программист, и меня научили, что вы не можете создать экземпляр абстрактного класса. Я также провел небольшое исследование, и я узнал, что в большинстве случаев, когда создается абстрактный класс, он фактически является анонимным подклассом. Но вот проблема, с которой я столкнулся:
Java URL
class имеет метод openConnection
, который возвращает URLConnection
. URLConnection
- абстрактный класс, а документация Java также перечисляет все его подклассы как абстрактные..... так что я действительно потерян. Что возвращается?
Ответы
Ответ 1
То, что возвращается, является не абстрактным подклассом, который вы не найдете в документации API, например sun.net.www.protocol.http.HttpUrlConnection
. Если вы запустите тот же код из апплета в браузере, вы, скорее всего, получите другое, обычно это то, что обертывает родные соединения браузера.
Итак, нет никаких трюков и магии, просто некоторые классы не отображаются в документах API, поскольку они считаются внутренними для реализации и могут быть изменены.
Есть много подобных примеров, DocumentBuilderFactory
или TransformerFactory
являются абстрактными, но их Метод newInstance()
возвращает подкласс, обычно упакованный отдельно (например, Saxon).
Но есть и другие решения одной и той же проблемы: JDBC определяет интерфейс Driver
(а не абстрактный класс) и класс утилиты DriverManager
со статическими методами для загрузки различных реализаций драйверов. Вместо расширения абстрактного класса разработчикам драйверов баз данных требуется реализовать интерфейс Driver
.
Кстати, чтобы найти фактический класс времени выполнения объекта, просто назовите getClass()
на них.
Ответ 2
openConnection
возвращает некоторый конкретный класс, который расширяет URLConnection
. Подпись метода определяется как возвращающая URLConnection
, так как ваш код, использующий ее, не должен полагаться на какую-либо конкретную реализацию.
Ответ 3
Здесь будет применяться концепция полиморфизма.
Тип объектов будет URLConnection (родительский класс\интерфейс), а объект будет иметь его дочерний класс (расширяет или реализует (в случае интерфейса)).
Следующий пример может сделать это понятным для вас.
abstract class URLConnection {
// some methods.
}
Предположим, у вас есть свой класс.
class ConnectionClass extends URLConnection {
// some methods
}
class Main {
URLConnection connect = null
public URLConnection getUrl() {
return connect = new ConnectionClass();
}
}
Вы вернете объект класса, который дает реализацию openConnection()
класса URLConnection
. Эти же понятия применяются в интерфейсе.
Ответ 4
Скажите, что у вас есть abstract class
...
abstract class Vehicle {
abstract public void move();
}
Без создания class Car extends Vehicle
или class Boat extends Vehicle
вы можете сделать это с помощью магии анонимных классов. (Может быть, почему javadoc не говорит, что существует подкласс, потому что он анонимный и поэтому не может быть ссылкой публичным api, который представляет javadoc.)
class Example {
public Vehicle foo() {
Vehicle car = new Vehicle {
@Override
public void move() {
// do some car movement, i.e. driving
}
}
return car;
}
public Vehicle bar() {
Vehicle boat = new Vehicle {
@Override
public void move() {
// do some boat movement, i.e. boating
}
}
return boat;
}
}
Итак, вы не можете создать экземпляр abstract class
... но это не совсем правда, вы можете сделать это как анонимный класс и реализовать методы на месте. Это технически не создает экземпляр abstract class
, хотя, но это то, что делается много, когда вы видите подобное.
Снова скажите, что у вас есть abstract class
...
abstract class Vehicle {
abstract public void move();
}
Если внутренний class
был private
, то только экземпляр класса, который его обменивает, может создать экземпляр. (Может быть, почему javadoc не говорит, что есть подкласс, потому что он является частным и, следовательно, скрыт от публичного api, который представляет javadoc.)
class Example {
private class Car extends Vehicle {
@Override
public void move() {
// do some car movement, i.e. driving
}
}
private class Boat extends Vehicle {
@Override
public void move() {
// do some boat movement, i.e. boating
}
}
public Vehicle foo() {
return new Car();
}
public Vehicle bar() {
return new Boat();
}
}
Это ничего не говорит о создании экземпляра abstract class
es, но может помочь ответить на URL
, openConnection
и URLConnection
.
Ответ 5
Это класс, расширяющий URLConnection
, который возвращается. Это способ скрытия детализации реализации, поскольку в зависимости от входных параметров может быть возвращена различная реализация URLConnection
.
Ответ 6
Когда все подклассы являются абстрактными, то это потому, что вы можете использовать классы только путем его создания в factory. Если вы тщательно проверите код с помощью java.net.URLConnection для запуска и обработки HTTP-запросов, вы увидите, что объект URLConnection
никогда не создается. Вместо этого мы получаем его, вызывая openConnection
следующим образом:
URLConnection connection = new URL(url + "?" + query).openConnection();