Comments 13
Вещь, интересная и в каких-то случаях даже полезная. Но, блин, var
... Вот не зря говорили, что от него больше вреда, чем пользы.
Метод
compile()
генерирует байт-коды для исходных файлов Java, но пока не загружает их в память.
final var byteCodes = Compiler.java()
.from("com.app", source)
.compile();
Как мне, ни разу не пользовавшемуся данной библиотекой понять, что есть эти самые байт-коды? Учитывая, что они не загружаются в память, я логично предположил, что byte[]
. Но буквально парой строк ниже вижу byteCodes.saveTo()
, т.е. таки некий ByteCode(s?)
.
Читаем далее и видим
Метод
byteCodes.load()
загружает классы и преобразует байт-код в объекты типаClass
:
final var loadedClasses = compiled.load();
Опять же, полагаем, что loadedClasses
- это Class
. Но и тут мы оказываемся неправы, потому что Class<?> customClass = loadedClasses.get("com.app.CustomClass")
, т.е. по факту это опять же какой-то библиотечный класс.
Понятно, что это перевод, но ужель у самого переводчика не возникло таких вопросов?
З.Ы.
Кто-нибудь знает как в этом редакторе вставлять блоки кода внутрь цитаты?
вы здесь не правы, под интерфейсом тоже не видно реализации.
Всё-таки это автовыведение, а не динамическая типизация, IDE подсказывает тип переменной.
А без IDE, читая код с хабра.... вам имя класса собственно зачем?
А без IDE, читая код с хабра.... вам имя класса собственно зачем?
Я тебе один умный вещь скажу, но ты не обижайся. (с) Мне не имя класса нужно, а понимание, что вообще данный метод возвращает. Хотя бы затем, чтобы можно было сравнить подходы в новом читаемом и уже известном кодах.
Всё-таки это автовыведение, а не динамическая типизация
Это автовыведение, в данном конкретном случае, только всё усложняет и по большей части грозит потенциальными проблемами. Например, такой код не компилируется, потому что list - ArrayList, а не List.
var list = new ArrayList<String>();
// 100500 строк кода
list = Collections.emptyList();
такой код не компилируется, потому что list - ArrayList, а не List.
Пример точно так же бы не скомпилировался, будь там:
ArrayList<String> list = new ArrayList<>();
То есть проблема здесь не в var, а в неверном выборе типа переменной.
грозит потенциальными проблемами.
Тут могут быть какие-то настоящие проблемы, от которых не защитит компилятор?
только всё усложняет
Напротив - спасает от необходимости искать отличия слева и справа в тривиальных случаях.
проблема здесь не в var, а в неверном выборе типа переменной.
И как часто вы работаете с переменными типа ArrayList или HashMap? Или всё-таки это List или Map? А если мне всё равно придётся писать List list = new ArrayList()
, то какой смысл в var
?
Я считаю, что var
должен был быть val
: сахарком для final переменной, для которой тип можно вывести и будет по барабану List там или ArrayList, потому что записать в переменную всё равно ничего не получится.
искать отличия слева и справа
А зачем их искать? Тип определён слева, что там справа в подавляющем большинстве случаев неважно. От несоответствия типов опять же защитит компилятор.
И как часто вы работаете с переменными типа ArrayList или HashMap? Или всё-таки это List или Map?
Всегда, когда справа new
. Вообще, для локальных переменных редко имеет смысл ставить тип, отличный от того, что справа (или он подразумевается очевидным образом).
для которой тип можно вывести
То есть "тупой" var
называете усложнением, а (нетривиальный) вывод типа - ок?
А зачем их искать?
Тип слева может сужать функционал объекта справа. Чтобы знать насколько, очевидно)
То есть "тупой"
var
называете усложнением, а (нетривиальный) вывод типа - ок?
Подозреваю, что меня неправильно поняли. Во-первых, вывод типа - это дело компилятора, а не разработчика. И он нужен и в первую очередь совсем не для var
-а. Во-вторых, под усложнением я имел ввиду именно понимание кода при чтении, а не то, как это реализовано.
Вообще, для локальных переменных редко имеет смысл ставить тип, отличный от того, что справа
Вообще нет. Утверждение истинно только при условии, что эти переменные как минимум effective final.
Тип слева может сужать функционал объекта справа.
Может, но как я писал ранее в подавляющем большинстве случаев это неважно. Как часто вы использовали ArrayList#trimToSize(int)
или ConcurrentHashMap.contains(Object)
?
он нужен и в первую очередь совсем не для var-а.
Понял вас так: компилятор смотрит вниз по сценариям использования и выводит наименее общий тип, удовлетворяющий всем этим сценариям. То есть если тип объекта — ArrayList, а используется он лишь в рамках List, то выводится List. Это не выглядит очевидным.
под усложнением я имел ввиду именно понимание кода при чтении
Почему увидев var
сложно понять, скажем, что тип переменной идентичен типу справа от new
?
Вообще нет. Утверждение истинно только при условии, что эти переменные как минимум effective final.
Ну раскройте) Что им мешает быть мутабельными, если нам это необходимо?
Как часто вы использовали ArrayList#trimToSize(int) или ConcurrentHashMap.contains(Object)?
Не вижу особо проблем, кроме того, что второй метод задепрекейчен. Давайте сразу к сути проблемы, пожалуйста.
Что им мешает быть мутабельными, если нам это необходимо?
Ничего не мешает. Но это неудобно. В первую очередь потому, что ломаются основные паттерны работы с java-кодом. Как я уже писал ранее такой код невалиден.
var list = new ArrayList();
list = Collections.emptyList();
Давайте сразу к сути проблемы, пожалуйста.
Нет проблемы, на вопрос-то ответите: как часто вы в повседневном коде используете методы, определённые для конкретной реализации общего интерфейса?
как часто вы в повседневном коде используете методы, определённые для конкретной реализации общего интерфейса?
Как уже говорил выше, я всегда использую var
, когда справа new
и зачастую, когда справа метод с очевидным типом. То есть использую конкретные реализации.
Как я уже писал ранее такой код невалиден.
Можно написать new ArrayList<>()
и код будет валиден. Мы же знаем тип, мы сами его тут создаем, к чему тут интерфейс?
Нет проблемы
Если "основные паттерны" не решают какие-либо проблемы, то это просто привычки.
Разницу между
используете методы, определённые для конкретной реализации
и
использую конкретные реализации.
принципиально не замечаете?
Можно написать
new ArrayList<>()
и код будет валиден.
Ага, а потом "java тормозит, жрёт память".
Мы же знаем тип, мы сами его тут создаем, к чему тут интерфейс?
К тому, что в java принято работать с максимально возможно узким типом.
принципиально не замечаете?
Нет, подсветите разницу.
а потом "java тормозит, жрёт память".
Сомневаюсь, что нельзя обойтись без перезаписывания переменной. Если возврат — ранний return Collections.emptyList()
, если добавляем в какую-то коллекцию List
, то collection.add( Collections.emptyList())
.
Мешать инлайнингу вызовов интерфейсами и параллельно рассуждать о производительности — это странно)
в java принято работать с максимально возможно узким типом
В Java принято контракты делать максимально гибкими, что логично. Делая то же самое для локальных переменных — это уже похоже культ карго.
SourceBuddy динамически компилирует исходный код Java