Интервью: можем ли мы создать экземпляр абстрактного класса?



интервьюер спросил-можем ли мы создать экземпляр абстрактного класса? Я сказал, Нет. Он сказал мне-неправильно, мы можем.



Я немного поспорил на этот счет. Тогда он сказал мне попробовать это самостоятельно у себя дома.



abstract class my {
public void mymethod() {
System.out.print("Abstract");
}
}

class poly {
public static void main(String a[]) {
my m = new my() {};
m.mymethod();
}
}


здесь я создаю экземпляр моего класса и вызываю метод абстрактного класса. Может кто-нибудь объяснить мне это? Был ли я действительно неправ во время моего интервью?

683   15  

15 ответов:

здесь я создаю экземпляр моего класса

нет, вы не создаете экземпляр абстрактного класса здесь. Скорее вы создаете экземпляр анонимный подкласс абстрактного класса. И тогда вы вызываете метод на вашем абстрактный класс ссылка, указывающая на подкласс.

это поведение четко указано в JLS-раздел # 15.9.1: -

если выражение создания экземпляра класса завершается в теле класса, то экземпляр класса является анонимным классом. Затем:

  • если T обозначает класс, то объявляется анонимный прямой подкласс класса с именем T. Это-ошибка времени компиляции, если класс, обозначаемый T, является конечным классом.
  • если T обозначает интерфейс, то анонимный прямой подкласс объекта, реализующий интерфейс с именем T объявленный.
  • в любом случае телом подкласса является тело класса, заданное в выражении создания экземпляра класса.
  • экземпляр класса является анонимным подклассом.

выделено мной.

кроме того, в JLS-раздел # 12.5, вы можете прочитать о Процесс Создания Объекта. Я процитирую одно утверждение из этого здесь: -

всякий раз, когда создается новый экземпляр класса, выделяется место в памяти для него есть место для всех переменных экземпляра, объявленных в классе тип и все переменные экземпляра, объявленные в каждом суперклассе тип класса, включая все переменные, которые могут быть скрыты.

непосредственно перед тем, как ссылка на вновь созданный объект возвращается как в результате указанный конструктор обрабатывается для инициализации нового объект, использующий следующее процедура:

вы можете прочитать о процедуре по ссылке, которую я предоставил.


практически видеть, что экземпляр класса является Анонимный Подкласс, вам просто нужно скомпилировать оба ваших класса. Предположим, вы помещаете эти классы в два разных файла:

мой.java:

abstract class My {
    public void myMethod() {
        System.out.print("Abstract");
    }
}

Поли.java:

class Poly extends My {
    public static void main(String a[]) {
        My m = new My() {};
        m.myMethod();
    }
}

теперь скомпилируйте оба источника файлы:

javac My.java Poly.java

сейчас в каталоге, где вы скомпилировали исходный код, вы увидите следующие файлы класса:

My.class
Poly.class  // Class file corresponding to anonymous subclass
Poly.class

видим, что класс Poly.class. Это файл класса, созданный компилятором, соответствующим анонимному подклассу, который вы создали, используя приведенный ниже код:

new My() {};

итак, ясно, что существует другой экземпляр класса. Просто этот класс получает имя только после компиляции компилятор.

в общем, все анонимные подклассы в вашем классе будут названы следующим образом:

Poly.class, Poly.class, Poly.class, ... so on

эти числа обозначают порядок, в котором эти анонимные классы появляются в заключительном классе.

выше создает анонимный внутренний класс, который является подклассом my абстрактный класс. Это не совсем эквивалентно созданию экземпляра самого абстрактного класса. OTOH, каждый экземпляр подкласса является экземпляром всех его суперклассов и интерфейсов, поэтому большинство абстрактных классов действительно создаются путем создания экземпляра одного из их конкретных подклассов.

если интервьюер просто сказал: "неправильно!"не объясняя, а приведя этот пример, как уникальный контрпример, я хотя, думаю, он не знает, о чем говорит.

