javascript, который используется для отображения div, модифицированного для работы с несколькими уникальными divs

Под капотом

Используя некоторые скрытые функции javac, мы можем получить более подробную информацию о том, что происходит:

$ javac -XDverboseResolution=deferred-inference,success,applicable LambdaInference.java 
LambdaInference.java:16: Note: resolving method foo in type Foo to candidate 0
    Foo.foo(value -> true).booleanValue(); // Compile error here
       ^
  phase: BASIC
  with actuals: 
  with type-args: no arguments
  candidates:
      #0 applicable method found: foo(Bar)
        (partially instantiated to: (Bar)Object)
  where T is a type-variable:
    T extends Object declared in method foo(Bar)
LambdaInference.java:16: Note: Deferred instantiation of method foo(Bar)
    Foo.foo(value -> true).booleanValue(); // Compile error here
           ^
  instantiated signature: (Bar)Object
  target-type: 
  where T is a type-variable:
    T extends Object declared in method foo(Bar)
LambdaInference.java:16: error: cannot find symbol
    Foo.foo(value -> true).booleanValue(); // Compile error here
                          ^
  symbol:   method booleanValue()
  location: class Object
1 error

Это много информации, давайте сломаем его .

LambdaInference.java:16: Note: resolving method foo in type Foo to candidate 0
    Foo.foo(value -> true).booleanValue(); // Compile error here
       ^
  phase: BASIC
  with actuals: 
  with type-args: no arguments
  candidates:
      #0 applicable method found: foo(Bar)
        (partially instantiated to: (Bar)Object)
  where T is a type-variable:
    T extends Object declared in method foo(Bar)

фаза: применяется применимость фаза : фактические аргументы, переданные в аргументах типа-args: явные типы: потенциально применимые методы

имеет значение , поскольку наша неявно типизированная лямбда не является , относящейся к применимости .

Компилятор разрешает ваш вызов foo единственному методу назван foo в Foo. Он частично был создан для Foo. foo (поскольку не было никаких фактических данных или типов-аргументов), но это может измениться на стадии отложенного вывода.

LambdaInference.java:16: Note: Deferred instantiation of method foo(Bar)
    Foo.foo(value -> true).booleanValue(); // Compile error here
           ^
  instantiated signature: (Bar)Object
  target-type: 
  where T is a type-variable:
    T extends Object declared in method foo(Bar)

экземплярная подпись: полностью созданная подпись foo. Это результат этого шага (в этот момент больше не будет сделан вывод о типе на подпись foo). target-type: контекст, в который делается вызов. Если вызов метода является частью назначения, он будет левым. Если вызов метода сам по себе является частью вызова метода, это будет тип параметра.

Поскольку ваш вызов метода свисает, нет целевого типа. Поскольку нет целевого типа, больше никаких выводов на foo и T не предполагается Object.


Анализ

Компилятор не использует неявно типизированные лямбда во время вывода. В определенной степени это имеет смысл. В общем, учитывая param -> BODY, вы не сможете скомпилировать BODY, пока у вас не будет типа для param. Если вы попытались вывести тип для param из BODY, это может привести к проблеме типа курица и яйцо. Возможно, некоторые улучшения будут сделаны в этом в будущих выпусках Java.


Решения

Foo. foo(value -> true)

Это решение обеспечивает явный тип аргумент foo (обратите внимание на раздел with type-args ниже). Это изменяет частичное копирование сигнатуры метода на (Bar)Boolean, что вы хотите.

LambdaInference.java:16: Note: resolving method foo in type Foo to candidate 0
    Foo. foo(value -> true).booleanValue(); // Compile error here
       ^
  phase: BASIC
  with actuals: 
  with type-args: Boolean
  candidates:
      #0 applicable method found: foo(Bar)
        (partially instantiated to: (Bar)Boolean)
  where T is a type-variable:
    T extends Object declared in method foo(Bar)
