Выполнить 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();