= my() {}; означает, что существует анонимная реализация, а не простой экземпляр объекта, который должен был быть:= my(). Вы никогда не сможете создать экземпляр абстрактного класса.

просто наблюдения, которые вы могли бы сделать:

  1. почему poly выходит my? Это бесполезно...
  2. каков результат компиляции? Три файла:my.class,poly.class и poly.class
  3. если мы можем создать экземпляр абстрактного класса, как это, мы можем создать экземпляр интерфейса тоже... странный...


можем ли мы создать экземпляр абстрактного класса?

нет, мы не можем. это, создать анонимный класс (это третий файл) и создать его экземпляр.


как насчет экземпляра суперкласса?

абстрактный суперкласс не создается нас но по java.

EDIT: попросите его проверить это

public static final void main(final String[] args) {
    final my m1 = new my() {
    };
    final my m2 = new my() {
    };
    System.out.println(m1 == m2);

    System.out.println(m1.getClass().toString());
    System.out.println(m2.getClass().toString());

}

вывод:

false
class my
class my

вы можете просто ответить, всего в одной строке

нет, вы никогда не сможете создать экземпляр абстрактного класса

но, интервьюер все равно не согласен, тогда вы можете сказать ему/ей

все, что вы можете сделать, это создать анонимный класс.

и, согласно анонимному классу,класс объявлен и экземпляр в том же месте/line

Так что, вполне возможно, что, интервьюер было бы интересно проверить ваш уровень доверия и сколько вы знаете о Упс .

техническая часть была хорошо освещена в других ответах, и она в основном заканчивается:
"Он ошибается, он ничего не знает, попросите его присоединиться так и получить все это очищено :)"

Я хотел бы обратиться к тому факту (который был упомянут в других ответах), что это может быть стресс-вопрос и является важным инструментом для многих интервьюеров, чтобы узнать больше о вас и как вы реагируете в сложных и нестандартных ситуациях. Давая вам неправильные коды, он наверное хотел посмотреть, если вы утверждали обратно. Чтобы знать, есть ли у вас уверенность, чтобы противостоять своим старшим в ситуациях, подобных этой.

P. S: Я не знаю почему, но у меня такое ощущение, что интервьюер прочитал этот пост.

абстрактные классы не могут быть созданы, но они могут быть подклассами. Ссылка

лучший пример-это

хотя класс Calender имеет абстрактный метод getInstance (), но когда вы говорите Calendar calc=Calendar.getInstance();

calc ссылается на экземпляр класса класса GregorianCalendar как " GregorianCalendar расширяет календарь"

на самом деле annonymous внутренний типпозволяет создайте безымянный подкласс абстрактного класса и пример этого.

Технический Ответ

абстрактные классы не могут быть созданы-это по определению и дизайну.

из JLS, Глава 8. Классы:

именованный класс может быть объявлен абстрактным (§8.1.1.1) и должен быть объявлен абстрактный, если он не полностью реализован; такой класс не может быть экземпляр, но может быть расширен подклассами.

из JSE 6 java doc для Занятия.newInstance ():

InstantiationException-если этот класс представляет абстрактный класс, интерфейс, массив класс, тип примитива, или недействительными, или если класс имеет конструктор, не возвращающих значений; или если создание экземпляра не удается по какой-то другой причине.

вы можете, конечно, создать экземпляр конкретного подкласса абстрактного класса (включая анонимный подкласс), а также выполнить типизацию ссылки объекта на абстрактный класс тип.

Под Другим Углом На Это - Командная Игра И Социальный Интеллект:

" навыки работы с людьми "здесь могут быть важнее, чем"технические навыки". Если соревновательно и агрессивно пытаться доказать свою сторону аргумента, то вы можете быть теоретически правы, но вы также можете сделать больше урон в драке / повреждение "лица" / создание врага, чем это стоит. Будьте примирительными и понимающими в разрешении ваших разногласий. Кто знает-может быть, вы "оба правы", но отрабатываете немного разные значения для терминов??