LambdaInference.java:16: Note: resolving method booleanValue in type Boolean to candidate 0
    Foo. foo(value -> true).booleanValue(); // Compile error here
                                    ^
  phase: BASIC
  with actuals: no arguments
  with type-args: no arguments
  candidates:
      #0 applicable method found: booleanValue()

Foo.foo((Value value) -> true)

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

LambdaInference.java:16: Note: resolving method foo in type Foo to candidate 0
    Foo.foo((Value value) -> true).booleanValue(); // Compile error here
       ^
  phase: BASIC
  with actuals: Bar
  with type-args: no arguments
  candidates:
      #0 applicable method found: foo(Bar)
        (partially instantiated to: (Bar)Boolean)
  where T is a type-variable:
    T extends Object declared in method foo(Bar)
LambdaInference.java:16: Note: Deferred instantiation of method foo(Bar)
    Foo.foo((Value value) -> true).booleanValue(); // Compile error here
           ^
  instantiated signature: (Bar)Boolean
  target-type: 
  where T is a type-variable:
    T extends Object declared in method foo(Bar)
LambdaInference.java:16: Note: resolving method booleanValue in type Boolean to candidate 0
    Foo.foo((Value value) -> true).booleanValue(); // Compile error here
                                           ^
  phase: BASIC
  with actuals: no arguments
  with type-args: no arguments
  candidates:
      #0 applicable method found: booleanValue()

Foo.foo((Bar) value -> true)

То же, что и выше, но с немного отличающийся вкус.

LambdaInference.java:16: Note: resolving method foo in type Foo to candidate 0
    Foo.foo((Bar) value -> true).booleanValue(); // Compile error here
       ^
  phase: BASIC
  with actuals: Bar
  with type-args: no arguments
  candidates:
      #0 applicable method found: foo(Bar)
        (partially instantiated to: (Bar)Boolean)
  where T is a type-variable:
    T extends Object declared in method foo(Bar)
LambdaInference.java:16: Note: Deferred instantiation of method foo(Bar)
    Foo.foo((Bar) value -> true).booleanValue(); // Compile error here
           ^
  instantiated signature: (Bar)Boolean
  target-type: 
  where T is a type-variable:
    T extends Object declared in method foo(Bar)
LambdaInference.java:16: Note: resolving method booleanValue in type Boolean to candidate 0
    Foo.foo((Bar) value -> true).booleanValue(); // Compile error here
                                         ^
  phase: BASIC
  with actuals: no arguments
  with type-args: no arguments
  candidates:
      #0 applicable method found: booleanValue()

Boolean b = Foo.foo(value -> true)

Это решение обеспечивает явную цель для вызова вашего метода (см. target-type ниже). Это позволяет отложенному-инстанцированию выводить, что параметр типа должен быть Boolean вместо Object (см. instantiated signature ниже).

LambdaInference.java:16: Note: resolving method foo in type Foo to candidate 0
    Boolean b = Foo.foo(value -> true);
                   ^
  phase: BASIC
  with actuals: 
  with type-args: no arguments
  candidates:
      #0 applicable method found: foo(Bar)
        (partially instantiated to: (Bar)Object)
  where T is a type-variable:
    T extends Object declared in method foo(Bar)
LambdaInference.java:16: Note: Deferred instantiation of method foo(Bar)
    Boolean b = Foo.foo(value -> true);
                       ^
  instantiated signature: (Bar)Boolean
  target-type: Boolean
  where T is a type-variable:
    T extends Object declared in method foo(Bar)

Отказ от ответственности

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

Это также не полностью объясняет, почему изменение Bar для использования raw Value исправит эту проблему:

LambdaInference.java:16: Note: resolving method foo in type Foo to candidate 0
    Foo.foo(value -> true).booleanValue();
       ^
  phase: BASIC
  with actuals: 
  with type-args: no arguments
  candidates:
      #0 applicable method found: foo(Bar)
        (partially instantiated to: (Bar)Object)
  where T is a type-variable:
    T extends Object declared in method foo(Bar)
