Или создайте массив параметров вручную:
SqlParameter[] parameter = {
new SqlParameter(...),
new SqlParameter(...),
new SqlParameter(...)
};
, Но я не вижу то, что должно быть неправильным с Вашим подходом. Это простой, читаемый и понятный.
Java не поддерживает истинные замыкания , хотя использование анонимного класса, подобного используемому вами здесь ( new TimerTask () {...}
), выглядит как своего рода закрытие.
редактировать - См. комментарии ниже - следующее не является правильным объяснением, как указывает KeeperOfTheSoul.
Вот почему это не работает:
Переменные lastPrice
и price являются локальными переменными в методе main (). Объект, который вы создаете с помощью анонимного класса, может существовать до тех пор, пока метод main ()
не вернется.
Когда метод main ()
вернет результат, локальные переменные (например, ] lastPrice
и price
) будут удалены из стека, поэтому они больше не будут существовать после возврата main ()
.
Но анонимный объект класса ссылается на эти переменные. Все будет ужасно неправильно, если объект анонимного класса попытается получить доступ к переменным после того, как они были очищены.
Сделав lastPrice
и price
final
, они не являются действительно переменных больше, но констант. Затем компилятор может просто заменить использование lastPrice
и price
в анонимном классе значениями констант (конечно, во время компиляции), и у вас не будет проблема с доступом к несуществующим переменным больше.
Другие языки программирования, которые действительно поддерживают замыкания, делают это, специально обрабатывая эти переменные - следя за тем, чтобы они не были уничтожены при завершении метода, чтобы замыкание все еще могло получить доступ к переменным .
@Ankur: Ты мог бы сделать это:
public static void main(String args[]) {
int period = 2000;
int delay = 2000;
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
// Variables as member variables instead of local variables in main()
private double lastPrice = 0;
private Price priceObject = new Price();
private double price = 0;
public void run() {
price = priceObject.getNextPrice(lastPrice);
System.out.println();
lastPrice = price;
}
}, delay, period);
}
Потому что это сбивает с толку, если переменная не является окончательной, поскольку ее изменения не будут учтены в анонимном классе.
Просто сделайте переменные 'price' и 'lastPrice 'final.
- Edit
К сожалению, вам также не нужно назначать их, очевидно, в вашей функции. Вам понадобятся новые локальные переменные. В любом случае, я подозреваю, что кто-то уже дал вам лучший ответ.
Вы можете получить доступ только к конечным переменным из содержащего класса при использовании анонимного класса.
Если переменная должна быть окончательной, не может быть, тогда вы можете присвоить значение переменной другой переменной и сделать ТОЛЬКО окончательным, чтобы вы могли использовать его вместо этого.
Вы не можете ссылаться на незавершенные переменные, потому что так сказано в спецификации языка Java. Начиная с версии 8.1.3:
«Любая локальная переменная, параметр формального метода или параметр обработчика исключений, используемые, но не объявленные во внутреннем классе, должны быть объявлены окончательными». Целый абзац.
Я вижу только часть вашего кода - на мой взгляд, изменение расписания локальных переменных - странная идея. Локальные переменные перестают существовать, когда вы выходите из функции. Может быть, статические поля класса лучше?
Когда я натыкаюсь на эту проблему, я просто передаю объекты внутреннему классу через конструктор. Если мне нужно передать примитивы или неизменяемые объекты (как в этом случае), необходим класс-оболочка.
Изменить: На самом деле я вообще не использую анонимный класс, а использую соответствующий подкласс:
public class PriceData {
private double lastPrice = 0;
private double price = 0;
public void setlastPrice(double lastPrice) {
this.lastPrice = lastPrice;
}
public double getLastPrice() {
return lastPrice;
}
public void setPrice(double price) {
this.price = price;
}
public double getPrice() {
return price;
}
}
public class PriceTimerTask extends TimerTask {
private PriceData priceData;
private Price priceObject;
public PriceTimerTask(PriceData priceData, Price priceObject) {
this.priceData = priceData;
this.priceObject = priceObject;
}
public void run() {
priceData.setPrice(priceObject.getNextPrice(lastPrice));
System.out.println();
priceData.setLastPrice(priceData.getPrice());
}
}
public static void main(String args[]) {
int period = 2000;
int delay = 2000;
PriceData priceData = new PriceData();
Price priceObject = new Price();
Timer timer = new Timer();
timer.scheduleAtFixedRate(new PriceTimerTask(priceData, priceObject), delay, period);
}
Чтобы избежать странных побочных эффектов с замыканиями в java-переменных, на которые ссылается анонимный делегат, они должны быть помечены как окончательные, чтобы ссылаться на lastPrice
и цену в пределах задача таймера, они должны быть помечены как окончательные.
Очевидно, это не сработает для вас, потому что вы хотите их изменить, в этом случае вам следует взглянуть на их инкапсуляцию в класс.
public class Foo {
private PriceObject priceObject;
private double lastPrice;
private double price;
public Foo(PriceObject priceObject) {
this.priceObject = priceObject;
}
public void tick() {
price = priceObject.getNextPrice(lastPrice);
lastPrice = price;
}
}
теперь просто создайте новый Foo как final и вызовите .tick из таймера.
public static void main(String args[]){
int period = 2000;
int delay = 2000;
Price priceObject = new Price();
final Foo foo = new Foo(priceObject);
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
foo.tick();
}
}, delay, period);
}
Хорошие объяснения того, почему вы не можете делать то, что пытаетесь сделать, уже предоставлены. В качестве решения, возможно, рассмотрите:
public class foo
{
static class priceInfo
{
public double lastPrice = 0;
public double price = 0;
public Price priceObject = new Price ();
}
public static void main ( String args[] )
{
int period = 2000;
int delay = 2000;
final priceInfo pi = new priceInfo ();
Timer timer = new Timer ();
timer.scheduleAtFixedRate ( new TimerTask ()
{
public void run ()
{
pi.price = pi.priceObject.getNextPrice ( pi.lastPrice );
System.out.println ();
pi.lastPrice = pi.price;
}
}, delay, period );
}
}
Похоже, что вы могли бы сделать лучший дизайн, чем этот, но идея состоит в том, что вы можете сгруппировать обновленные переменные внутри ссылки на класс, которая не изменяется.
Вы можете получить доступ только к final переменные из содержащего класса при использовании анонимного класса. Поэтому вам необходимо объявить используемые переменные final (это не вариант для вас, поскольку вы меняете lastPrice и price ) или не используйте анонимный класс.
Итак, вы можете создать реальный внутренний класс, в который вы можете передавать переменные и использовать их обычным образом
или:
Существует быстрый (и, на мой взгляд, уродливый) способ взлома вашего lastPrice и price переменная, которая должна объявить это так
final double lastPrice[1];
final double price[1];
, и в вашем анонимном классе вы можете установить значение, подобное этому
price[0] = priceObject.getNextPrice(lastPrice[0]);
System.out.println();
lastPrice[0] = price[0];