кто знает - хотя и маловероятно, что интервьюер намеренно ввел небольшой конфликт / недоразумение, чтобы поставить вас в сложную ситуацию и посмотреть, как вы ведете себя эмоционально и социально. Будьте милостивы и конструктивно с коллегами, следовать советам от старших, и следовать через После интервью, чтобы решить любую проблему/недоразумение - по электронной почте или по телефону. Показывает, что вы мотивированы и ориентированы на детали.

это хорошо установленный факт, что abstract class можете не быть инстанцированы, как все ответили.

когда программа определяет анонимный класс, компилятор фактически создает новый класс с другим именем (имеет шаблон EnclosedClassName$n здесь n - это анонимный номер класса)

поэтому, если вы декомпилируете этот класс Java, вы найдете код, как показано ниже:

мой.класс

abstract class my { 
    public void mymethod() 
    { 
        System.out.print("Abstract"); 
    }
} 

Поли-1$.класс (сгенерированный класс "анонимный класс")

class poly extends my 
{
} 

ploly.касс

public class poly extends my
{
    public static void main(String[] a)
    {
        my m = new poly.1(); // instance of poly.1 class NOT the abstract my class

        m.mymethod();
    }
}

нет, вы не можете создать экземпляр абстрактного класса.Мы создаем только анонимные экземпляры class.In абстрактный класс мы объявляем абстрактные методы и определяем только конкретные методы.

Об Абстрактных Классах

  • не удается создать объект абстрактного класса
  • может создавать переменные (может вести себя как типы данных)
  • если ребенок не может переопределить хотя бы один абстрактный метод родителя, то ребенок также становится абстрактным
  • абстрактные классы бесполезны без дочерних классов

цель абстрактного класса-вести себя как база. В иерархии наследования вы увидите абстрактные классы к вершине.

вы можете сказать:
мы не можем создать экземпляр абстрактного класса, но мы можем использовать new ключевое слово для создания анонимного экземпляра класса, просто добавив {} как реализовать тело в конце абстрактный класс.

расширение класса не означает, что вы создаете экземпляр класса. На самом деле, в вашем случае вы создаете экземпляр подкласса.

Я уверен, что абстрактные классы не допускать возбуждения. Итак, я бы сказал Нет: вы не можете создать экземпляр абстрактного класса. Но, вы можете расширить его / наследовать его.

вы не можете напрямую создать экземпляр абстрактного класса. Но это не значит, что вы не можете получить экземпляр класса (не actully экземпляр исходного абстрактного класс) косвенно. Я имею в виду, что вы не можете создать экземпляр исходного абстрактного класса, но вы можете:

  1. создать пустой класс
  2. наследовать от абстрактного класса
  3. создать экземпляр класса dervied

таким образом, вы получаете доступ ко всем методам и свойствам в абстрактном классе через экземпляр производного класса.

невозможно создать экземпляр абстрактного класса. То, что вы действительно можете сделать, имеет реализацию некоторых общих методов в абстрактном классе и позволяет другим нереализованным (объявляя их абстрактными) и позволяет конкретному потомку реализовать их в зависимости от своих потребностей. Затем вы можете сделать фабрику, которая возвращает экземпляр этого абстрактного класса (фактически его реализатор). На заводе вы потом решаете, какого исполнителя выбрать. Это известно как заводской дизайн выкройка:

   public abstract class AbstractGridManager {
        private LifecicleAlgorithmIntrface lifecicleAlgorithm;
        // ... more private fields

        //Method implemented in concrete Manager implementors 
        abstract public Grid initGrid();

        //Methods common to all implementors
        public Grid calculateNextLifecicle(Grid grid){
            return this.getLifecicleAlgorithm().calculateNextLifecicle(grid);
        }

        public LifecicleAlgorithmIntrface getLifecicleAlgorithm() {
            return lifecicleAlgorithm;
        }
        public void setLifecicleAlgorithm(LifecicleAlgorithmIntrface lifecicleAlgorithm) {
            this.lifecicleAlgorithm = lifecicleAlgorithm;
        }
        // ... more common logic and getters-setters pairs
    }

конкретному исполнителю нужно только реализовать методы, объявленные как абстрактные, но он будет иметь доступ к логике, реализованной в тех классах абстрактного класса, которые не объявлены абстрактными:

public class FileInputGridManager extends AbstractGridManager {

private String filePath;

//Method implemented in concrete Manager implementors 
abstract public Grid initGrid();

public class FileInputGridManager extends AbstractGridManager {

    private String filePath;

    //Method implemented in concrete Manager implementors 
    abstract public Grid initGrid();

    public Grid initGrid(String filePath) {
        List<Cell> cells = new ArrayList<>();
        char[] chars;
        File file = new File(filePath); // for example foo.txt
        // ... more logic
        return grid;
    }
}

затем, наконец, завод выглядит примерно так:

public class GridManagerFactory {
    public static AbstractGridManager getGridManager(LifecicleAlgorithmIntrface lifecicleAlgorithm, String... args){
        AbstractGridManager manager = null;

        // input from the command line
        if(args.length == 2){
            CommandLineGridManager clManager = new CommandLineGridManager();
            clManager.setWidth(Integer.parseInt(args[0]));
            clManager.setHeight(Integer.parseInt(args[1]));
            // possibly more configuration logic
            ...
            manager = clManager;
        } 
        // input from the file
        else if(args.length == 1){
            FileInputGridManager fiManager = new FileInputGridManager();
            fiManager.setFilePath(args[0]);
            // possibly more method calls from abstract class
            ...
            manager = fiManager ;
        }
        //... more possible concrete implementors
        else{
            manager = new CommandLineGridManager();
        }
        manager.setLifecicleAlgorithm(lifecicleAlgorithm);
        return manager;
    }
}

получатель AbstractGridManager вызовет методы на нем и получит логику, реализованную в конкретном спуске (и частично в абстрактном методы класса), не зная, какую конкретную реализацию он получил. Это также известно как инверсия управления и внедрение зависимостей.

нет, мы не можем создать объект абстрактного класса, но создать ссылочную переменную абстрактного класса. Ссылочная переменная используется для обращения к объектам производных классов (подклассов абстрактного класса)

вот пример, который иллюстрирует эту концепцию

abstract class Figure { 

    double dim1; 

    double dim2; 

    Figure(double a, double b) { 

        dim1 = a; 

        dim2 = b; 

    } 

    // area is now an abstract method 

    abstract double area(); 

    }


    class Rectangle extends Figure { 
        Rectangle(double a, double b) { 
        super(a, b); 
    } 
    // override area for rectangle 
    double area() { 
        System.out.println("Inside Area for Rectangle."); 
        return dim1 * dim2; 
    } 
}

class Triangle extends Figure { 
    Triangle(double a, double b) { 
        super(a, b); 
    } 
    // override area for right triangle 
    double area() { 
        System.out.println("Inside Area for Triangle."); 
        return dim1 * dim2 / 2; 
    } 
}

class AbstractAreas { 
    public static void main(String args[]) { 
        // Figure f = new Figure(10, 10); // illegal now 
        Rectangle r = new Rectangle(9, 5); 
        Triangle t = new Triangle(10, 8); 
        Figure figref; // this is OK, no object is created 
        figref = r; 
        System.out.println("Area is " + figref.area()); 
        figref = t; 
        System.out.println("Area is " + figref.area()); 
    } 
}

здесь мы видим, что мы не можем создать объект типа Figure, но мы можем создать ссылочную переменную типа Figure. Здесь мы создали ссылочной переменной из типа фигуры и рис. Переменная ссылки на класс используется для ссылки на объекты класса прямоугольник и треугольник.

Comments

    Ничего не найдено.