LambdaInference.java:16: Note: Deferred instantiation of method foo(Bar)
    Foo.foo(value -> true).booleanValue();
           ^
  instantiated signature: (Bar)Boolean
  target-type: 
  where T is a type-variable:
    T extends Object declared in method foo(Bar)
LambdaInference.java:16: Note: resolving method booleanValue in type Boolean to candidate 0
    Foo.foo(value -> true).booleanValue();
                          ^
  phase: BASIC
  with actuals: no arguments
  with type-args: no arguments
  candidates:
      #0 applicable method found: booleanValue()

По какой-то причине изменение этого параметра на использование raw Value позволяет отложенному экземпляру сделать вывод о том, что T является Boolean. Если бы мне пришлось размышлять, я бы предположил, что, когда компилятор пытается привязать лямбда к Bar, он может сделать вывод, что T - Boolean, глядя на тело лямбда. Это означает, что мой предыдущий анализ неверен. Компилятор может выполнять вывод типа в теле лямбда, но только в переменных типа, которые только появляются в возвращаемом типе.

0
задан Heretic Monkey 13 July 2018 в 21:39
поделиться

1 ответ

Как упоминалось в комментариях, похоже, что вы хотите получить id выбранного option, а не select. Один из способов получить это - использовать свойство selectedIndex для select в сочетании с его коллекцией options (вы также можете использовать selectedOptions[0] , среди других методов).

Я взял на себя смелость «исправить» некоторые соглашения об именах; как правило, начальные буквы в верхнем регистре обозначают конструктор объекта, а не просто функцию или переменную. Кроме того, используя var (или let или const, в зависимости от необходимости) до назначения переменной, по умолчанию она не становится глобальной переменной. Было сделано несколько других незначительных исправлений, которые я вам отдам.

function showDiv(nameSelect) {

  console.log(nameSelect);
  if (nameSelect) {

    var selectedOption = nameSelect.options[nameSelect.selectedIndex];
    var name = selectedOption.id;
    var splitName = name.split('_');

    console.log(splitName[1]);
    var idOfSection = splitName[0] + '_' + splitName[1];

    var optionValue = selectedOption.value;
    if (optionValue == nameSelect.value) {
      document.getElementById(idOfSection).style.display = "block";
    } else {
      document.getElementById(idOfSection).style.display = "none";
    }
  } else {
    // Commenting this out, since splitName will be undefined in this branch...
    //document.getElementById(splitName[0] + splitName[1]).style.display = "none";
  }
}
<select name="number_of_skids" onchange="showDiv(this);">
  <option value="SHIP WITH" id="SHIPWITH_11_Show">SHIP WITH</option>
  <option value="1">1</option>
  <option value="2" selected="selected">2</option>
</select>

<div id="SHIPWITH_11" style="display: none;">
  <select name="ship_with_product">
    <option value="">SELECT PRODUCT</option>
    <option value="4">1234</option>
  </select>
</div>


<select name="number_of_skids" onchange="showDiv(this);">
  <option value="SHIP WITH" id="SHIPWITH_21_Show">SHIP WITH</option>
  <option value="1">1</option>
  <option value="2" selected="selected">2</option>
</select>

<div id="SHIPWITH_21" style="display: none;">
  <select name="ship_with_product">
    <option value="">SELECT PRODUCT</option>
    <option value="4">1234</option>
  </select>
</div>





<select name="number_of_skids" onchange="showDiv(this);">
  <option value="SHIP WITH" id="SHIPWITH_33_Show">SHIP WITH</option>
  <option value="1">1</option>
  <option value="2" selected="selected">2</option>
</select>

<div id="SHIPWITH_33" style="display: none;">
  <select name="ship_with_product">
    <option value="">SELECT PRODUCT</option>
    <option value="4">1234</option>
  </select>
</div>

1
ответ дан Heretic Monkey 17 August 2018 в 12:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: