Я тоже столкнулся с этой ошибкой.
Моя проблема заключалась в том, что я изменил подпись метода, например
void invest(Currency money){...}
в
void invest(Euro money){...}
Этот метод был вызван из контекста, подобного
public static void main(String args[]) {
Bank myBank = new Bank();
Euro capital = new Euro();
myBank.invest(capital);
}
. Компилятор молчал в отношении предупреждений / ошибок, поскольку капитал - это как валюта, так и евро.
Проблема возникла из-за того, что я только скомпилировал класс, в котором был определен метод - Bank, но не класс, из которого вызывается метод, который содержит метод main ().
Эта проблема не является чем-то, с чем вы можете столкнуться слишком часто, так как чаще всего проект перестраивается вручную или автоматически запускается действие Build, вместо того, чтобы просто компилировать один модифицированный класс.
Мое заявление состояло в том, что я создал .jar, который должен был использоваться как исправление, которое не содержало App.class, поскольку это не было изменено. Мне было разумно не включать его, поскольку я сохранил наследование базового класса исходного аргумента.
Дело в том, что при компиляции класса полученный байт-код является видом static , другими словами, это hard-reference .
Оригинальный дизассемблированный байт-код (сгенерированный с помощью инструмента javap) выглядит следующим образом:
#7 = Methodref #2.#22 // Bank.invest:(LCurrency;)V
После того, как ClassLoader загружает новый скомпилированный Bank.class, он не найдет такого метода, он выглядит так, как будто он был удален и не изменен, поэтому именованная ошибка.
Надеюсь, это поможет.
let
и const
имеют две большие отличия от var
:
var
до его объявления имеет результат undefined
; доступ к let
или const
, прежде чем он будет объявлен бросками ReferenceError
:
console.log(aVar); // undefined
console.log(aLet); // causes ReferenceError: aLet is not defined
var aVar = 1;
let aLet = 2;
примеры, что let
объявления (и const
, которые работают одинаково) могут не быть подняты , так как aLet
не существует, пока ему не присвоено значение.
Это не так, однако let
и const
подняты (например, var
, class
и function
), но есть период между вводом области и объявлением там, где они не могут быть доступны. Этот период является временной мертвой зоной (TDZ).
TDZ заканчивается, когда aLet
объявлен объявлен , а не назначен :
//console.log(aLet) // would throw ReferenceError
let aLet;
console.log(aLet); // undefined
aLet = 10;
console.log(aLet); // 10
Этот пример показывает, что let
поднят:
let x = 'outer value';
(function() {
// start TDZ for x
console.log(x);
let x = 'inner value'; // declaration ends TDZ for x
}());
Кредит: временная мертвая зона (TDZ) demystified
Доступ к x
во внутренней области все еще вызывает ReferenceError
. Если let
не были подняты, он будет записывать outer value
.
TDZ - это хорошо, потому что он помогает выделить ошибки - доступ к значению до того, как он был объявлен, редко преднамерен.
TDZ также применяется к аргументам функции по умолчанию. Аргументы оцениваются слева направо, и каждый аргумент находится в TDZ до тех пор, пока он не назначен:
// b is in TDZ until its value is assigned
function testDefaults(a=b, b) { }
testDefaults(undefined, 1); // throws ReferenceError because the evaluation of a reads b before it has been evaluated.
TDZ не включен по умолчанию в трансляторе babel.js . Включите режим «высокого соответствия», чтобы использовать его в REPL . Поставьте флаг es6.spec.blockScoping
, чтобы использовать его с CLI или в качестве библиотеки.
Рекомендуемое дополнительное чтение: TDZ demystified и ES6 Let, Const и «Temporal Dead» Зона "(TDZ) в глубину .
b is not defined
(как комментарий первого фрагмента кода), но я думаю, что вы изменили имена переменных тем временем (и позже вы напишете об этом) – oliverpool 18 October 2015 в 14:12let foo
в блоке вызывает его подъем и объявление в верхней части этого блока. Строкаlet foo
заставляет ее инициализироваться. Иfoo = xyz
заставляет его присваивать значение. – AJP 4 June 2017 в 01:04