|
|
|
Стирание типов в java, как проверить?
|
|||
|---|---|---|---|
|
#18+
Изучаю java, в настоящий момент дошел до изучения обобщенных классов и методов. В различной литературе сказано, что параметр типа будет удален при компиляции, Переменные типа стираются и заменяются ограничивающими типами (или типом Object, если переменная не имеет ограничений) Как это проверить? Как узнать какой код в результате будет выполнятся jvm ? Создал простой обобщенный класс с параметром типа, скомпилировал в .class, затем декомпилировал с помощью http://www.javadecompilers.com И... получил в точности свой исходный файл(!), включая обобщенный тип! Который вроде как должен был быть удален при компиляции?!! Никаких замен на Object нет и в помине! Я что-то не так понял? Друзья, помогите разобраться... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2017, 19:43 |
|
||
|
Стирание типов в java, как проверить?
|
|||
|---|---|---|---|
|
#18+
ll13, В некоторых случаях Generic тип доступен через рефлексию. Например вот в таком: Код: java 1. 2. А посмотреть на erasure можно разными способами. Например, написать Generic метод\класс, а рефлексией посмотреть сигнатуру - поля и методы и увидеть как Generic тип поменялся на "ограничивающий". Для локальных переменных и смотреть особо нечего. Например, любая коллекция может содаржать объекты любого типа. Компилятор просто пытается вам не дать поместить их туда валидируя Generic. Но это не значит что вы не можете прикастить, подавить предупреждение и отгрести потом ClassCastException в рантайме. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2017, 19:52 |
|
||
|
Стирание типов в java, как проверить?
|
|||
|---|---|---|---|
|
#18+
Э... все равно не совсем понял( Я пришел с другого языка, поэтому скорее всего не конца понимаю как работает компилятор и JVM, но хочу это понять... Давайте , на примере, есть обобщенный класс: public class genTest<T> { private T value = null; public genTest(T value) { this.value= value; } public T getValue() { return value; } @Override public String toString() { return "genTest{" + "value=" + value + '}'; } public static void main(String[] args) { genTest<String> pstr = new Pair<>("aaa""); System.out.println(pstr); genTest<Integer> pint = new Pair<>(333); System.out.println(pint); } После его компиляции я получу файл genTest.class содержащий байт-код, который и будет выполнять виртуальная машина java. В литературе пишут, что виртуальная машина java никаких обобщенных типов знать не знает и компилятор при создании genTest.class сотрет все параметры типов и сделает все соответствующие подстановки. Таким образом genTest.class уже содержит обычные классы и не содержит обобщенных. Я правильно рассуждаю? Далее я декомпилирую genTest.class с помощью http://www.javadecompilers.com и получаю точно такой же исходный файл genTest.java, который содержит обобщенный класс! Откуда он там, если он уже был "преобразован" компилятором?! ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2017, 22:29 |
|
||
|
Стирание типов в java, как проверить?
|
|||
|---|---|---|---|
|
#18+
Следует читать: ll13 ... genTest<String> pstr = new genTest<>("aaa""); System.out.println(pstr); genTest<Integer> pint = new genTest<>(333); System.out.println(pint); ... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.09.2017, 22:36 |
|
||
|
Стирание типов в java, как проверить?
|
|||
|---|---|---|---|
|
#18+
ll13, Попробуй скомпилировать этот класс: Код: java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2017, 05:44 |
|
||
|
Стирание типов в java, как проверить?
|
|||
|---|---|---|---|
|
#18+
ll13В литературе пишут, что виртуальная машина java никаких обобщенных типов знать не знает и компилятор при создании genTest.class сотрет все параметры типов и сделает все соответствующие подстановки. Это очень грубое приближение. На самом деле всё намного сложнее. http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html Вот пример того что JVM знает о генериках. https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getGenericInterfaces-- https://docs.oracle.com/javase/8/docs/api/java/lang/Class.html#getGenericSuperclass-- ll13Таким образом genTest.class уже содержит обычные классы и не содержит обобщенных. Я правильно рассуждаю? В целом, да. Но вы местами делаете выводы основываясь на ограниченных знаниях. ll13Далее я декомпилирую genTest.class с помощью http://www.javadecompilers.com и получаю точно такой же исходный файл genTest.java, который содержит обобщенный класс! Потому что вы не правильно понимаете erasure. public class GenTest<T> -> эта информация никуда не девается. Java знает что GetTest содержит в себе генерик. Это часть сигнатуры класса. GenTest<String> test = new GenTest<>(); - а вот эта информация о том что переменная test ограничена не только классом GetTest но и его генерик типом String - вот эта информация и теряется. В рантайме у нас есть только GetTest, который может работать с любым типом объекта. ll13Откуда он там, если он уже был "преобразован" компилятором?! Ну, компилятор сохраняет в мета описании класса больше информации. Я привел выше методы. Это она и есть. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2017, 07:20 |
|
||
|
Стирание типов в java, как проверить?
|
|||
|---|---|---|---|
|
#18+
guest2, Я знаю что не скомпилируется... потому-что параметры методов будут одного и того же типа List ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 08.09.2017, 18:49 |
|
||
|
|

start [/forum/topic.php?desktop=1&fid=59&tid=2122605]: |
0ms |
get settings: |
7ms |
get forum list: |
14ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
52ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
52ms |
get tp. blocked users: |
1ms |
| others: | 200ms |
| total: | 340ms |

| 0 / 0 |
