newinstance java что это
Какую роль выполняет метод newInstance в Java?
По книги Thinking Java, требует выполнить упражнение. Итак, прежде всего я создают топовый класс:
public class TOP implements itf2, itf1<>
Далее создаю несколько интерфейсов.
Далее создаю несколько классов расширяемые по иерархии
И соотвественно создаю главный класс с методами.
Теперь, мне нужно сделать сделать это в виде массива, для этого нужно использовать newInstance. Но дело в то, что я не понимаю, для чего он именно нужен. Пример кода:
Топовый класс:
Далее создаю дополнительный класс и создаю массив типа List
И соотвесвтенно создаю главный класс
Для чего и для каких целей используется метод newInstance, как ис ним правильно работать?
thatmaniscool: рефлексия довольно сложная и к ней лучше вернуться потом. В целом такие фишки используются для динамической работы с неизвестными классами. Т.е. к примеру можно так взять скомпилированный class файлик и работать с ним, посмотреть его методы, переменные и сделать его экземпляр. Можно к примеру залезть в класс и что то изменить в нем. Но это уже совсем глубоко.
Банальный пример, к примеру ты пишешь библиотеку в которой хотелось бы взять заранее неизвестный класс и сериализовать его в json. Для этого ты делаешь такое вот фокус:
Провернуть такое с помощью интерфейса намного сложнее или невозможно.
Дальше можно также и десериализовать по принципу
Как то так если пытаться объяснить на пальцах.
Инстанцируем java.lang.Class
Конструктор java.lang.Class является одной из самых охраняемых сущностей в языке Java. В спецификации чётко сказано, что объекты типа Class может создавать только сама JVM и что нам тут делать нечего, но так ли это на самом деле?
Предлагаю погрузиться в глубины Reflection API (и не только) и выяснить, как там всё устроено и насколько трудно будет обойти имеющиеся ограничения.
Эксперимент я провожу на 64-битной JDK 1.8.0_151 с дефолтными настройками. Про Java 9 будет в самом конце статьи.
Уровень 1. Простой
Начнём с самых наивных попыток и пойдём по нарастающей. Сперва посмотрим врагу в лицо:
Ничего особенного этот конструктор собой не представляет. Компилятор не делает для него никаких исключений, и в байткоде конструктор тоже присутствует. Поэтому попробуем поступить так же, как мы бы поступили с любым другим классом:
Вполне ожидаемо данный код не будет работать и выдаст следующую ошибку:
Уровень 2. Посложнее
Уровень 3. Нативный
Время узнать, каких вообще типов бывают объекты ConstructorAccessor (помимо описанного выше):
Здесь нет никаких подвохов: объект создаётся без лишних ограничений, и всё, что нам остаётся, так это с его помощью инстанцировать java.lang.Class :
Но тут ждёт сюрприз:
Уровень 4. Магический
Такой код, естественно, обратно не скомпилируется, и этому есть две причины:
Данные инструкции разнесены для того, чтобы находиться в разных try-блоках. Почему сделано именно так, я не знаю. Вероятно, это был единственный способ обрабатывать исключения так, чтобы они полностью соответствовали спецификации языка.
Если закрыть глаза на нетипичную обработку исключений, то во всём остальном данный класс абсолютно нормален, но всё ещё непонятно, откуда у него вдруг права на вызов приватных конструкторов. Оказывается, всё дело в суперклассе:
и опять получаем исключение:
Вот это уже действительно интересно. Судя по всему, обещанной магии не произошло. Или я ошибаюсь?
Уровень 5. Современный
Reflection не помог решить проблему. Может быть, дело в том, что Reflection старый и слабый, и вместо него стоит использовать молодой и сильный MethodHandles? Думаю, да. Как минимум, стоит попробовать.
И как только я решил, что Reflection не нужен, он тут же пригодился. MethodHandles — это, конечно, хорошо, но с помощью него принято получать лишь те данные, к которым есть доступ. А если понадобился приватный конструктор, то придётся выкручиваться по старинке.
После запуска этого метода я был откровенно удивлён — lookup делает вид, что конструктора вообще не существует, хотя он точно присутствует в классе!
Данный метод уж точно корректно отработает и вернёт тот handle, который должен.
Момент истины. Запускаем метод инстанцирования:
Думаю, вы уже догадались, что ничего хорошего не произойдёт, но давайте хоть глянем на ошибку. Сейчас это что-то новенькое:
Раз даже Unsafe не смог, мне остаётся лишь прийти к печальному заключению: аллоцировать новый объект java.lang.Class невозможно. Интересно выходит — думал, что запрещён конструктор, а запрещена аллокация! Попробуем это дело обойти.
Уровень 6. Небезопасный
Предлагаю создать пустой объект и взглянуть, из чего же он состоит. Для этого возьмём Unsafe и аллоцируем новенький java.lang.Object :
На текущей JVM результатом будет область памяти в 12 байт, выглядящая вот так:
То, что вы здесь видите, это «заголовок объекта». По большому счёту, он состоит из двух частей — 8 байт markword, которые нас не интересуют, и 4 байта classword, которые важны.
Каким образом JVM узнаёт класс объекта? Она делает это путём чтения области classword, которая хранит указатель на внутреннюю структуру JVM, описывающую класс. Значит если в данное место записать другое значение, то и класс объекта изменится!
Дальнейший код очень, очень плохой, никогда так не делайте:
Так начинается создание класса (константы импортированы статически, так короче):
Так ему создаётся конструктор:
Класс готов. Осталось загрузить, инстанцировать и вызвать нужный метод:
И это работает! Точнее так: повезло, что работает. Можно проверить, запустив следующий код:
О том, в какую область памяти записался этот ClassLoader и откуда потом прочитался, я тактично умолчу. И, как ожидалось, вызов практически любого другого метода на данном объекте приводит к немедленному краху JVM. А в остальном — цель выполнена!
Что там в Java 9?
В Java 9 всё почти так же. Можно проделать все те же действия, но с несколькими оговорками:
В целом, в Java 9 нужно намного сильнее постараться, чтобы выстрелить себе в ногу, даже если именно это и является главной целью. Думаю, это и к лучшему.
Создание объекта Java
Java – это объектно-ориентированный язык. Другими словами, почти все в Java рассматривается как объект.
Использование ключевого слова «new»
При программировании вы наверняка сталкивались с ключевым словом «new», используемым для создания объекта, которому динамически выделяется память, т.е. память этим объектам выделяется во время выполнения. И это динамическое распределение требуется большую часть времени при создании объектов. Следовательно, этот метод используется чаще, чем другие.
Синтаксис
ClassName ObjectName = new classConstructor();
Пример
Выход – Hello World
Этот метод создания объектов в Java может использоваться с любым конструктором требуемого класса, если класс имеет более одного конструктора.
Использование метода clone()
Метод clone() можно использовать только после реализации интерфейса Cloneable и обработки исключения CloneNotSupportedException.
Пример
Вывод
Welcome to the world of programming
В приведенной выше программе мы создали копию нашего уже существующего объекта. Чтобы обе переменные не указывали на одну и ту же ячейку памяти, было важно изменить значение «FirstString» для второго объекта, а затем распечатать его значение для обоих объектов.
Использование метода newInstance() класса Class
Этот метод не часто используется для создания объектов, в случаях, когда мы знаем имя класса, а конструктор по умолчанию является публичным по своей природе. Чтобы использовать его, нам нужно обработать 3 исключения
Пример
Выход – Hello World
Использование десериализации
В Java сериализация используется для преобразования текущего состояния объекта в поток байтов. десериализация является полной противоположностью, поскольку мы воссоздаем объект, используя поток байтов. Для процесса сериализации нам необходимо реализовать интерфейс Serializable.
Обработка исключений должна быть сделана для создания объектов с использованием этого метода.
Использование метода newInstance() класса Constructor
Мы увидели метод newInstance класса Class, который мы использовали для создания объекта. Точно так же конструктор класса также состоит из метода newInstance(), который можно использовать для создания объектов. Другие могут использовать конструкторы Java по умолчанию с помощью этого метода, мы также можем вызвать параметризованные конструкторы.
Welcome to the world of programming.
Это 5 различных способов создания объектов в Java, которые используются чаще других. Каждый метод имеет свои преимущества и недостатки. В конце концов, выбор за вами.
Полное руководство по Java Reflection API. Рефлексия на примерах
В этой статье мы познакомимся со всеми элементами и функциональными возможностями Java Reflection API.
Рефлексия в Java — это механизм, с помощью которого можно вносить изменения и получать информацию о классах, интерфейсах, полях и методах во время выполнения, при этом не зная имен этих классов, методов и полей. Кроме того, Reflection API дает возможность создавать новые экземпляры классов, вызывать методы, а также получать или устанавливать значения полей.
Начинающие Java-программисты часто путают рефлексию с интроспекцией. Интроспекция — проверка кода и возможность видеть типы объектов во время выполнения. Рефлексия дает возможность вносить изменения во время выполнения программы путем использования интроспекции. Здесь важно понимать различие, поскольку некоторые языки поддерживают интроспекцию, но не поддерживают рефлексию, например, C++.
В этом руководстве мы рассмотрим не только базовые, но и более продвинутые возможности Reflection API.
Java Reflection API
Рефлексия — мощная концепция, которая лежит в основе большинства современных Java/Java EE фреймворков и библиотек. Например, для Java классическими примерами являются:
Список можно продолжать бесконечно: от веб-контейнеров до решения задач объектно-реляционного отображения (ORM). Их всех объединяет одно: они используют Java рефлексию, потому что не имеют доступа и представления к определенных пользователем классах, методах, интерфейсах и т.д.
Ограничения при работе с рефлексией в Java
Почему мы не должны использовать рефлексию в обычном программировании, когда уже есть доступ к интерфейсам и классам. Причин несколько:
Constructor newInstance() method in Java with Examples
The newInstance() method of a Constructor class is used to create and initialize a new instance of this constructor, with the initialization parameters passed as parameter to this method. Each parameter is unwrapped to match primitive formal parameters, and both primitive and reference parameters are subject to method invocation conversions as necessary.
If the number of formal parameters of the constructor is 0, the supplied parameter is of length 0 or null. If the constructor completes normally, returns the newly created and initialized instance.
Attention reader! Don’t stop learning now. Get hold of all the important Java Foundation and Collections concepts with the Fundamentals of Java and Java Collections Course at a student-friendly price and become industry ready. To complete your preparation from learning a language to DS Algo and many more, please refer Complete Interview Preparation Course.
Syntax:
Parameters: This method accepts initargs as the parameter which is an array of objects to be passed as arguments to the constructor call. The values of primitive types are wrapped in a wrapper object of the appropriate type (e.g. float in Float).
Return value: This method returns a new object created by calling the constructor this object represents.
Below programs illustrate the newInstance() method:
Program 1: