Теперь это возможно
Но вам нужно будет, чтобы ваше устройство было запущено на java 1.8 и разрешено «jackOptions» «запустить его. Джек - это имя нового Android-компилятора, который запускает Java 8
https://developer.android.com/guide/platform/j8-jack.html
добавьте эти строки в build_gradle
android {
...
defaultConfig {
...
jackOptions {
enabled true
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
Java 8 кажется запущенным движком java для Android studio 2.0, но он все еще не принимает синтаксис java 8 после того, как я проверил, и теперь вы не можете выбрать компилятор из студии Android. Тем не менее, вы можете использовать плагин scala, если вам нужен механизм функционального программирования в вашем Android-клиенте.
Я ожидаю, что выбор метода учитывает действительный (не объявленный) тип параметра. Я что-то упустил?
blockquote>Да. Ваши ожидания ошибочны. В Java динамическая отправка метода происходит только для объекта, на который вызывается метод, а не для типов параметров перегруженных методов.
Ссылаясь на Спецификацию языка Java :
Когда метод вызывается (§15.12), количество фактических аргументов (и любых явных аргументов типа) и типы аргументов во время компиляции используются во время компиляции для определения сигнатуры метод, который будет вызываться (§15.12.2). Если метод, который должен быть вызван, является методом экземпляра, фактический метод, который будет вызываться, будет определен во время выполнения, используя динамический поиск метода (§15.12.4).
blockquote>
Java ищет тип ссылки при попытке определить, какой метод вызывать. Если вы хотите заставить свой код выбрать «правильный» метод, вы можете объявить свои поля как экземпляры определенного типа:
Integeri = new Integer(12);
String s = "foobar";
Object o = new Object();
Вы также можете указать ваши параметры как тип параметра:
callee.foo(i);
callee.foo((String)s);
callee.foo(((Integer)o);
У меня была аналогичная проблема с вызовом правого конструктора класса под названием «Параметр», который мог бы принимать несколько базовых типов Java, таких как String, Integer, Boolean, Long и т. д. Учитывая массив объектов, я хочу их преобразовать в массив объектов Parameter, вызывая наиболее специфичный конструктор для каждого объекта во входном массиве. Я также хотел определить конструктор Parameter (Object o), который бы выбрал исключение IllegalArgumentException. Я, конечно, нашел, что этот метод вызывается для каждого объекта в моем массиве.
Решение, которое я использовал, - это поиск конструктора через отражение ...
public Parameter[] convertObjectsToParameters(Object[] objArray) {
Parameter[] paramArray = new Parameter[objArray.length];
int i = 0;
for (Object obj : objArray) {
try {
Constructor<Parameter> cons = Parameter.class.getConstructor(obj.getClass());
paramArray[i++] = cons.newInstance(obj);
} catch (Exception e) {
throw new IllegalArgumentException("This method can't handle objects of type: " + obj.getClass(), e);
}
}
return paramArray;
}
Не требуется уродливого экземпляра, операторов switch или шаблона посетителя! :) [/ Д2]
Возможность отправки вызова методу, основанному на типах аргументов, называется multiple dispatch . В Java это делается с шаблоном посетителя .
Однако, поскольку вы имеете дело с Integer
s и String
s, вы не можете легко включить этот шаблон (вы просто не могут изменять эти классы). Таким образом, гигантское switch
на время выполнения объекта будет вашим оружием выбора.
Если существует точное соответствие между количеством и типами аргументов, указанными в вызове метода, и сигнатурой метода перегруженного метода, то это метод, который будет вызываться. Вы используете ссылки на объекты, поэтому java решает во время компиляции, что для параметра Object существует метод, который принимает непосредственно Object. Так он назвал этот метод 3 раза.
Как упоминалось ранее, во время компиляции выполняется перегрузка разрешения.
Java Puzzlers имеет приятный пример:
Головоломка 46: Случай Confusing Constructor
Эта головоломка представляет вам два конструктора Confusing. Основной метод вызывает конструктор, но какой? Выход программы зависит от ответа. Что делает программа, или она даже законна?
public class Confusing {
private Confusing(Object o) {
System.out.println("Object");
}
private Confusing(double[] dArray) {
System.out.println("double array");
}
public static void main(String[] args) {
new Confusing(null);
}
}
Решение 46: Случай смущающего конструктора
... Процесс разрешения перегрузки Java работает в два этапа. На первом этапе выбираются все доступные или применимые методы или конструкторы. Вторая фаза выбирает наиболее специфичный методов или конструкторов, выбранных на первой фазе. Один метод или конструктор менее конкретный , чем другой, если он может принимать любые параметры, переданные другому [JLS 15.12.2.5].
В нашей программе оба конструктора доступны и применимы , Конструктор Confusing (Object) принимает любой параметр, переданный в Confusing (double []) , поэтому Confusing (Object) менее специфичен. (Каждый двойной массив является Object , но не каждый Object является двойным массивом .) Наиболее специфический конструктор поэтому Confusing (double []) , который объясняет вывод программы.
Такое поведение имеет смысл, если вы передадите значение типа double [] ; это противоречит, если вы передадите null . Ключом к пониманию этой головоломки является то, что тест, для которого метод или конструктор наиболее специфичен, не использует фактические параметры: параметры, появляющиеся в вызове. Они используются только для определения того, какие перегрузки применимы. Когда компилятор определяет, какие перегрузки применимы и доступны, он выбирает наиболее специфическую перегрузку, используя только формальные параметры: параметры, появляющиеся в объявлении.
Чтобы вызвать Confusing (Object) с параметром null , напишите new Confusing ((Object) null) . Это гарантирует, что применим только Confusing (Object) . В более общем плане, чтобы заставить компилятор выбрать конкретную перегрузку, применить фактические параметры к объявленным типам формальных параметров.
В Java метод вызова (как в используемой сигнатуре метода) определяется во время компиляции, поэтому он идет с типом времени компиляции.
Типичный шаблон для работы вокруг этого заключается в проверке тип объекта в методе с сигнатурой объекта и делегировать метод с литой.
public void foo(Object o) {
if (o instanceof String) foo((String) o);
if (o instanceof Integer) foo((Integer) o);
logger.debug("foo(Object o)");
}
Если у вас много типов, и это неуправляемо, то перегрузка метода, вероятно, не является правильным подходом, скорее публичный метод должен просто взять Object и реализовать какой-то шаблон стратегии для делегирования соответствующей обработки для каждого типа объекта.
foo(Object)
. Во время выполнения класс объекта , вызываемый в , определяет, какая реализация этого метода вызывается, принимая во внимание, что он может быть экземпляром подкласса объявленного типа, который переопределяет метод. – Michael Borgwardt 3 May 2012 в 22:31